diff --git a/digital_doctor/application/api/logic/TychatLogic.php b/digital_doctor/application/api/logic/TychatLogic.php index 08050c3..cf105ce 100644 --- a/digital_doctor/application/api/logic/TychatLogic.php +++ b/digital_doctor/application/api/logic/TychatLogic.php @@ -13,6 +13,7 @@ use app\api\controller\BaseWssApi; use GatewayWorker\Lib\Gateway; use think\Db; use wanghua\general_utility_tools_php\gpt\chat\ChatGPT; +use wanghua\general_utility_tools_php\Mmodel; use wanghua\general_utility_tools_php\tool\Tools; /** @@ -22,25 +23,73 @@ use wanghua\general_utility_tools_php\tool\Tools; */ class TychatLogic extends BaseLogic { + /** + * desc:听译-保存听译聊天记录 + * + * Tyuser/saveChatHistory + * + * author:wh + */ + function saveChatHistory($client_id,$data){ + return Mmodel::catchJson(function ()use ($client_id,$data){ + $action = 'Tyuser/saveChatHistory'; + if(empty($data['items'])){ + $json = Tools::wss_json($action, 'items参数错误'); + return Gateway::sendToClient($client_id, $json); + } + $obj = new TychatLogic(); + if(empty($data['items']['chat_msg'])){ + $json = Tools::wss_json($action, 'chat_msg参数错误'); + return Gateway::sendToClient($client_id, $json); + } + //if(empty($data['items']['username'])){ + // $json = Tools::wss_json($action, 'username参数错误'); + // return Gateway::sendToClient($client_id, $json); + //} + $chat_msg = $data['items']['chat_msg']; + $user = Db::table('fa_ty_users') + ->where('clientid',$client_id) + ->find(); + $username = $user['username']; + //保存记录 + $obj->saveHistory($username,$chat_msg); + + //将消息转发到绑定关系的对方 + //判断用户类型,医生还是病人 + if($user['type']=='doc'){ + //消息发给病人 + $client_id = Db::table('fa_ty_users') + ->where('doctor',$user['username']) + ->value('clientid'); + if(empty($client_id)){ + $json = Tools::wss_json($action, '病人未上线'); + return Gateway::sendToClient($client_id, $json); + } + $json = Tools::wss_json($action, '成功',['chat_msg'=>$chat_msg]); + return Gateway::sendToClient($client_id, $json); + }else{ + //消息发给医生 + $client_id = Db::table('fa_ty_users') + ->where('username',$user['doctor']) + ->value('clientid'); + if(empty($client_id)){ + $json = Tools::wss_json($action, '医生未上线'); + return Gateway::sendToClient($client_id, $json); + } + $json = Tools::wss_json($action, '成功',['chat_msg'=>$chat_msg]); + return Gateway::sendToClient($client_id, $json); + } + }); + } /** * desc:保存听译聊天记录 * - * 注: - * 在websocket 的onMessage中send消息,消息格式如下: - * - * json参数: - * [ - 'action'=>'TychatLogic/saveChatHistory', - 'items'=>[ - 'content'=>'聊天内容', - 'username'=>'用户名',//医生说话就传医生的username,病人说话就传病人的username - ] - ]; */ - function saveChatHistory($chat_content){ + private function saveHistory($username,$chat_content){ $data = [ 'chat_msg'=>$chat_content, + 'username'=>$username, ]; Db::table('fa_ty_chathistory')->insert($data); diff --git a/digital_doctor/application/api/logic/TyuserLogic.php b/digital_doctor/application/api/logic/TyuserLogic.php new file mode 100644 index 0000000..c60ece8 --- /dev/null +++ b/digital_doctor/application/api/logic/TyuserLogic.php @@ -0,0 +1,107 @@ +where('clientid', $client_id) + // ->find(); + // if(empty($user)){ + // Tools::log_to_write_txt(['error:客户端离线,用户不存在:client_id:' . $client_id]); + // return ; + // } + // + // Tools::log_to_write_txt(['写入离线记录:openid:' . $user['openid']]); + // //写入离线记录 + // Db::table(TabConf::$fa_user_offline_record) + // ->insert([ + // 'openid'=>$user['openid'], + // ]); + // + // Tools::log_to_write_txt(['设置离线时间:clientid:' . $client_id]); + // Db::table('fa_ty_users') + // ->where('clientid', $client_id) + // ->data([ + // 'clientid'=>'', + // 'offline_time'=>Tools::get_now_date(),//离线时间 + // ]) + // ->update(); + // + // Tools::log_to_write_txt(['好友列表设置为离线:openid:' . $user['openid']]); + // //好友列表设置为离线 + // Db::table(TabConf::$fa_gamefriend) + // ->data([ + // 'offline_time'=>Tools::get_now_date(),//离线时间 + // ]) + // ->where('friend_openid',$user['openid']) + // ->update(); + // + // Tools::log_to_write_txt(['返回离线消息']); + // + // //在$client_id无效的情况下可能会抛出异常 + // //$json = BaseWssApi::wss_json('ok', '用户已离线'); + // //Gateway::sendToClient($client_id, json_encode($json, JSON_UNESCAPED_UNICODE)); + // }); + //} + + + + + /** + * desc:听译-绑定医患关系,医患客户端初始化后绑定关系 + *请求参数: + * json消息格式:[ + 'action'=>'Tyuser/bindRelation', + 'items'=>[ + 'username'=>'13333322323', + ] + ] + * author:wh + */ + function bindRelation($clientid,$data){ + $action = 'Tyuser/bindRelation'; + if(empty($data['items'])){ + $json = Tools::wss_json($action,'items参数错误'); + return Gateway::sendToClient($clientid, $json); + } + $items = $data['items']; + if(empty($items['username'])){ + $json = Tools::wss_json($action,'username参数错误'); + return Gateway::sendToClient($clientid, $json); + } + Db::table('fa_ty_users') + ->data([ + 'clientid'=>$clientid, + ]) + ->where('username',$items['username']) + ->update(); + + //$json = Tools::wss_json('ok','username参数错误'); + //return Gateway::sendToClient($clientid, $json); + return null; + } +} \ No newline at end of file diff --git a/digital_doctor/application/api/logic/UserLogic.php b/digital_doctor/application/api/logic/UserLogic.php deleted file mode 100644 index 48cd4a5..0000000 --- a/digital_doctor/application/api/logic/UserLogic.php +++ /dev/null @@ -1,125 +0,0 @@ -where('clientid', $client_id) - ->find(); - if(empty($user)){ - Tools::log_to_write_txt(['error:客户端离线,用户不存在:client_id:' . $client_id]); - return ; - } - - Tools::log_to_write_txt(['写入离线记录:openid:' . $user['openid']]); - //写入离线记录 - Db::table(TabConf::$fa_user_offline_record) - ->insert([ - 'openid'=>$user['openid'], - ]); - - Tools::log_to_write_txt(['设置离线时间:clientid:' . $client_id]); - Db::table('fa_ty_users') - ->where('clientid', $client_id) - ->data([ - 'clientid'=>'', - 'offline_time'=>Tools::get_now_date(),//离线时间 - ]) - ->update(); - - Tools::log_to_write_txt(['好友列表设置为离线:openid:' . $user['openid']]); - //好友列表设置为离线 - Db::table(TabConf::$fa_gamefriend) - ->data([ - 'offline_time'=>Tools::get_now_date(),//离线时间 - ]) - ->where('friend_openid',$user['openid']) - ->update(); - - Tools::log_to_write_txt(['返回离线消息']); - - //在$client_id无效的情况下可能会抛出异常 - //$json = BaseWssApi::json_wss('ok', '用户已离线'); - //Gateway::sendToClient($client_id, json_encode($json, JSON_UNESCAPED_UNICODE)); - }); - } - - /** - * desc:听译-保存听译聊天记录 - * - * User/saveChatHistory - * - * author:wh - */ - function saveChatHistory($client_id,$data){ - return Mmodel::catchJson(function ()use ($client_id){ - $obj = new TychatLogic(); - $chat_content = input('chat_content'); - if(empty($chat_content)){ - $json = Tools::json_wss('error', '参数错误'); - Gateway::sendToClient($client_id, $json); - - } - $res = $obj->saveChatHistory($chat_content); - return Tools::set_ok('ok',$res); - }); - } - - - /** - * desc:绑定医患关系,医患客户端初始化后绑定关系 - *请求参数: - * json消息格式:[ - 'action'=>'user/bindRelation', - 'items'=>[ - 'username'=>'13333322323', - ] - ] - * author:wh - */ - function bindRelation($clientid,$data){ - if(empty($data['items'])){ - $json = Tools::json_wss('error','items参数错误'); - return Gateway::sendToClient($clientid, $json); - } - $items = $data['items']; - if(empty($items['username'])){ - $json = Tools::json_wss('error','username参数错误'); - return Gateway::sendToClient($clientid, $json); - } - Db::table('fa_ty_users') - ->data([ - 'clientid'=>$clientid, - ]) - ->where('username',$items['username']) - ->update(); - - //$json = Tools::json_wss('ok','username参数错误'); - //return Gateway::sendToClient($clientid, $json); - return null; - } -} \ No newline at end of file diff --git a/digital_doctor/application/index/logic/events/Events.php b/digital_doctor/application/index/logic/events/Events.php index 8ce88f7..21141c0 100644 --- a/digital_doctor/application/index/logic/events/Events.php +++ b/digital_doctor/application/index/logic/events/Events.php @@ -6,7 +6,6 @@ use app\api\controller\BaseWssApi; use app\api\logic\AudioRevertLogic; use app\api\logic\BaseLogic; use app\api\logic\PartnerOfflineLogic; -use app\api\logic\UserLogic; use app\api\logic\WssMessageLogic; use GatewayWorker\Lib\Gateway; use IFlytek\Xfyun\Speech\LfasrClient; diff --git a/digital_doctor/composer.json b/digital_doctor/composer.json index d311f16..5de7cbe 100644 --- a/digital_doctor/composer.json +++ b/digital_doctor/composer.json @@ -24,13 +24,7 @@ "ext-json": "*", "ext-mbstring": "*", "doing/phpqrcode": "dev-master", - "iflytekop/xfyun-sdk": "^2.0", - "react/socket": "^1.15", - "evenement/evenement": "^3.0", - "cboden/ratchet": "^0.4.4", - "react/event-loop": "^1.5", - "react/http": "^1.10", - "react/promise": "^3.2" + "iflytekop/xfyun-sdk": "^2.0" }, "autoload": { "psr-4": { @@ -49,7 +43,7 @@ "repositories": { "packagist": { "type": "composer", - "url": "https://mirrors.huaweicloud.com/repository/php/" + "url": "https://mirrors.aliyun.com/composer/" } } } diff --git a/digital_doctor/vendor/cboden/ratchet/.github/workflows/ci.yml b/digital_doctor/vendor/cboden/ratchet/.github/workflows/ci.yml deleted file mode 100644 index aa12b68..0000000 --- a/digital_doctor/vendor/cboden/ratchet/.github/workflows/ci.yml +++ /dev/null @@ -1,52 +0,0 @@ -name: "CI" - -on: - pull_request: - push: - branches: - - "master" - schedule: - - cron: "42 3 * * *" - -jobs: - phpunit: - name: "PHPUnit" - runs-on: "ubuntu-20.04" - - strategy: - matrix: - php-version: - - "5.4" - - "5.5" - - "5.6" - - "7.0" - - "7.1" - - "7.2" - - "7.3" - - "7.4" - dependencies: - - "highest" - include: - - dependencies: "lowest" - php-version: "5.4" - - steps: - - name: "Checkout" - uses: "actions/checkout@v2" - with: - fetch-depth: 2 - - - name: "Install PHP" - uses: "shivammathur/setup-php@v2" - with: - php-version: "${{ matrix.php-version }}" - coverage: "none" - ini-values: "zend.assertions=1" - - - name: "Install dependencies with Composer" - uses: "ramsey/composer-install@v1" - with: - dependency-versions: "${{ matrix.dependencies }}" - - - name: "Run PHPUnit" - run: "vendor/bin/phpunit" diff --git a/digital_doctor/vendor/cboden/ratchet/.gitignore b/digital_doctor/vendor/cboden/ratchet/.gitignore deleted file mode 100644 index b9d0923..0000000 --- a/digital_doctor/vendor/cboden/ratchet/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -phpunit.xml -reports -sandbox -vendor -composer.lock \ No newline at end of file diff --git a/digital_doctor/vendor/cboden/ratchet/CHANGELOG.md b/digital_doctor/vendor/cboden/ratchet/CHANGELOG.md deleted file mode 100644 index 316d5dc..0000000 --- a/digital_doctor/vendor/cboden/ratchet/CHANGELOG.md +++ /dev/null @@ -1,150 +0,0 @@ -CHANGELOG -========= - -### Legend - -* "BC": Backwards compatibility break (from public component APIs) -* "BF": Bug fix - ---- - -* 0.4.4 (2021-12-11) - * Correct and update dependencies for forward compatibility - * Added context for React Socket server to App - * Use non-deprecated Guzzle API calls - -* 0.4.3 (2020-06-04) - * BF: Fixed interface acceptable regression in `App` - * Update RFC6455 library with latest fixes - -* 0.4.2 (2020-01-27) - * Support Symfony 5 - * BF: Use phpunit from vendor directory - * Allow disabling of xdebug warning by defining `RATCHET_DISABLE_XDEBUG_WARN` - * Stop using `LoopInterface::tick()` for testing - -* 0.4.1 (2017-12-11) - * Only enableKeepAlive in App if no WsServer passed allowing user to set their own timeout duration - * Support Symfony 4 - * BF: Plug NOOP controller in connection from router in case of misbehaving client - * BF: Raise error from invalid WAMP payload - -* 0.4 (2017-09-14) - * BC: $conn->WebSocket->request replaced with $conn->httpRequest which is a PSR-7 object - * Binary messages now supported via Ratchet\WebSocket\MessageComponentInterface - * Added heartbeat support via ping/pong in WsServer - * BC: No longer support old (and insecure) Hixie76 and Hybi protocols - * BC: No longer support disabling UTF-8 checks - * BC: The Session component implements HttpServerInterface instead of WsServerInterface - * BC: PHP 5.3 no longer supported - * BC: Update to newer version of react/socket dependency - * BC: WAMP topics reduced to 0 subscriptions are deleted, new subs to same name will result in new Topic instance - * Significant performance enhancements - -* 0.3.6 (2017-01-06) - * BF: Keep host and scheme in HTTP request object attatched to connection - * BF: Return correct HTTP response (405) when non-GET request made - -* 0.3.5 (2016-05-25) - * BF: Unmask responding close frame - * Added write handler for PHP session serializer - -* 0.3.4 (2015-12-23) - * BF: Edge case where version check wasn't run on message coalesce - * BF: Session didn't start when using pdo_sqlite - * BF: WAMP currie prefix check when using '#' - * Compatibility with Symfony 3 - -* 0.3.3 (2015-05-26) - * BF: Framing bug on large messages upon TCP fragmentation - * BF: Symfony Router query parameter defaults applied to Request - * BF: WAMP CURIE on all URIs - * OriginCheck rules applied to FlashPolicy - * Switched from PSR-0 to PSR-4 - -* 0.3.2 (2014-06-08) - * BF: No messages after closing handshake (fixed rare race condition causing 100% CPU) - * BF: Fixed accidental BC break from v0.3.1 - * Added autoDelete parameter to Topic to destroy when empty of connections - * Exposed React Socket on IoServer (allowing FlashPolicy shutdown in App) - * Normalized Exceptions in WAMP - -* 0.3.1 (2014-05-26) - * Added query parameter support to Router, set in HTTP request (ws://server?hello=world) - * HHVM compatibility - * BF: React/0.4 support; CPU starvation bug fixes - * BF: Allow App::route to ignore Host header - * Added expected filters to WAMP Topic broadcast method - * Resource cleanup in WAMP TopicManager - -* 0.3.0 (2013-10-14) - * Added the `App` class to help making Ratchet so easy to use it's silly - * BC: Require hostname to do HTTP Host header match and do Origin HTTP header check, verify same name by default, helping prevent CSRF attacks - * Added Symfony/2.2 based HTTP Router component to allowing for a single Ratchet server to handle multiple apps -> Ratchet\Http\Router - * BC: Decoupled HTTP from WebSocket component -> Ratchet\Http\HttpServer - * BF: Single sub-protocol selection to conform with RFC6455 - * BF: Sanity checks on WAMP protocol to prevent errors - -* 0.2.8 (2013-09-19) - * React 0.3 support - -* 0.2.7 (2013-06-09) - * BF: Sub-protocol negotation with Guzzle 3.6 - -* 0.2.6 (2013-06-01) - * Guzzle 3.6 support - -* 0.2.5 (2013-04-01) - * Fixed Hixie-76 handshake bug - -* 0.2.4 (2013-03-09) - * Support for Symfony 2.2 and Guzzle 2.3 - * Minor bug fixes when handling errors - -* 0.2.3 (2012-11-21) - * Bumped dep: Guzzle to v3, React to v0.2.4 - * More tests - -* 0.2.2 (2012-10-20) - * Bumped deps to use React v0.2 - -* 0.2.1 (2012-10-13) - * BF: No more UTF-8 warnings in browsers (no longer sending empty sub-protocol string) - * Documentation corrections - * Using new composer structure - -* 0.2 (2012-09-07) - * Ratchet passes every non-binary-frame test from the Autobahn Testsuite - * Major performance improvements - * BC: Renamed "WampServer" to "ServerProtocol" - * BC: New "WampServer" component passes Topic container objects of subscribed Connections - * Option to turn off UTF-8 checks in order to increase performance - * Switched dependency guzzle/guzzle to guzzle/http (no API changes) - * mbstring no longer required - -* 0.1.5 (2012-07-12) - * BF: Error where service wouldn't run on PHP <= 5.3.8 - * Dependency library updates - -* 0.1.4 (2012-06-17) - * Fixed dozens of failing AB tests - * BF: Proper socket buffer handling - -* 0.1.3 (2012-06-15) - * Major refactor inside WebSocket protocol handling, more loosley coupled - * BF: Proper error handling on failed WebSocket connections - * BF: Handle TCP message concatenation - * Inclusion of the AutobahnTestSuite checking WebSocket protocol compliance - * mb_string now a requirement - -* 0.1.2 (2012-05-19) - * BC/BF: Updated WAMP API to coincide with the official spec - * Tweaks to improve running as a long lived process - -* 0.1.1 (2012-05-14) - * Separated interfaces allowing WebSockets to support multiple sub protocols - * BF: remoteAddress variable on connections returns proper value - -* 0.1 (2012-05-11) - * First release with components: IoServer, WsServer, SessionProvider, WampServer, FlashPolicy, IpBlackList - * I/O now handled by React, making Ratchet fully asynchronous diff --git a/digital_doctor/vendor/cboden/ratchet/LICENSE b/digital_doctor/vendor/cboden/ratchet/LICENSE deleted file mode 100644 index 52b4aef..0000000 --- a/digital_doctor/vendor/cboden/ratchet/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2011 Chris Boden - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/digital_doctor/vendor/cboden/ratchet/Makefile b/digital_doctor/vendor/cboden/ratchet/Makefile deleted file mode 100644 index 8054867..0000000 --- a/digital_doctor/vendor/cboden/ratchet/Makefile +++ /dev/null @@ -1,42 +0,0 @@ -# This file is intended to ease the author's development and testing process -# Users do not need to use `make`; Ratchet does not need to be compiled - -test: - vendor/bin/phpunit - -cover: - vendor/bin/phpunit --coverage-text --coverage-html=reports/coverage - -abtests: - ulimit -n 2048 && php tests/autobahn/bin/fuzzingserver.php 8001 LibEvent & - ulimit -n 2048 && php tests/autobahn/bin/fuzzingserver.php 8002 StreamSelect & - ulimit -n 2048 && php tests/autobahn/bin/fuzzingserver.php 8004 LibEv & - wstest -m testeeserver -w ws://localhost:8000 & - sleep 1 - wstest -m fuzzingclient -s tests/autobahn/fuzzingclient-all.json - killall php wstest - -abtest: - ulimit -n 2048 && php tests/autobahn/bin/fuzzingserver.php 8000 StreamSelect & - sleep 1 - wstest -m fuzzingclient -s tests/autobahn/fuzzingclient-quick.json - killall php - -profile: - php -d 'xdebug.profiler_enable=1' tests/autobahn/bin/fuzzingserver.php 8000 LibEvent & - sleep 1 - wstest -m fuzzingclient -s tests/autobahn/fuzzingclient-profile.json - killall php - -apidocs: - apigen --title Ratchet -d reports/api \ - -s src/ \ - -s vendor/ratchet/rfc6455/src \ - -s vendor/react/event-loop/src \ - -s vendor/react/socket/src \ - -s vendor/react/stream/src \ - -s vendor/psr/http-message/src \ - -s vendor/symfony/http-foundation/Session \ - -s vendor/symfony/routing \ - -s vendor/evenement/evenement/src/Evenement \ - --exclude=vendor/symfony/routing/Tests \ diff --git a/digital_doctor/vendor/cboden/ratchet/README.md b/digital_doctor/vendor/cboden/ratchet/README.md deleted file mode 100644 index 462f42c..0000000 --- a/digital_doctor/vendor/cboden/ratchet/README.md +++ /dev/null @@ -1,87 +0,0 @@ -# Ratchet - -[![GitHub Actions][GA Image]][GA Link] -[![Autobahn Testsuite](https://img.shields.io/badge/Autobahn-passing-brightgreen.svg)](http://socketo.me/reports/ab/index.html) -[![Latest Stable Version](https://poser.pugx.org/cboden/ratchet/v/stable.png)](https://packagist.org/packages/cboden/ratchet) - -A PHP library for asynchronously serving WebSockets. -Build up your application through simple interfaces and re-use your application without changing any of its code just by combining different components. - -## Requirements - -Shell access is required and root access is recommended. -To avoid proxy/firewall blockage it's recommended WebSockets are requested on port 80 or 443 (SSL), which requires root access. -In order to do this, along with your sync web stack, you can either use a reverse proxy or two separate machines. -You can find more details in the [server conf docs](http://socketo.me/docs/deploy#server_configuration). - -### Documentation - -User and API documentation is available on Ratchet's website: http://socketo.me - -See https://github.com/cboden/Ratchet-examples for some out-of-the-box working demos using Ratchet. - -Need help? Have a question? Want to provide feedback? Write a message on the [Google Groups Mailing List](https://groups.google.com/forum/#!forum/ratchet-php). - ---- - -### A quick example - -```php -clients = new \SplObjectStorage; - } - - public function onOpen(ConnectionInterface $conn) { - $this->clients->attach($conn); - } - - public function onMessage(ConnectionInterface $from, $msg) { - foreach ($this->clients as $client) { - if ($from != $client) { - $client->send($msg); - } - } - } - - public function onClose(ConnectionInterface $conn) { - $this->clients->detach($conn); - } - - public function onError(ConnectionInterface $conn, \Exception $e) { - $conn->close(); - } -} - - // Run the server application through the WebSocket protocol on port 8080 - $app = new Ratchet\App('localhost', 8080); - $app->route('/chat', new MyChat, array('*')); - $app->route('/echo', new Ratchet\Server\EchoServer, array('*')); - $app->run(); -``` - - $ php chat.php - -```javascript - // Then some JavaScript in the browser: - var conn = new WebSocket('ws://localhost:8080/echo'); - conn.onmessage = function(e) { console.log(e.data); }; - conn.onopen = function(e) { conn.send('Hello Me!'); }; -``` - -[GA Image]: https://github.com/ratchetphp/Ratchet/workflows/CI/badge.svg - -[GA Link]: https://github.com/ratchetphp/Ratchet/actions?query=workflow%3A%22CI%22+branch%3Amaster diff --git a/digital_doctor/vendor/cboden/ratchet/SECURITY.md b/digital_doctor/vendor/cboden/ratchet/SECURITY.md deleted file mode 100644 index 45e2cf5..0000000 --- a/digital_doctor/vendor/cboden/ratchet/SECURITY.md +++ /dev/null @@ -1,8 +0,0 @@ -# Security Policy - -## Reporting a Vulnerability - -Please report security issues to: - -* Chris Boden [cboden@gmail.com](cboden@gmail.com) -* Matt Bonneau [matt@bonneau.net](matt@bonneau.net) diff --git a/digital_doctor/vendor/cboden/ratchet/composer.json b/digital_doctor/vendor/cboden/ratchet/composer.json deleted file mode 100644 index 1dffae6..0000000 --- a/digital_doctor/vendor/cboden/ratchet/composer.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "name": "cboden/ratchet" - , "type": "library" - , "description": "PHP WebSocket library" - , "keywords": ["WebSockets", "Server", "Ratchet", "Sockets", "WebSocket"] - , "homepage": "http://socketo.me" - , "license": "MIT" - , "authors": [ - { - "name": "Chris Boden" - , "email": "cboden@gmail.com" - , "role": "Developer" - } - , { - "name": "Matt Bonneau" - , "role": "Developer" - } - ] - , "support": { - "issues": "https://github.com/ratchetphp/Ratchet/issues" - , "chat": "https://gitter.im/reactphp/reactphp" - } - , "autoload": { - "psr-4": { - "Ratchet\\": "src/Ratchet" - } - } - , "require": { - "php": ">=5.4.2" - , "ratchet/rfc6455": "^0.3.1" - , "react/socket": "^1.0 || ^0.8 || ^0.7 || ^0.6 || ^0.5" - , "react/event-loop": ">=0.4" - , "guzzlehttp/psr7": "^1.7|^2.0" - , "symfony/http-foundation": "^2.6|^3.0|^4.0|^5.0|^6.0" - , "symfony/routing": "^2.6|^3.0|^4.0|^5.0|^6.0" - } - , "require-dev": { - "phpunit/phpunit": "~4.8" - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/phpunit.xml.dist b/digital_doctor/vendor/cboden/ratchet/phpunit.xml.dist deleted file mode 100644 index 0cc5451..0000000 --- a/digital_doctor/vendor/cboden/ratchet/phpunit.xml.dist +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - ./tests/unit/ - - - - - - ./tests/integration/ - - - - - - ./src/ - - - \ No newline at end of file diff --git a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/AbstractConnectionDecorator.php b/digital_doctor/vendor/cboden/ratchet/src/Ratchet/AbstractConnectionDecorator.php deleted file mode 100644 index 9707951..0000000 --- a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/AbstractConnectionDecorator.php +++ /dev/null @@ -1,41 +0,0 @@ -wrappedConn = $conn; - } - - /** - * @return ConnectionInterface - */ - protected function getConnection() { - return $this->wrappedConn; - } - - public function __set($name, $value) { - $this->wrappedConn->$name = $value; - } - - public function __get($name) { - return $this->wrappedConn->$name; - } - - public function __isset($name) { - return isset($this->wrappedConn->$name); - } - - public function __unset($name) { - unset($this->wrappedConn->$name); - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/App.php b/digital_doctor/vendor/cboden/ratchet/src/Ratchet/App.php deleted file mode 100644 index d3de200..0000000 --- a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/App.php +++ /dev/null @@ -1,147 +0,0 @@ -httpHost = $httpHost; - $this->port = $port; - - $socket = new Reactor($address . ':' . $port, $loop, $context); - - $this->routes = new RouteCollection; - $this->_server = new IoServer(new HttpServer(new Router(new UrlMatcher($this->routes, new RequestContext))), $socket, $loop); - - $policy = new FlashPolicy; - $policy->addAllowedAccess($httpHost, 80); - $policy->addAllowedAccess($httpHost, $port); - - if (80 == $port) { - $flashUri = '0.0.0.0:843'; - } else { - $flashUri = 8843; - } - $flashSock = new Reactor($flashUri, $loop); - $this->flashServer = new IoServer($policy, $flashSock); - } - - /** - * Add an endpoint/application to the server - * @param string $path The URI the client will connect to - * @param ComponentInterface $controller Your application to server for the route. If not specified, assumed to be for a WebSocket - * @param array $allowedOrigins An array of hosts allowed to connect (same host by default), ['*'] for any - * @param string $httpHost Override the $httpHost variable provided in the __construct - * @return ComponentInterface|WsServer - */ - public function route($path, ComponentInterface $controller, array $allowedOrigins = array(), $httpHost = null) { - if ($controller instanceof HttpServerInterface || $controller instanceof WsServer) { - $decorated = $controller; - } elseif ($controller instanceof WampServerInterface) { - $decorated = new WsServer(new WampServer($controller)); - $decorated->enableKeepAlive($this->_server->loop); - } elseif ($controller instanceof MessageComponentInterface || $controller instanceof WsMessageComponentInterface) { - $decorated = new WsServer($controller); - $decorated->enableKeepAlive($this->_server->loop); - } else { - $decorated = $controller; - } - - if ($httpHost === null) { - $httpHost = $this->httpHost; - } - - $allowedOrigins = array_values($allowedOrigins); - if (0 === count($allowedOrigins)) { - $allowedOrigins[] = $httpHost; - } - if ('*' !== $allowedOrigins[0]) { - $decorated = new OriginCheck($decorated, $allowedOrigins); - } - - //allow origins in flash policy server - if(empty($this->flashServer) === false) { - foreach($allowedOrigins as $allowedOrgin) { - $this->flashServer->app->addAllowedAccess($allowedOrgin, $this->port); - } - } - - $this->routes->add('rr-' . ++$this->_routeCounter, new Route($path, array('_controller' => $decorated), array('Origin' => $this->httpHost), array(), $httpHost, array(), array('GET'))); - - return $decorated; - } - - /** - * Run the server by entering the event loop - */ - public function run() { - $this->_server->run(); - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/ComponentInterface.php b/digital_doctor/vendor/cboden/ratchet/src/Ratchet/ComponentInterface.php deleted file mode 100644 index 37e41b1..0000000 --- a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/ComponentInterface.php +++ /dev/null @@ -1,31 +0,0 @@ - \Ratchet\VERSION - ], $additional_headers)); - - $conn->send(Message::toString($response)); - $conn->close(); - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Http/HttpRequestParser.php b/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Http/HttpRequestParser.php deleted file mode 100644 index 5043c28..0000000 --- a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Http/HttpRequestParser.php +++ /dev/null @@ -1,64 +0,0 @@ -httpBuffer)) { - $context->httpBuffer = ''; - } - - $context->httpBuffer .= $data; - - if (strlen($context->httpBuffer) > (int)$this->maxSize) { - throw new \OverflowException("Maximum buffer size of {$this->maxSize} exceeded parsing HTTP header"); - } - - if ($this->isEom($context->httpBuffer)) { - $request = $this->parse($context->httpBuffer); - - unset($context->httpBuffer); - - return $request; - } - } - - /** - * Determine if the message has been buffered as per the HTTP specification - * @param string $message - * @return boolean - */ - public function isEom($message) { - return (boolean)strpos($message, static::EOM); - } - - /** - * @param string $headers - * @return \Psr\Http\Message\RequestInterface - */ - public function parse($headers) { - return Message::parseRequest($headers); - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Http/HttpServer.php b/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Http/HttpServer.php deleted file mode 100644 index bbd8d53..0000000 --- a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Http/HttpServer.php +++ /dev/null @@ -1,76 +0,0 @@ -_httpServer = $component; - $this->_reqParser = new HttpRequestParser; - } - - /** - * {@inheritdoc} - */ - public function onOpen(ConnectionInterface $conn) { - $conn->httpHeadersReceived = false; - } - - /** - * {@inheritdoc} - */ - public function onMessage(ConnectionInterface $from, $msg) { - if (true !== $from->httpHeadersReceived) { - try { - if (null === ($request = $this->_reqParser->onMessage($from, $msg))) { - return; - } - } catch (\OverflowException $oe) { - return $this->close($from, 413); - } - - $from->httpHeadersReceived = true; - - return $this->_httpServer->onOpen($from, $request); - } - - $this->_httpServer->onMessage($from, $msg); - } - - /** - * {@inheritdoc} - */ - public function onClose(ConnectionInterface $conn) { - if ($conn->httpHeadersReceived) { - $this->_httpServer->onClose($conn); - } - } - - /** - * {@inheritdoc} - */ - public function onError(ConnectionInterface $conn, \Exception $e) { - if ($conn->httpHeadersReceived) { - $this->_httpServer->onError($conn, $e); - } else { - $this->close($conn, 500); - } - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Http/HttpServerInterface.php b/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Http/HttpServerInterface.php deleted file mode 100644 index 2c37c49..0000000 --- a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Http/HttpServerInterface.php +++ /dev/null @@ -1,14 +0,0 @@ -_component = $component; - $this->allowedOrigins += $allowed; - } - - /** - * {@inheritdoc} - */ - public function onOpen(ConnectionInterface $conn, RequestInterface $request = null) { - $header = (string)$request->getHeader('Origin')[0]; - $origin = parse_url($header, PHP_URL_HOST) ?: $header; - - if (!in_array($origin, $this->allowedOrigins)) { - return $this->close($conn, 403); - } - - return $this->_component->onOpen($conn, $request); - } - - /** - * {@inheritdoc} - */ - function onMessage(ConnectionInterface $from, $msg) { - return $this->_component->onMessage($from, $msg); - } - - /** - * {@inheritdoc} - */ - function onClose(ConnectionInterface $conn) { - return $this->_component->onClose($conn); - } - - /** - * {@inheritdoc} - */ - function onError(ConnectionInterface $conn, \Exception $e) { - return $this->_component->onError($conn, $e); - } -} \ No newline at end of file diff --git a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Http/Router.php b/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Http/Router.php deleted file mode 100644 index 2bd5942..0000000 --- a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Http/Router.php +++ /dev/null @@ -1,96 +0,0 @@ -_matcher = $matcher; - $this->_noopController = new NoOpHttpServerController; - } - - /** - * {@inheritdoc} - * @throws \UnexpectedValueException If a controller is not \Ratchet\Http\HttpServerInterface - */ - public function onOpen(ConnectionInterface $conn, RequestInterface $request = null) { - if (null === $request) { - throw new \UnexpectedValueException('$request can not be null'); - } - - $conn->controller = $this->_noopController; - - $uri = $request->getUri(); - - $context = $this->_matcher->getContext(); - $context->setMethod($request->getMethod()); - $context->setHost($uri->getHost()); - - try { - $route = $this->_matcher->match($uri->getPath()); - } catch (MethodNotAllowedException $nae) { - return $this->close($conn, 405, array('Allow' => $nae->getAllowedMethods())); - } catch (ResourceNotFoundException $nfe) { - return $this->close($conn, 404); - } - - if (is_string($route['_controller']) && class_exists($route['_controller'])) { - $route['_controller'] = new $route['_controller']; - } - - if (!($route['_controller'] instanceof HttpServerInterface)) { - throw new \UnexpectedValueException('All routes must implement Ratchet\Http\HttpServerInterface'); - } - - $parameters = []; - foreach($route as $key => $value) { - if ((is_string($key)) && ('_' !== substr($key, 0, 1))) { - $parameters[$key] = $value; - } - } - $parameters = array_merge($parameters, Query::parse($uri->getQuery() ?: '')); - - $request = $request->withUri($uri->withQuery(Query::build($parameters))); - - $conn->controller = $route['_controller']; - $conn->controller->onOpen($conn, $request); - } - - /** - * {@inheritdoc} - */ - public function onMessage(ConnectionInterface $from, $msg) { - $from->controller->onMessage($from, $msg); - } - - /** - * {@inheritdoc} - */ - public function onClose(ConnectionInterface $conn) { - if (isset($conn->controller)) { - $conn->controller->onClose($conn); - } - } - - /** - * {@inheritdoc} - */ - public function onError(ConnectionInterface $conn, \Exception $e) { - if (isset($conn->controller)) { - $conn->controller->onError($conn, $e); - } - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/MessageComponentInterface.php b/digital_doctor/vendor/cboden/ratchet/src/Ratchet/MessageComponentInterface.php deleted file mode 100644 index b4a92e2..0000000 --- a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/MessageComponentInterface.php +++ /dev/null @@ -1,5 +0,0 @@ -send($msg); - } - - public function onClose(ConnectionInterface $conn) { - } - - public function onError(ConnectionInterface $conn, \Exception $e) { - $conn->close(); - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Server/FlashPolicy.php b/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Server/FlashPolicy.php deleted file mode 100644 index 4a1b8bd..0000000 --- a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Server/FlashPolicy.php +++ /dev/null @@ -1,200 +0,0 @@ -'; - - /** - * Stores an array of allowed domains and their ports - * @var array - */ - protected $_access = array(); - - /** - * @var string - */ - protected $_siteControl = ''; - - /** - * @var string - */ - protected $_cache = ''; - - /** - * @var string - */ - protected $_cacheValid = false; - - /** - * Add a domain to an allowed access list. - * - * @param string $domain Specifies a requesting domain to be granted access. Both named domains and IP - * addresses are acceptable values. Subdomains are considered different domains. A wildcard (*) can - * be used to match all domains when used alone, or multiple domains (subdomains) when used as a - * prefix for an explicit, second-level domain name separated with a dot (.) - * @param string $ports A comma-separated list of ports or range of ports that a socket connection - * is allowed to connect to. A range of ports is specified through a dash (-) between two port numbers. - * Ranges can be used with individual ports when separated with a comma. A single wildcard (*) can - * be used to allow all ports. - * @param bool $secure - * @throws \UnexpectedValueException - * @return FlashPolicy - */ - public function addAllowedAccess($domain, $ports = '*', $secure = false) { - if (!$this->validateDomain($domain)) { - throw new \UnexpectedValueException('Invalid domain'); - } - - if (!$this->validatePorts($ports)) { - throw new \UnexpectedValueException('Invalid Port'); - } - - $this->_access[] = array($domain, $ports, (boolean)$secure); - $this->_cacheValid = false; - - return $this; - } - - /** - * Removes all domains from the allowed access list. - * - * @return \Ratchet\Server\FlashPolicy - */ - public function clearAllowedAccess() { - $this->_access = array(); - $this->_cacheValid = false; - - return $this; - } - - /** - * site-control defines the meta-policy for the current domain. A meta-policy specifies acceptable - * domain policy files other than the master policy file located in the target domain's root and named - * crossdomain.xml. - * - * @param string $permittedCrossDomainPolicies - * @throws \UnexpectedValueException - * @return FlashPolicy - */ - public function setSiteControl($permittedCrossDomainPolicies = 'all') { - if (!$this->validateSiteControl($permittedCrossDomainPolicies)) { - throw new \UnexpectedValueException('Invalid site control set'); - } - - $this->_siteControl = $permittedCrossDomainPolicies; - $this->_cacheValid = false; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function onOpen(ConnectionInterface $conn) { - } - - /** - * {@inheritdoc} - */ - public function onMessage(ConnectionInterface $from, $msg) { - if (!$this->_cacheValid) { - $this->_cache = $this->renderPolicy()->asXML(); - $this->_cacheValid = true; - } - - $from->send($this->_cache . "\0"); - $from->close(); - } - - /** - * {@inheritdoc} - */ - public function onClose(ConnectionInterface $conn) { - } - - /** - * {@inheritdoc} - */ - public function onError(ConnectionInterface $conn, \Exception $e) { - $conn->close(); - } - - /** - * Builds the crossdomain file based on the template policy - * - * @throws \UnexpectedValueException - * @return \SimpleXMLElement - */ - public function renderPolicy() { - $policy = new \SimpleXMLElement($this->_policy); - - $siteControl = $policy->addChild('site-control'); - - if ($this->_siteControl == '') { - $this->setSiteControl(); - } - - $siteControl->addAttribute('permitted-cross-domain-policies', $this->_siteControl); - - if (empty($this->_access)) { - throw new \UnexpectedValueException('You must add a domain through addAllowedAccess()'); - } - - foreach ($this->_access as $access) { - $tmp = $policy->addChild('allow-access-from'); - $tmp->addAttribute('domain', $access[0]); - $tmp->addAttribute('to-ports', $access[1]); - $tmp->addAttribute('secure', ($access[2] === true) ? 'true' : 'false'); - } - - return $policy; - } - - /** - * Make sure the proper site control was passed - * - * @param string $permittedCrossDomainPolicies - * @return bool - */ - public function validateSiteControl($permittedCrossDomainPolicies) { - //'by-content-type' and 'by-ftp-filename' are not available for sockets - return (bool)in_array($permittedCrossDomainPolicies, array('none', 'master-only', 'all')); - } - - /** - * Validate for proper domains (wildcards allowed) - * - * @param string $domain - * @return bool - */ - public function validateDomain($domain) { - return (bool)preg_match("/^((http(s)?:\/\/)?([a-z0-9-_]+\.|\*\.)*([a-z0-9-_\.]+)|\*)$/i", $domain); - } - - /** - * Make sure valid ports were passed - * - * @param string $port - * @return bool - */ - public function validatePorts($port) { - return (bool)preg_match('/^(\*|(\d+[,-]?)*\d+)$/', $port); - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Server/IoConnection.php b/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Server/IoConnection.php deleted file mode 100644 index 9f864bb..0000000 --- a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Server/IoConnection.php +++ /dev/null @@ -1,38 +0,0 @@ -conn = $conn; - } - - /** - * {@inheritdoc} - */ - public function send($data) { - $this->conn->write($data); - - return $this; - } - - /** - * {@inheritdoc} - */ - public function close() { - $this->conn->end(); - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Server/IoServer.php b/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Server/IoServer.php deleted file mode 100644 index b3fb7e0..0000000 --- a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Server/IoServer.php +++ /dev/null @@ -1,140 +0,0 @@ -loop = $loop; - $this->app = $app; - $this->socket = $socket; - - $socket->on('connection', array($this, 'handleConnect')); - } - - /** - * @param \Ratchet\MessageComponentInterface $component The application that I/O will call when events are received - * @param int $port The port to server sockets on - * @param string $address The address to receive sockets on (0.0.0.0 means receive connections from any) - * @return IoServer - */ - public static function factory(MessageComponentInterface $component, $port = 80, $address = '0.0.0.0') { - $loop = LoopFactory::create(); - $socket = new Reactor($address . ':' . $port, $loop); - - return new static($component, $socket, $loop); - } - - /** - * Run the application by entering the event loop - * @throws \RuntimeException If a loop was not previously specified - */ - public function run() { - if (null === $this->loop) { - throw new \RuntimeException("A React Loop was not provided during instantiation"); - } - - // @codeCoverageIgnoreStart - $this->loop->run(); - // @codeCoverageIgnoreEnd - } - - /** - * Triggered when a new connection is received from React - * @param \React\Socket\ConnectionInterface $conn - */ - public function handleConnect($conn) { - $conn->decor = new IoConnection($conn); - $conn->decor->resourceId = (int)$conn->stream; - - $uri = $conn->getRemoteAddress(); - $conn->decor->remoteAddress = trim( - parse_url((strpos($uri, '://') === false ? 'tcp://' : '') . $uri, PHP_URL_HOST), - '[]' - ); - - $this->app->onOpen($conn->decor); - - $conn->on('data', function ($data) use ($conn) { - $this->handleData($data, $conn); - }); - $conn->on('close', function () use ($conn) { - $this->handleEnd($conn); - }); - $conn->on('error', function (\Exception $e) use ($conn) { - $this->handleError($e, $conn); - }); - } - - /** - * Data has been received from React - * @param string $data - * @param \React\Socket\ConnectionInterface $conn - */ - public function handleData($data, $conn) { - try { - $this->app->onMessage($conn->decor, $data); - } catch (\Exception $e) { - $this->handleError($e, $conn); - } - } - - /** - * A connection has been closed by React - * @param \React\Socket\ConnectionInterface $conn - */ - public function handleEnd($conn) { - try { - $this->app->onClose($conn->decor); - } catch (\Exception $e) { - $this->handleError($e, $conn); - } - - unset($conn->decor); - } - - /** - * An error has occurred, let the listening application know - * @param \Exception $e - * @param \React\Socket\ConnectionInterface $conn - */ - public function handleError(\Exception $e, $conn) { - $this->app->onError($conn->decor, $e); - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Server/IpBlackList.php b/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Server/IpBlackList.php deleted file mode 100644 index 9342254..0000000 --- a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Server/IpBlackList.php +++ /dev/null @@ -1,111 +0,0 @@ -_decorating = $component; - } - - /** - * Add an address to the blacklist that will not be allowed to connect to your application - * @param string $ip IP address to block from connecting to your application - * @return IpBlackList - */ - public function blockAddress($ip) { - $this->_blacklist[$ip] = true; - - return $this; - } - - /** - * Unblock an address so they can access your application again - * @param string $ip IP address to unblock from connecting to your application - * @return IpBlackList - */ - public function unblockAddress($ip) { - if (isset($this->_blacklist[$this->filterAddress($ip)])) { - unset($this->_blacklist[$this->filterAddress($ip)]); - } - - return $this; - } - - /** - * @param string $address - * @return bool - */ - public function isBlocked($address) { - return (isset($this->_blacklist[$this->filterAddress($address)])); - } - - /** - * Get an array of all the addresses blocked - * @return array - */ - public function getBlockedAddresses() { - return array_keys($this->_blacklist); - } - - /** - * @param string $address - * @return string - */ - public function filterAddress($address) { - if (strstr($address, ':') && substr_count($address, '.') == 3) { - list($address, $port) = explode(':', $address); - } - - return $address; - } - - /** - * {@inheritdoc} - */ - function onOpen(ConnectionInterface $conn) { - if ($this->isBlocked($conn->remoteAddress)) { - return $conn->close(); - } - - return $this->_decorating->onOpen($conn); - } - - /** - * {@inheritdoc} - */ - function onMessage(ConnectionInterface $from, $msg) { - return $this->_decorating->onMessage($from, $msg); - } - - /** - * {@inheritdoc} - */ - function onClose(ConnectionInterface $conn) { - if (!$this->isBlocked($conn->remoteAddress)) { - $this->_decorating->onClose($conn); - } - } - - /** - * {@inheritdoc} - */ - function onError(ConnectionInterface $conn, \Exception $e) { - if (!$this->isBlocked($conn->remoteAddress)) { - $this->_decorating->onError($conn, $e); - } - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Session/Serialize/HandlerInterface.php b/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Session/Serialize/HandlerInterface.php deleted file mode 100644 index b83635f..0000000 --- a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Session/Serialize/HandlerInterface.php +++ /dev/null @@ -1,16 +0,0 @@ - $bucketData) { - $preSerialized[] = $bucket . '|' . serialize($bucketData); - } - $serialized = implode('', $preSerialized); - } - - return $serialized; - } - - /** - * {@inheritdoc} - * @link http://ca2.php.net/manual/en/function.session-decode.php#108037 Code from this comment on php.net - * @throws \UnexpectedValueException If there is a problem parsing the data - */ - public function unserialize($raw) { - $returnData = array(); - $offset = 0; - - while ($offset < strlen($raw)) { - if (!strstr(substr($raw, $offset), "|")) { - throw new \UnexpectedValueException("invalid data, remaining: " . substr($raw, $offset)); - } - - $pos = strpos($raw, "|", $offset); - $num = $pos - $offset; - $varname = substr($raw, $offset, $num); - $offset += $num + 1; - $data = unserialize(substr($raw, $offset)); - - $returnData[$varname] = $data; - $offset += strlen(serialize($data)); - } - - return $returnData; - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Session/SessionProvider.php b/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Session/SessionProvider.php deleted file mode 100644 index 44276c5..0000000 --- a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Session/SessionProvider.php +++ /dev/null @@ -1,243 +0,0 @@ -_app = $app; - $this->_handler = $handler; - $this->_null = new NullSessionHandler; - - ini_set('session.auto_start', 0); - ini_set('session.cache_limiter', ''); - ini_set('session.use_cookies', 0); - - $this->setOptions($options); - - if (null === $serializer) { - $serialClass = __NAMESPACE__ . "\\Serialize\\{$this->toClassCase(ini_get('session.serialize_handler'))}Handler"; // awesome/terrible hack, eh? - if (!class_exists($serialClass)) { - throw new \RuntimeException('Unable to parse session serialize handler'); - } - - $serializer = new $serialClass; - } - - $this->_serializer = $serializer; - } - - /** - * {@inheritdoc} - */ - public function onOpen(ConnectionInterface $conn, RequestInterface $request = null) { - $sessionName = ini_get('session.name'); - - $id = array_reduce($request->getHeader('Cookie'), function($accumulator, $cookie) use ($sessionName) { - if ($accumulator) { - return $accumulator; - } - - $crumbs = $this->parseCookie($cookie); - - return isset($crumbs['cookies'][$sessionName]) ? $crumbs['cookies'][$sessionName] : false; - }, false); - - if (null === $request || false === $id) { - $saveHandler = $this->_null; - $id = ''; - } else { - $saveHandler = $this->_handler; - } - - $conn->Session = new Session(new VirtualSessionStorage($saveHandler, $id, $this->_serializer)); - - if (ini_get('session.auto_start')) { - $conn->Session->start(); - } - - return $this->_app->onOpen($conn, $request); - } - - /** - * {@inheritdoc} - */ - function onMessage(ConnectionInterface $from, $msg) { - return $this->_app->onMessage($from, $msg); - } - - /** - * {@inheritdoc} - */ - function onClose(ConnectionInterface $conn) { - // "close" session for Connection - - return $this->_app->onClose($conn); - } - - /** - * {@inheritdoc} - */ - function onError(ConnectionInterface $conn, \Exception $e) { - return $this->_app->onError($conn, $e); - } - - /** - * Set all the php session. ini options - * © Symfony - * @param array $options - * @return array - */ - protected function setOptions(array $options) { - $all = array( - 'auto_start', 'cache_limiter', 'cookie_domain', 'cookie_httponly', - 'cookie_lifetime', 'cookie_path', 'cookie_secure', - 'entropy_file', 'entropy_length', 'gc_divisor', - 'gc_maxlifetime', 'gc_probability', 'hash_bits_per_character', - 'hash_function', 'name', 'referer_check', - 'serialize_handler', 'use_cookies', - 'use_only_cookies', 'use_trans_sid', 'upload_progress.enabled', - 'upload_progress.cleanup', 'upload_progress.prefix', 'upload_progress.name', - 'upload_progress.freq', 'upload_progress.min-freq', 'url_rewriter.tags' - ); - - foreach ($all as $key) { - if (!array_key_exists($key, $options)) { - $options[$key] = ini_get("session.{$key}"); - } else { - ini_set("session.{$key}", $options[$key]); - } - } - - return $options; - } - - /** - * @param string $langDef Input to convert - * @return string - */ - protected function toClassCase($langDef) { - return str_replace(' ', '', ucwords(str_replace('_', ' ', $langDef))); - } - - /** - * Taken from Guzzle3 - */ - private static $cookieParts = array( - 'domain' => 'Domain', - 'path' => 'Path', - 'max_age' => 'Max-Age', - 'expires' => 'Expires', - 'version' => 'Version', - 'secure' => 'Secure', - 'port' => 'Port', - 'discard' => 'Discard', - 'comment' => 'Comment', - 'comment_url' => 'Comment-Url', - 'http_only' => 'HttpOnly' - ); - - /** - * Taken from Guzzle3 - */ - private function parseCookie($cookie, $host = null, $path = null, $decode = false) { - // Explode the cookie string using a series of semicolons - $pieces = array_filter(array_map('trim', explode(';', $cookie))); - - // The name of the cookie (first kvp) must include an equal sign. - if (empty($pieces) || !strpos($pieces[0], '=')) { - return false; - } - - // Create the default return array - $data = array_merge(array_fill_keys(array_keys(self::$cookieParts), null), array( - 'cookies' => array(), - 'data' => array(), - 'path' => $path ?: '/', - 'http_only' => false, - 'discard' => false, - 'domain' => $host - )); - $foundNonCookies = 0; - - // Add the cookie pieces into the parsed data array - foreach ($pieces as $part) { - - $cookieParts = explode('=', $part, 2); - $key = trim($cookieParts[0]); - - if (count($cookieParts) == 1) { - // Can be a single value (e.g. secure, httpOnly) - $value = true; - } else { - // Be sure to strip wrapping quotes - $value = trim($cookieParts[1], " \n\r\t\0\x0B\""); - if ($decode) { - $value = urldecode($value); - } - } - - // Only check for non-cookies when cookies have been found - if (!empty($data['cookies'])) { - foreach (self::$cookieParts as $mapValue => $search) { - if (!strcasecmp($search, $key)) { - $data[$mapValue] = $mapValue == 'port' ? array_map('trim', explode(',', $value)) : $value; - $foundNonCookies++; - continue 2; - } - } - } - - // If cookies have not yet been retrieved, or this value was not found in the pieces array, treat it as a - // cookie. IF non-cookies have been parsed, then this isn't a cookie, it's cookie data. Cookies then data. - $data[$foundNonCookies ? 'data' : 'cookies'][$key] = $value; - } - - // Calculate the expires date - if (!$data['expires'] && $data['max_age']) { - $data['expires'] = time() + (int) $data['max_age']; - } - - return $data; - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Session/Storage/Proxy/VirtualProxy.php b/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Session/Storage/Proxy/VirtualProxy.php deleted file mode 100644 index b478d03..0000000 --- a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Session/Storage/Proxy/VirtualProxy.php +++ /dev/null @@ -1,54 +0,0 @@ -saveHandlerName = 'user'; - $this->_sessionName = ini_get('session.name'); - } - - /** - * {@inheritdoc} - */ - public function getId() { - return $this->_sessionId; - } - - /** - * {@inheritdoc} - */ - public function setId($id) { - $this->_sessionId = $id; - } - - /** - * {@inheritdoc} - */ - public function getName() { - return $this->_sessionName; - } - - /** - * DO NOT CALL THIS METHOD - * @internal - */ - public function setName($name) { - throw new \RuntimeException("Can not change session name in VirtualProxy"); - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Session/Storage/VirtualSessionStorage.php b/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Session/Storage/VirtualSessionStorage.php deleted file mode 100644 index daa10bb..0000000 --- a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Session/Storage/VirtualSessionStorage.php +++ /dev/null @@ -1,88 +0,0 @@ -setSaveHandler($handler); - $this->saveHandler->setId($sessionId); - $this->_serializer = $serializer; - $this->setMetadataBag(null); - } - - /** - * {@inheritdoc} - */ - public function start() { - if ($this->started && !$this->closed) { - return true; - } - - // You have to call Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler::open() to use - // pdo_sqlite (and possible pdo_*) as session storage, if you are using a DSN string instead of a \PDO object - // in the constructor. The method arguments are filled with the values, which are also used by the symfony - // framework in this case. This must not be the best choice, but it works. - $this->saveHandler->open(session_save_path(), session_name()); - - $rawData = $this->saveHandler->read($this->saveHandler->getId()); - $sessionData = $this->_serializer->unserialize($rawData); - - $this->loadSession($sessionData); - - if (!$this->saveHandler->isWrapper() && !$this->saveHandler->isSessionHandlerInterface()) { - $this->saveHandler->setActive(false); - } - - return true; - } - - /** - * {@inheritdoc} - */ - public function regenerate($destroy = false, $lifetime = null) { - // .. ? - } - - /** - * {@inheritdoc} - */ - public function save() { - // get the data from the bags? - // serialize the data - // save the data using the saveHandler -// $this->saveHandler->write($this->saveHandler->getId(), - - if (!$this->saveHandler->isWrapper() && !$this->getSaveHandler()->isSessionHandlerInterface()) { - $this->saveHandler->setActive(false); - } - - $this->closed = true; - } - - /** - * {@inheritdoc} - */ - public function setSaveHandler($saveHandler = null) { - if (!($saveHandler instanceof \SessionHandlerInterface)) { - throw new \InvalidArgumentException('Handler must be instance of SessionHandlerInterface'); - } - - if (!($saveHandler instanceof VirtualProxy)) { - $saveHandler = new VirtualProxy($saveHandler); - } - - $this->saveHandler = $saveHandler; - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Wamp/Exception.php b/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Wamp/Exception.php deleted file mode 100644 index 6c824da..0000000 --- a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Wamp/Exception.php +++ /dev/null @@ -1,5 +0,0 @@ -_decorating = $serverComponent; - $this->connections = new \SplObjectStorage; - } - - /** - * {@inheritdoc} - */ - public function getSubProtocols() { - if ($this->_decorating instanceof WsServerInterface) { - $subs = $this->_decorating->getSubProtocols(); - $subs[] = 'wamp'; - - return $subs; - } - - return ['wamp']; - } - - /** - * {@inheritdoc} - */ - public function onOpen(ConnectionInterface $conn) { - $decor = new WampConnection($conn); - $this->connections->attach($conn, $decor); - - $this->_decorating->onOpen($decor); - } - - /** - * {@inheritdoc} - * @throws \Ratchet\Wamp\Exception - * @throws \Ratchet\Wamp\JsonException - */ - public function onMessage(ConnectionInterface $from, $msg) { - $from = $this->connections[$from]; - - if (null === ($json = @json_decode($msg, true))) { - throw new JsonException; - } - - if (!is_array($json) || $json !== array_values($json)) { - throw new Exception("Invalid WAMP message format"); - } - - if (isset($json[1]) && !(is_string($json[1]) || is_numeric($json[1]))) { - throw new Exception('Invalid Topic, must be a string'); - } - - switch ($json[0]) { - case static::MSG_PREFIX: - $from->WAMP->prefixes[$json[1]] = $json[2]; - break; - - case static::MSG_CALL: - array_shift($json); - $callID = array_shift($json); - $procURI = array_shift($json); - - if (count($json) == 1 && is_array($json[0])) { - $json = $json[0]; - } - - $this->_decorating->onCall($from, $callID, $from->getUri($procURI), $json); - break; - - case static::MSG_SUBSCRIBE: - $this->_decorating->onSubscribe($from, $from->getUri($json[1])); - break; - - case static::MSG_UNSUBSCRIBE: - $this->_decorating->onUnSubscribe($from, $from->getUri($json[1])); - break; - - case static::MSG_PUBLISH: - $exclude = (array_key_exists(3, $json) ? $json[3] : null); - if (!is_array($exclude)) { - if (true === (boolean)$exclude) { - $exclude = [$from->WAMP->sessionId]; - } else { - $exclude = []; - } - } - - $eligible = (array_key_exists(4, $json) ? $json[4] : []); - - $this->_decorating->onPublish($from, $from->getUri($json[1]), $json[2], $exclude, $eligible); - break; - - default: - throw new Exception('Invalid WAMP message type'); - } - } - - /** - * {@inheritdoc} - */ - public function onClose(ConnectionInterface $conn) { - $decor = $this->connections[$conn]; - $this->connections->detach($conn); - - $this->_decorating->onClose($decor); - } - - /** - * {@inheritdoc} - */ - public function onError(ConnectionInterface $conn, \Exception $e) { - return $this->_decorating->onError($this->connections[$conn], $e); - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Wamp/Topic.php b/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Wamp/Topic.php deleted file mode 100644 index 675b236..0000000 --- a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Wamp/Topic.php +++ /dev/null @@ -1,101 +0,0 @@ -id = $topicId; - $this->subscribers = new \SplObjectStorage; - } - - /** - * @return string - */ - public function getId() { - return $this->id; - } - - public function __toString() { - return $this->getId(); - } - - /** - * Send a message to all the connections in this topic - * @param string|array $msg Payload to publish - * @param array $exclude A list of session IDs the message should be excluded from (blacklist) - * @param array $eligible A list of session Ids the message should be send to (whitelist) - * @return Topic The same Topic object to chain - */ - public function broadcast($msg, array $exclude = array(), array $eligible = array()) { - $useEligible = (bool)count($eligible); - foreach ($this->subscribers as $client) { - if (in_array($client->WAMP->sessionId, $exclude)) { - continue; - } - - if ($useEligible && !in_array($client->WAMP->sessionId, $eligible)) { - continue; - } - - $client->event($this->id, $msg); - } - - return $this; - } - - /** - * @param WampConnection $conn - * @return boolean - */ - public function has(ConnectionInterface $conn) { - return $this->subscribers->contains($conn); - } - - /** - * @param WampConnection $conn - * @return Topic - */ - public function add(ConnectionInterface $conn) { - $this->subscribers->attach($conn); - - return $this; - } - - /** - * @param WampConnection $conn - * @return Topic - */ - public function remove(ConnectionInterface $conn) { - if ($this->subscribers->contains($conn)) { - $this->subscribers->detach($conn); - } - - return $this; - } - - /** - * {@inheritdoc} - */ - #[\ReturnTypeWillChange] - public function getIterator() { - return $this->subscribers; - } - - /** - * {@inheritdoc} - */ - #[\ReturnTypeWillChange] - public function count() { - return $this->subscribers->count(); - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Wamp/TopicManager.php b/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Wamp/TopicManager.php deleted file mode 100644 index dd06ada..0000000 --- a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Wamp/TopicManager.php +++ /dev/null @@ -1,125 +0,0 @@ -app = $app; - } - - /** - * {@inheritdoc} - */ - public function onOpen(ConnectionInterface $conn) { - $conn->WAMP->subscriptions = new \SplObjectStorage; - $this->app->onOpen($conn); - } - - /** - * {@inheritdoc} - */ - public function onCall(ConnectionInterface $conn, $id, $topic, array $params) { - $this->app->onCall($conn, $id, $this->getTopic($topic), $params); - } - - /** - * {@inheritdoc} - */ - public function onSubscribe(ConnectionInterface $conn, $topic) { - $topicObj = $this->getTopic($topic); - - if ($conn->WAMP->subscriptions->contains($topicObj)) { - return; - } - - $this->topicLookup[$topic]->add($conn); - $conn->WAMP->subscriptions->attach($topicObj); - $this->app->onSubscribe($conn, $topicObj); - } - - /** - * {@inheritdoc} - */ - public function onUnsubscribe(ConnectionInterface $conn, $topic) { - $topicObj = $this->getTopic($topic); - - if (!$conn->WAMP->subscriptions->contains($topicObj)) { - return; - } - - $this->cleanTopic($topicObj, $conn); - - $this->app->onUnsubscribe($conn, $topicObj); - } - - /** - * {@inheritdoc} - */ - public function onPublish(ConnectionInterface $conn, $topic, $event, array $exclude, array $eligible) { - $this->app->onPublish($conn, $this->getTopic($topic), $event, $exclude, $eligible); - } - - /** - * {@inheritdoc} - */ - public function onClose(ConnectionInterface $conn) { - $this->app->onClose($conn); - - foreach ($this->topicLookup as $topic) { - $this->cleanTopic($topic, $conn); - } - } - - /** - * {@inheritdoc} - */ - public function onError(ConnectionInterface $conn, \Exception $e) { - $this->app->onError($conn, $e); - } - - /** - * {@inheritdoc} - */ - public function getSubProtocols() { - if ($this->app instanceof WsServerInterface) { - return $this->app->getSubProtocols(); - } - - return array(); - } - - /** - * @param string - * @return Topic - */ - protected function getTopic($topic) { - if (!array_key_exists($topic, $this->topicLookup)) { - $this->topicLookup[$topic] = new Topic($topic); - } - - return $this->topicLookup[$topic]; - } - - protected function cleanTopic(Topic $topic, ConnectionInterface $conn) { - if ($conn->WAMP->subscriptions->contains($topic)) { - $conn->WAMP->subscriptions->detach($topic); - } - - $this->topicLookup[$topic->getId()]->remove($conn); - - if (0 === $topic->count()) { - unset($this->topicLookup[$topic->getId()]); - } - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Wamp/WampConnection.php b/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Wamp/WampConnection.php deleted file mode 100644 index dda1e4e..0000000 --- a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Wamp/WampConnection.php +++ /dev/null @@ -1,115 +0,0 @@ -WAMP = new \StdClass; - $this->WAMP->sessionId = str_replace('.', '', uniqid(mt_rand(), true)); - $this->WAMP->prefixes = array(); - - $this->send(json_encode(array(WAMP::MSG_WELCOME, $this->WAMP->sessionId, 1, \Ratchet\VERSION))); - } - - /** - * Successfully respond to a call made by the client - * @param string $id The unique ID given by the client to respond to - * @param array $data an object or array - * @return WampConnection - */ - public function callResult($id, $data = array()) { - return $this->send(json_encode(array(WAMP::MSG_CALL_RESULT, $id, $data))); - } - - /** - * Respond with an error to a client call - * @param string $id The unique ID given by the client to respond to - * @param string $errorUri The URI given to identify the specific error - * @param string $desc A developer-oriented description of the error - * @param string $details An optional human readable detail message to send back - * @return WampConnection - */ - public function callError($id, $errorUri, $desc = '', $details = null) { - if ($errorUri instanceof Topic) { - $errorUri = (string)$errorUri; - } - - $data = array(WAMP::MSG_CALL_ERROR, $id, $errorUri, $desc); - - if (null !== $details) { - $data[] = $details; - } - - return $this->send(json_encode($data)); - } - - /** - * @param string $topic The topic to broadcast to - * @param mixed $msg Data to send with the event. Anything that is json'able - * @return WampConnection - */ - public function event($topic, $msg) { - return $this->send(json_encode(array(WAMP::MSG_EVENT, (string)$topic, $msg))); - } - - /** - * @param string $curie - * @param string $uri - * @return WampConnection - */ - public function prefix($curie, $uri) { - $this->WAMP->prefixes[$curie] = (string)$uri; - - return $this->send(json_encode(array(WAMP::MSG_PREFIX, $curie, (string)$uri))); - } - - /** - * Get the full request URI from the connection object if a prefix has been established for it - * @param string $uri - * @return string - */ - public function getUri($uri) { - $curieSeperator = ':'; - - if (preg_match('/http(s*)\:\/\//', $uri) == false) { - if (strpos($uri, $curieSeperator) !== false) { - list($prefix, $action) = explode($curieSeperator, $uri); - - if(isset($this->WAMP->prefixes[$prefix]) === true){ - return $this->WAMP->prefixes[$prefix] . '#' . $action; - } - } - } - - return $uri; - } - - /** - * @internal - */ - public function send($data) { - $this->getConnection()->send($data); - - return $this; - } - - /** - * {@inheritdoc} - */ - public function close($opt = null) { - $this->getConnection()->close($opt); - } - -} diff --git a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Wamp/WampServer.php b/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Wamp/WampServer.php deleted file mode 100644 index 5d710aa..0000000 --- a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Wamp/WampServer.php +++ /dev/null @@ -1,67 +0,0 @@ -wampProtocol = new ServerProtocol(new TopicManager($app)); - } - - /** - * {@inheritdoc} - */ - public function onOpen(ConnectionInterface $conn) { - $this->wampProtocol->onOpen($conn); - } - - /** - * {@inheritdoc} - */ - public function onMessage(ConnectionInterface $conn, $msg) { - try { - $this->wampProtocol->onMessage($conn, $msg); - } catch (Exception $we) { - $conn->close(1007); - } - } - - /** - * {@inheritdoc} - */ - public function onClose(ConnectionInterface $conn) { - $this->wampProtocol->onClose($conn); - } - - /** - * {@inheritdoc} - */ - public function onError(ConnectionInterface $conn, \Exception $e) { - $this->wampProtocol->onError($conn, $e); - } - - /** - * {@inheritdoc} - */ - public function getSubProtocols() { - return $this->wampProtocol->getSubProtocols(); - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Wamp/WampServerInterface.php b/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Wamp/WampServerInterface.php deleted file mode 100644 index 15c521d..0000000 --- a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/Wamp/WampServerInterface.php +++ /dev/null @@ -1,43 +0,0 @@ -connection = $conn; - $this->buffer = $buffer; - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/WebSocket/MessageCallableInterface.php b/digital_doctor/vendor/cboden/ratchet/src/Ratchet/WebSocket/MessageCallableInterface.php deleted file mode 100644 index b5c094e..0000000 --- a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/WebSocket/MessageCallableInterface.php +++ /dev/null @@ -1,8 +0,0 @@ -WebSocket->closing) { - if (!($msg instanceof DataInterface)) { - $msg = new Frame($msg); - } - - $this->getConnection()->send($msg->getContents()); - } - - return $this; - } - - /** - * @param int|\Ratchet\RFC6455\Messaging\DataInterface - */ - public function close($code = 1000) { - if ($this->WebSocket->closing) { - return; - } - - if ($code instanceof DataInterface) { - $this->send($code); - } else { - $this->send(new Frame(pack('n', $code), true, Frame::OP_CLOSE)); - } - - $this->getConnection()->close(); - - $this->WebSocket->closing = true; - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/WebSocket/WsServer.php b/digital_doctor/vendor/cboden/ratchet/src/Ratchet/WebSocket/WsServer.php deleted file mode 100644 index 27795ca..0000000 --- a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/WebSocket/WsServer.php +++ /dev/null @@ -1,225 +0,0 @@ -msgCb = function(ConnectionInterface $conn, MessageInterface $msg) { - $this->delegate->onMessage($conn, $msg); - }; - } elseif ($component instanceof DataComponentInterface) { - $this->msgCb = function(ConnectionInterface $conn, MessageInterface $msg) { - $this->delegate->onMessage($conn, $msg->getPayload()); - }; - } else { - throw new \UnexpectedValueException('Expected instance of \Ratchet\WebSocket\MessageComponentInterface or \Ratchet\MessageComponentInterface'); - } - - if (bin2hex('✓') !== 'e29c93') { - throw new \DomainException('Bad encoding, unicode character ✓ did not match expected value. Ensure charset UTF-8 and check ini val mbstring.func_autoload'); - } - - $this->delegate = $component; - $this->connections = new \SplObjectStorage; - - $this->closeFrameChecker = new CloseFrameChecker; - $this->handshakeNegotiator = new ServerNegotiator(new RequestVerifier); - $this->handshakeNegotiator->setStrictSubProtocolCheck(true); - - if ($component instanceof WsServerInterface) { - $this->handshakeNegotiator->setSupportedSubProtocols($component->getSubProtocols()); - } - - $this->pongReceiver = function() {}; - - $reusableUnderflowException = new \UnderflowException; - $this->ueFlowFactory = function() use ($reusableUnderflowException) { - return $reusableUnderflowException; - }; - } - - /** - * {@inheritdoc} - */ - public function onOpen(ConnectionInterface $conn, RequestInterface $request = null) { - if (null === $request) { - throw new \UnexpectedValueException('$request can not be null'); - } - - $conn->httpRequest = $request; - - $conn->WebSocket = new \StdClass; - $conn->WebSocket->closing = false; - - $response = $this->handshakeNegotiator->handshake($request)->withHeader('X-Powered-By', \Ratchet\VERSION); - - $conn->send(Message::toString($response)); - - if (101 !== $response->getStatusCode()) { - return $conn->close(); - } - - $wsConn = new WsConnection($conn); - - $streamer = new MessageBuffer( - $this->closeFrameChecker, - function(MessageInterface $msg) use ($wsConn) { - $cb = $this->msgCb; - $cb($wsConn, $msg); - }, - function(FrameInterface $frame) use ($wsConn) { - $this->onControlFrame($frame, $wsConn); - }, - true, - $this->ueFlowFactory - ); - - $this->connections->attach($conn, new ConnContext($wsConn, $streamer)); - - return $this->delegate->onOpen($wsConn); - } - - /** - * {@inheritdoc} - */ - public function onMessage(ConnectionInterface $from, $msg) { - if ($from->WebSocket->closing) { - return; - } - - $this->connections[$from]->buffer->onData($msg); - } - - /** - * {@inheritdoc} - */ - public function onClose(ConnectionInterface $conn) { - if ($this->connections->contains($conn)) { - $context = $this->connections[$conn]; - $this->connections->detach($conn); - - $this->delegate->onClose($context->connection); - } - } - - /** - * {@inheritdoc} - */ - public function onError(ConnectionInterface $conn, \Exception $e) { - if ($this->connections->contains($conn)) { - $this->delegate->onError($this->connections[$conn]->connection, $e); - } else { - $conn->close(); - } - } - - public function onControlFrame(FrameInterface $frame, WsConnection $conn) { - switch ($frame->getOpCode()) { - case Frame::OP_CLOSE: - $conn->close($frame); - break; - case Frame::OP_PING: - $conn->send(new Frame($frame->getPayload(), true, Frame::OP_PONG)); - break; - case Frame::OP_PONG: - $pongReceiver = $this->pongReceiver; - $pongReceiver($frame, $conn); - break; - } - } - - public function setStrictSubProtocolCheck($enable) { - $this->handshakeNegotiator->setStrictSubProtocolCheck($enable); - } - - public function enableKeepAlive(LoopInterface $loop, $interval = 30) { - $lastPing = new Frame(uniqid(), true, Frame::OP_PING); - $pingedConnections = new \SplObjectStorage; - $splClearer = new \SplObjectStorage; - - $this->pongReceiver = function(FrameInterface $frame, $wsConn) use ($pingedConnections, &$lastPing) { - if ($frame->getPayload() === $lastPing->getPayload()) { - $pingedConnections->detach($wsConn); - } - }; - - $loop->addPeriodicTimer((int)$interval, function() use ($pingedConnections, &$lastPing, $splClearer) { - foreach ($pingedConnections as $wsConn) { - $wsConn->close(); - } - $pingedConnections->removeAllExcept($splClearer); - - $lastPing = new Frame(uniqid(), true, Frame::OP_PING); - - foreach ($this->connections as $key => $conn) { - $wsConn = $this->connections[$conn]->connection; - - $wsConn->send($lastPing); - $pingedConnections->attach($wsConn); - } - }); - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/WebSocket/WsServerInterface.php b/digital_doctor/vendor/cboden/ratchet/src/Ratchet/WebSocket/WsServerInterface.php deleted file mode 100644 index 15d1f7b..0000000 --- a/digital_doctor/vendor/cboden/ratchet/src/Ratchet/WebSocket/WsServerInterface.php +++ /dev/null @@ -1,14 +0,0 @@ -send($msg); - } - - public function onOpen(ConnectionInterface $conn) { - } - - public function onClose(ConnectionInterface $conn) { - } - - public function onError(ConnectionInterface $conn, \Exception $e) { - } -} - - $port = $argc > 1 ? $argv[1] : 8000; - $impl = sprintf('React\EventLoop\%sLoop', $argc > 2 ? $argv[2] : 'StreamSelect'); - - $loop = new $impl; - $sock = new React\Socket\Server('0.0.0.0:' . $port, $loop); - - $wsServer = new Ratchet\WebSocket\WsServer(new BinaryEcho); - // This is enabled to test https://github.com/ratchetphp/Ratchet/issues/430 - // The time is left at 10 minutes so that it will not try to every ping anything - // This causes the Ratchet server to crash on test 2.7 - $wsServer->enableKeepAlive($loop, 600); - - $app = new Ratchet\Http\HttpServer($wsServer); - - $server = new Ratchet\Server\IoServer($app, $sock, $loop); - $server->run(); diff --git a/digital_doctor/vendor/cboden/ratchet/tests/autobahn/fuzzingclient-all.json b/digital_doctor/vendor/cboden/ratchet/tests/autobahn/fuzzingclient-all.json deleted file mode 100644 index 0494cf3..0000000 --- a/digital_doctor/vendor/cboden/ratchet/tests/autobahn/fuzzingclient-all.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "options": {"failByDrop": false} - , "outdir": "reports/ab" - - , "servers": [ - {"agent": "Ratchet/0.4 libevent", "url": "ws://localhost:8001", "options": {"version": 18}} - , {"agent": "Ratchet/0.4 libev", "url": "ws://localhost:8004", "options": {"version": 18}} - , {"agent": "Ratchet/0.4 streams", "url": "ws://localhost:8002", "options": {"version": 18}} - , {"agent": "AutobahnTestSuite/0.5.9", "url": "ws://localhost:8000", "options": {"version": 18}} - ] - - , "cases": ["*"] - , "exclude-cases": [] - , "exclude-agent-cases": {} -} diff --git a/digital_doctor/vendor/cboden/ratchet/tests/autobahn/fuzzingclient-profile.json b/digital_doctor/vendor/cboden/ratchet/tests/autobahn/fuzzingclient-profile.json deleted file mode 100644 index e81a9fd..0000000 --- a/digital_doctor/vendor/cboden/ratchet/tests/autobahn/fuzzingclient-profile.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "options": {"failByDrop": false} - , "outdir": "reports/profile" - - , "servers": [ - {"agent": "Ratchet", "url": "ws://localhost:8000", "options": {"version": 18}} - ] - - , "cases": ["9.7.4"] - , "exclude-cases": ["1.2.*", "2.3", "2.4", "2.6", "9.2.*", "9.4.*", "9.6.*", "9.8.*"] - , "exclude-agent-cases": {} -} diff --git a/digital_doctor/vendor/cboden/ratchet/tests/autobahn/fuzzingclient-quick.json b/digital_doctor/vendor/cboden/ratchet/tests/autobahn/fuzzingclient-quick.json deleted file mode 100644 index c92e805..0000000 --- a/digital_doctor/vendor/cboden/ratchet/tests/autobahn/fuzzingclient-quick.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "options": {"failByDrop": false} - , "outdir": "reports/rfc" - - , "servers": [ - {"agent": "Ratchet", "url": "ws://localhost:8000", "options": {"version": 18}} - ] - - , "cases": ["*"] - , "exclude-cases": [] - , "exclude-agent-cases": {} -} diff --git a/digital_doctor/vendor/cboden/ratchet/tests/bootstrap.php b/digital_doctor/vendor/cboden/ratchet/tests/bootstrap.php deleted file mode 100644 index 40791ba..0000000 --- a/digital_doctor/vendor/cboden/ratchet/tests/bootstrap.php +++ /dev/null @@ -1,4 +0,0 @@ -addPsr4('Ratchet\\', __DIR__ . '/helpers/Ratchet'); diff --git a/digital_doctor/vendor/cboden/ratchet/tests/helpers/Ratchet/AbstractMessageComponentTestCase.php b/digital_doctor/vendor/cboden/ratchet/tests/helpers/Ratchet/AbstractMessageComponentTestCase.php deleted file mode 100644 index 8c298e5..0000000 --- a/digital_doctor/vendor/cboden/ratchet/tests/helpers/Ratchet/AbstractMessageComponentTestCase.php +++ /dev/null @@ -1,50 +0,0 @@ -_app = $this->getMock($this->getComponentClassString()); - $decorator = $this->getDecoratorClassString(); - $this->_serv = new $decorator($this->_app); - $this->_conn = $this->getMock('\Ratchet\ConnectionInterface'); - - $this->doOpen($this->_conn); - } - - protected function doOpen($conn) { - $this->_serv->onOpen($conn); - } - - public function isExpectedConnection() { - return new \PHPUnit_Framework_Constraint_IsInstanceOf($this->getConnectionClassString()); - } - - public function testOpen() { - $this->_app->expects($this->once())->method('onOpen')->with($this->isExpectedConnection()); - $this->doOpen($this->getMock('\Ratchet\ConnectionInterface')); - } - - public function testOnClose() { - $this->_app->expects($this->once())->method('onClose')->with($this->isExpectedConnection()); - $this->_serv->onClose($this->_conn); - } - - public function testOnError() { - $e = new \Exception('Whoops!'); - $this->_app->expects($this->once())->method('onError')->with($this->isExpectedConnection(), $e); - $this->_serv->onError($this->_conn, $e); - } - - public function passthroughMessageTest($value) { - $this->_app->expects($this->once())->method('onMessage')->with($this->isExpectedConnection(), $value); - $this->_serv->onMessage($this->_conn, $value); - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/tests/helpers/Ratchet/Mock/Component.php b/digital_doctor/vendor/cboden/ratchet/tests/helpers/Ratchet/Mock/Component.php deleted file mode 100644 index e152988..0000000 --- a/digital_doctor/vendor/cboden/ratchet/tests/helpers/Ratchet/Mock/Component.php +++ /dev/null @@ -1,35 +0,0 @@ -last[__FUNCTION__] = func_get_args(); - } - - public function onOpen(ConnectionInterface $conn) { - $this->last[__FUNCTION__] = func_get_args(); - } - - public function onMessage(ConnectionInterface $from, $msg) { - $this->last[__FUNCTION__] = func_get_args(); - } - - public function onClose(ConnectionInterface $conn) { - $this->last[__FUNCTION__] = func_get_args(); - } - - public function onError(ConnectionInterface $conn, \Exception $e) { - $this->last[__FUNCTION__] = func_get_args(); - } - - public function getSubProtocols() { - return $this->protocols; - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/tests/helpers/Ratchet/Mock/Connection.php b/digital_doctor/vendor/cboden/ratchet/tests/helpers/Ratchet/Mock/Connection.php deleted file mode 100644 index 5918296..0000000 --- a/digital_doctor/vendor/cboden/ratchet/tests/helpers/Ratchet/Mock/Connection.php +++ /dev/null @@ -1,20 +0,0 @@ - '' - , 'close' => false - ); - - public $remoteAddress = '127.0.0.1'; - - public function send($data) { - $this->last[__FUNCTION__] = $data; - } - - public function close() { - $this->last[__FUNCTION__] = true; - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/tests/helpers/Ratchet/Mock/ConnectionDecorator.php b/digital_doctor/vendor/cboden/ratchet/tests/helpers/Ratchet/Mock/ConnectionDecorator.php deleted file mode 100644 index 5570c07..0000000 --- a/digital_doctor/vendor/cboden/ratchet/tests/helpers/Ratchet/Mock/ConnectionDecorator.php +++ /dev/null @@ -1,22 +0,0 @@ - '' - , 'end' => false - ); - - public function send($data) { - $this->last[__FUNCTION__] = $data; - - $this->getConnection()->send($data); - } - - public function close() { - $this->last[__FUNCTION__] = true; - - $this->getConnection()->close(); - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/tests/helpers/Ratchet/Mock/WampComponent.php b/digital_doctor/vendor/cboden/ratchet/tests/helpers/Ratchet/Mock/WampComponent.php deleted file mode 100644 index cd526cb..0000000 --- a/digital_doctor/vendor/cboden/ratchet/tests/helpers/Ratchet/Mock/WampComponent.php +++ /dev/null @@ -1,43 +0,0 @@ -protocols; - } - - public function onCall(ConnectionInterface $conn, $id, $procURI, array $params) { - $this->last[__FUNCTION__] = func_get_args(); - } - - public function onSubscribe(ConnectionInterface $conn, $topic) { - $this->last[__FUNCTION__] = func_get_args(); - } - - public function onUnSubscribe(ConnectionInterface $conn, $topic) { - $this->last[__FUNCTION__] = func_get_args(); - } - - public function onPublish(ConnectionInterface $conn, $topic, $event, array $exclude, array $eligible) { - $this->last[__FUNCTION__] = func_get_args(); - } - - public function onOpen(ConnectionInterface $conn) { - $this->last[__FUNCTION__] = func_get_args(); - } - - public function onClose(ConnectionInterface $conn) { - $this->last[__FUNCTION__] = func_get_args(); - } - - public function onError(ConnectionInterface $conn, \Exception $e) { - $this->last[__FUNCTION__] = func_get_args(); - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/tests/helpers/Ratchet/NullComponent.php b/digital_doctor/vendor/cboden/ratchet/tests/helpers/Ratchet/NullComponent.php deleted file mode 100644 index 90def21..0000000 --- a/digital_doctor/vendor/cboden/ratchet/tests/helpers/Ratchet/NullComponent.php +++ /dev/null @@ -1,28 +0,0 @@ -mock = $this->getMock('\Ratchet\ConnectionInterface'); - $this->l1 = new ConnectionDecorator($this->mock); - $this->l2 = new ConnectionDecorator($this->l1); - } - - public function testGet() { - $var = 'hello'; - $val = 'world'; - - $this->mock->$var = $val; - - $this->assertEquals($val, $this->l1->$var); - $this->assertEquals($val, $this->l2->$var); - } - - public function testSet() { - $var = 'Chris'; - $val = 'Boden'; - - $this->l1->$var = $val; - - $this->assertEquals($val, $this->mock->$var); - } - - public function testSetLevel2() { - $var = 'Try'; - $val = 'Again'; - - $this->l2->$var = $val; - - $this->assertEquals($val, $this->mock->$var); - } - - public function testIsSetTrue() { - $var = 'PHP'; - $val = 'Ratchet'; - - $this->mock->$var = $val; - - $this->assertTrue(isset($this->l1->$var)); - $this->assertTrue(isset($this->l2->$var)); - } - - public function testIsSetFalse() { - $var = 'herp'; - $val = 'derp'; - - $this->assertFalse(isset($this->l1->$var)); - $this->assertFalse(isset($this->l2->$var)); - } - - public function testUnset() { - $var = 'Flying'; - $val = 'Monkey'; - - $this->mock->$var = $val; - unset($this->l1->$var); - - $this->assertFalse(isset($this->mock->$var)); - } - - public function testUnsetLevel2() { - $var = 'Flying'; - $val = 'Monkey'; - - $this->mock->$var = $val; - unset($this->l2->$var); - - $this->assertFalse(isset($this->mock->$var)); - } - - public function testGetConnection() { - $class = new \ReflectionClass('\\Ratchet\\AbstractConnectionDecorator'); - $method = $class->getMethod('getConnection'); - $method->setAccessible(true); - - $conn = $method->invokeArgs($this->l1, array()); - - $this->assertSame($this->mock, $conn); - } - - public function testGetConnectionLevel2() { - $class = new \ReflectionClass('\\Ratchet\\AbstractConnectionDecorator'); - $method = $class->getMethod('getConnection'); - $method->setAccessible(true); - - $conn = $method->invokeArgs($this->l2, array()); - - $this->assertSame($this->l1, $conn); - } - - public function testWrapperCanStoreSelfInDecorator() { - $this->mock->decorator = $this->l1; - - $this->assertSame($this->l1, $this->l2->decorator); - } - - public function testDecoratorRecursion() { - $this->mock->decorator = new \stdClass; - $this->mock->decorator->conn = $this->l1; - - $this->assertSame($this->l1, $this->mock->decorator->conn); - $this->assertSame($this->l1, $this->l1->decorator->conn); - $this->assertSame($this->l1, $this->l2->decorator->conn); - } - - public function testDecoratorRecursionLevel2() { - $this->mock->decorator = new \stdClass; - $this->mock->decorator->conn = $this->l2; - - $this->assertSame($this->l2, $this->mock->decorator->conn); - $this->assertSame($this->l2, $this->l1->decorator->conn); - $this->assertSame($this->l2, $this->l2->decorator->conn); - - // just for fun - $this->assertSame($this->l2, $this->l2->decorator->conn->decorator->conn->decorator->conn); - } - - public function testWarningGettingNothing() { - $this->setExpectedException('PHPUnit_Framework_Error'); - $var = $this->mock->nonExistant; - } - - public function testWarningGettingNothingLevel1() { - $this->setExpectedException('PHPUnit_Framework_Error'); - $var = $this->l1->nonExistant; - } - - public function testWarningGettingNothingLevel2() { - $this->setExpectedException('PHPUnit_Framework_Error'); - $var = $this->l2->nonExistant; - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/tests/unit/Http/HttpRequestParserTest.php b/digital_doctor/vendor/cboden/ratchet/tests/unit/Http/HttpRequestParserTest.php deleted file mode 100644 index 6af8402..0000000 --- a/digital_doctor/vendor/cboden/ratchet/tests/unit/Http/HttpRequestParserTest.php +++ /dev/null @@ -1,50 +0,0 @@ -parser = new HttpRequestParser; - } - - public function headersProvider() { - return array( - array(false, "GET / HTTP/1.1\r\nHost: socketo.me\r\n") - , array(true, "GET / HTTP/1.1\r\nHost: socketo.me\r\n\r\n") - , array(true, "GET / HTTP/1.1\r\nHost: socketo.me\r\n\r\n1") - , array(true, "GET / HTTP/1.1\r\nHost: socketo.me\r\n\r\nHixie✖") - , array(true, "GET / HTTP/1.1\r\nHost: socketo.me\r\n\r\nHixie✖\r\n\r\n") - , array(true, "GET / HTTP/1.1\r\nHost: socketo.me\r\n\r\nHixie\r\n") - ); - } - - /** - * @dataProvider headersProvider - */ - public function testIsEom($expected, $message) { - $this->assertEquals($expected, $this->parser->isEom($message)); - } - - public function testBufferOverflowResponse() { - $conn = $this->getMock('\Ratchet\ConnectionInterface'); - - $this->parser->maxSize = 20; - - $this->assertNull($this->parser->onMessage($conn, "GET / HTTP/1.1\r\n")); - - $this->setExpectedException('OverflowException'); - - $this->parser->onMessage($conn, "Header-Is: Too Big"); - } - - public function testReturnTypeIsRequest() { - $conn = $this->getMock('\Ratchet\ConnectionInterface'); - $return = $this->parser->onMessage($conn, "GET / HTTP/1.1\r\nHost: socketo.me\r\n\r\n"); - - $this->assertInstanceOf('\Psr\Http\Message\RequestInterface', $return); - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/tests/unit/Http/HttpServerTest.php b/digital_doctor/vendor/cboden/ratchet/tests/unit/Http/HttpServerTest.php deleted file mode 100644 index 7041d66..0000000 --- a/digital_doctor/vendor/cboden/ratchet/tests/unit/Http/HttpServerTest.php +++ /dev/null @@ -1,64 +0,0 @@ -_conn->httpHeadersReceived = true; - } - - public function getConnectionClassString() { - return '\Ratchet\ConnectionInterface'; - } - - public function getDecoratorClassString() { - return '\Ratchet\Http\HttpServer'; - } - - public function getComponentClassString() { - return '\Ratchet\Http\HttpServerInterface'; - } - - public function testOpen() { - $headers = "GET / HTTP/1.1\r\nHost: socketo.me\r\n\r\n"; - - $this->_conn->httpHeadersReceived = false; - $this->_app->expects($this->once())->method('onOpen')->with($this->isExpectedConnection()); - $this->_serv->onMessage($this->_conn, $headers); - } - - public function testOnMessageAfterHeaders() { - $headers = "GET / HTTP/1.1\r\nHost: socketo.me\r\n\r\n"; - $this->_conn->httpHeadersReceived = false; - $this->_serv->onMessage($this->_conn, $headers); - - $message = "Hello World!"; - $this->_app->expects($this->once())->method('onMessage')->with($this->isExpectedConnection(), $message); - $this->_serv->onMessage($this->_conn, $message); - } - - public function testBufferOverflow() { - $this->_conn->expects($this->once())->method('close'); - $this->_conn->httpHeadersReceived = false; - - $this->_serv->onMessage($this->_conn, str_repeat('a', 5000)); - } - - public function testCloseIfNotEstablished() { - $this->_conn->httpHeadersReceived = false; - $this->_conn->expects($this->once())->method('close'); - $this->_serv->onError($this->_conn, new \Exception('Whoops!')); - } - - public function testBufferHeaders() { - $this->_conn->httpHeadersReceived = false; - $this->_app->expects($this->never())->method('onOpen'); - $this->_app->expects($this->never())->method('onMessage'); - - $this->_serv->onMessage($this->_conn, "GET / HTTP/1.1"); - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/tests/unit/Http/OriginCheckTest.php b/digital_doctor/vendor/cboden/ratchet/tests/unit/Http/OriginCheckTest.php deleted file mode 100644 index c1c4012..0000000 --- a/digital_doctor/vendor/cboden/ratchet/tests/unit/Http/OriginCheckTest.php +++ /dev/null @@ -1,46 +0,0 @@ -_reqStub = $this->getMock('Psr\Http\Message\RequestInterface'); - $this->_reqStub->expects($this->any())->method('getHeader')->will($this->returnValue(['localhost'])); - - parent::setUp(); - - $this->_serv->allowedOrigins[] = 'localhost'; - } - - protected function doOpen($conn) { - $this->_serv->onOpen($conn, $this->_reqStub); - } - - public function getConnectionClassString() { - return '\Ratchet\ConnectionInterface'; - } - - public function getDecoratorClassString() { - return '\Ratchet\Http\OriginCheck'; - } - - public function getComponentClassString() { - return '\Ratchet\Http\HttpServerInterface'; - } - - public function testCloseOnNonMatchingOrigin() { - $this->_serv->allowedOrigins = ['socketo.me']; - $this->_conn->expects($this->once())->method('close'); - - $this->_serv->onOpen($this->_conn, $this->_reqStub); - } - - public function testOnMessage() { - $this->passthroughMessageTest('Hello World!'); - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/tests/unit/Http/RouterTest.php b/digital_doctor/vendor/cboden/ratchet/tests/unit/Http/RouterTest.php deleted file mode 100644 index 1ca4cbc..0000000 --- a/digital_doctor/vendor/cboden/ratchet/tests/unit/Http/RouterTest.php +++ /dev/null @@ -1,165 +0,0 @@ -_conn = $this->getMock('\Ratchet\ConnectionInterface'); - $this->_uri = $this->getMock('Psr\Http\Message\UriInterface'); - $this->_req = $this->getMock('\Psr\Http\Message\RequestInterface'); - $this->_req - ->expects($this->any()) - ->method('getUri') - ->will($this->returnValue($this->_uri)); - $this->_matcher = $this->getMock('Symfony\Component\Routing\Matcher\UrlMatcherInterface'); - $this->_matcher - ->expects($this->any()) - ->method('getContext') - ->will($this->returnValue($this->getMock('Symfony\Component\Routing\RequestContext'))); - $this->_router = new Router($this->_matcher); - - $this->_uri->expects($this->any())->method('getPath')->will($this->returnValue('ws://doesnt.matter/')); - $this->_uri->expects($this->any())->method('withQuery')->with($this->callback(function($val) { - $this->setResult($val); - - return true; - }))->will($this->returnSelf()); - $this->_uri->expects($this->any())->method('getQuery')->will($this->returnCallback([$this, 'getResult'])); - $this->_req->expects($this->any())->method('withUri')->will($this->returnSelf()); - } - - public function testFourOhFour() { - $this->_conn->expects($this->once())->method('close'); - - $nope = new ResourceNotFoundException; - $this->_matcher->expects($this->any())->method('match')->will($this->throwException($nope)); - - $this->_router->onOpen($this->_conn, $this->_req); - } - - public function testNullRequest() { - $this->setExpectedException('\UnexpectedValueException'); - $this->_router->onOpen($this->_conn); - } - - public function testControllerIsMessageComponentInterface() { - $this->setExpectedException('\UnexpectedValueException'); - $this->_matcher->expects($this->any())->method('match')->will($this->returnValue(array('_controller' => new \StdClass))); - $this->_router->onOpen($this->_conn, $this->_req); - } - - public function testControllerOnOpen() { - $controller = $this->getMockBuilder('\Ratchet\WebSocket\WsServer')->disableOriginalConstructor()->getMock(); - $this->_matcher->expects($this->any())->method('match')->will($this->returnValue(array('_controller' => $controller))); - $this->_router->onOpen($this->_conn, $this->_req); - - $expectedConn = new \PHPUnit_Framework_Constraint_IsInstanceOf('\Ratchet\ConnectionInterface'); - $controller->expects($this->once())->method('onOpen')->with($expectedConn, $this->_req); - - $this->_matcher->expects($this->any())->method('match')->will($this->returnValue(array('_controller' => $controller))); - $this->_router->onOpen($this->_conn, $this->_req); - } - - public function testControllerOnMessageBubbles() { - $message = "The greatest trick the Devil ever pulled was convincing the world he didn't exist"; - $controller = $this->getMockBuilder('\Ratchet\WebSocket\WsServer')->disableOriginalConstructor()->getMock(); - $controller->expects($this->once())->method('onMessage')->with($this->_conn, $message); - - $this->_conn->controller = $controller; - - $this->_router->onMessage($this->_conn, $message); - } - - public function testControllerOnCloseBubbles() { - $controller = $this->getMockBuilder('\Ratchet\WebSocket\WsServer')->disableOriginalConstructor()->getMock(); - $controller->expects($this->once())->method('onClose')->with($this->_conn); - - $this->_conn->controller = $controller; - - $this->_router->onClose($this->_conn); - } - - public function testControllerOnErrorBubbles() { - $e= new \Exception('One cannot be betrayed if one has no exceptions'); - $controller = $this->getMockBuilder('\Ratchet\WebSocket\WsServer')->disableOriginalConstructor()->getMock(); - $controller->expects($this->once())->method('onError')->with($this->_conn, $e); - - $this->_conn->controller = $controller; - - $this->_router->onError($this->_conn, $e); - } - - public function testRouterGeneratesRouteParameters() { - /** @var $controller WsServerInterface */ - $controller = $this->getMockBuilder('\Ratchet\WebSocket\WsServer')->disableOriginalConstructor()->getMock(); - /** @var $matcher UrlMatcherInterface */ - $this->_matcher->expects($this->any())->method('match')->will( - $this->returnValue(['_controller' => $controller, 'foo' => 'bar', 'baz' => 'qux']) - ); - $conn = $this->getMock('Ratchet\Mock\Connection'); - - $router = new Router($this->_matcher); - - $router->onOpen($conn, $this->_req); - - $this->assertEquals('foo=bar&baz=qux', $this->_req->getUri()->getQuery()); - } - - public function testQueryParams() { - $controller = $this->getMockBuilder('\Ratchet\WebSocket\WsServer')->disableOriginalConstructor()->getMock(); - $this->_matcher->expects($this->any())->method('match')->will( - $this->returnValue(['_controller' => $controller, 'foo' => 'bar', 'baz' => 'qux']) - ); - - $conn = $this->getMock('Ratchet\Mock\Connection'); - $request = $this->getMock('Psr\Http\Message\RequestInterface'); - $uri = new \GuzzleHttp\Psr7\Uri('ws://doesnt.matter/endpoint?hello=world&foo=nope'); - - $request->expects($this->any())->method('getUri')->will($this->returnCallback(function() use (&$uri) { - return $uri; - })); - $request->expects($this->any())->method('withUri')->with($this->callback(function($url) use (&$uri) { - $uri = $url; - - return true; - }))->will($this->returnSelf()); - - $router = new Router($this->_matcher); - $router->onOpen($conn, $request); - - $this->assertEquals('foo=nope&baz=qux&hello=world', $request->getUri()->getQuery()); - $this->assertEquals('ws', $request->getUri()->getScheme()); - $this->assertEquals('doesnt.matter', $request->getUri()->getHost()); - } - - public function testImpatientClientOverflow() { - $this->_conn->expects($this->once())->method('close'); - - $header = "GET /nope HTTP/1.1 -Upgrade: websocket -Connection: upgrade -Host: localhost -Origin: http://localhost -Sec-WebSocket-Version: 13\r\n\r\n"; - - $app = new HttpServer(new Router(new UrlMatcher(new RouteCollection, new RequestContext))); - $app->onOpen($this->_conn); - $app->onMessage($this->_conn, $header); - $app->onMessage($this->_conn, 'Silly body'); - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/tests/unit/Server/EchoServerTest.php b/digital_doctor/vendor/cboden/ratchet/tests/unit/Server/EchoServerTest.php deleted file mode 100644 index 47fb0e2..0000000 --- a/digital_doctor/vendor/cboden/ratchet/tests/unit/Server/EchoServerTest.php +++ /dev/null @@ -1,26 +0,0 @@ -_conn = $this->getMock('\Ratchet\ConnectionInterface'); - $this->_comp = new EchoServer; - } - - public function testMessageEchod() { - $message = 'Tillsonburg, my back still aches when I hear that word.'; - $this->_conn->expects($this->once())->method('send')->with($message); - $this->_comp->onMessage($this->_conn, $message); - } - - public function testErrorClosesConnection() { - ob_start(); - $this->_conn->expects($this->once())->method('close'); - $this->_comp->onError($this->_conn, new \Exception); - ob_end_clean(); - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/tests/unit/Server/FlashPolicyComponentTest.php b/digital_doctor/vendor/cboden/ratchet/tests/unit/Server/FlashPolicyComponentTest.php deleted file mode 100644 index 38fc96a..0000000 --- a/digital_doctor/vendor/cboden/ratchet/tests/unit/Server/FlashPolicyComponentTest.php +++ /dev/null @@ -1,152 +0,0 @@ -_policy = new FlashPolicy(); - } - - public function testPolicyRender() { - $this->_policy->setSiteControl('all'); - $this->_policy->addAllowedAccess('example.com', '*'); - $this->_policy->addAllowedAccess('dev.example.com', '*'); - - $this->assertInstanceOf('SimpleXMLElement', $this->_policy->renderPolicy()); - } - - public function testInvalidPolicyReader() { - $this->setExpectedException('UnexpectedValueException'); - $this->_policy->renderPolicy(); - } - - public function testInvalidDomainPolicyReader() { - $this->setExpectedException('UnexpectedValueException'); - $this->_policy->setSiteControl('all'); - $this->_policy->addAllowedAccess('dev.example.*', '*'); - $this->_policy->renderPolicy(); - } - - /** - * @dataProvider siteControl - */ - public function testSiteControlValidation($accept, $permittedCrossDomainPolicies) { - $this->assertEquals($accept, $this->_policy->validateSiteControl($permittedCrossDomainPolicies)); - } - - public static function siteControl() { - return array( - array(true, 'all') - , array(true, 'none') - , array(true, 'master-only') - , array(false, 'by-content-type') - , array(false, 'by-ftp-filename') - , array(false, '') - , array(false, 'all ') - , array(false, 'asdf') - , array(false, '@893830') - , array(false, '*') - ); - } - - /** - * @dataProvider URI - */ - public function testDomainValidation($accept, $domain) { - $this->assertEquals($accept, $this->_policy->validateDomain($domain)); - } - - public static function URI() { - return array( - array(true, '*') - , array(true, 'example.com') - , array(true, 'exam-ple.com') - , array(true, '*.example.com') - , array(true, 'www.example.com') - , array(true, 'dev.dev.example.com') - , array(true, 'http://example.com') - , array(true, 'https://example.com') - , array(true, 'http://*.example.com') - , array(false, 'exam*ple.com') - , array(true, '127.0.255.1') - , array(true, 'localhost') - , array(false, 'www.example.*') - , array(false, 'www.exa*le.com') - , array(false, 'www.example.*com') - , array(false, '*.example.*') - , array(false, 'gasldf*$#a0sdf0a8sdf') - ); - } - - /** - * @dataProvider ports - */ - public function testPortValidation($accept, $ports) { - $this->assertEquals($accept, $this->_policy->validatePorts($ports)); - } - - public static function ports() { - return array( - array(true, '*') - , array(true, '80') - , array(true, '80,443') - , array(true, '507,516-523') - , array(true, '507,516-523,333') - , array(true, '507,516-523,507,516-523') - , array(false, '516-') - , array(true, '516-523,11') - , array(false, '516,-523,11') - , array(false, 'example') - , array(false, 'asdf,123') - , array(false, '--') - , array(false, ',,,') - , array(false, '838*') - ); - } - - public function testAddAllowedAccessOnlyAcceptsValidPorts() { - $this->setExpectedException('UnexpectedValueException'); - - $this->_policy->addAllowedAccess('*', 'nope'); - } - - public function testSetSiteControlThrowsException() { - $this->setExpectedException('UnexpectedValueException'); - - $this->_policy->setSiteControl('nope'); - } - - public function testErrorClosesConnection() { - $conn = $this->getMock('\\Ratchet\\ConnectionInterface'); - $conn->expects($this->once())->method('close'); - - $this->_policy->onError($conn, new \Exception); - } - - public function testOnMessageSendsString() { - $this->_policy->addAllowedAccess('*', '*'); - - $conn = $this->getMock('\\Ratchet\\ConnectionInterface'); - $conn->expects($this->once())->method('send')->with($this->isType('string')); - - $this->_policy->onMessage($conn, ' '); - } - - public function testOnOpenExists() { - $this->assertTrue(method_exists($this->_policy, 'onOpen')); - $conn = $this->getMock('\Ratchet\ConnectionInterface'); - $this->_policy->onOpen($conn); - } - - public function testOnCloseExists() { - $this->assertTrue(method_exists($this->_policy, 'onClose')); - $conn = $this->getMock('\Ratchet\ConnectionInterface'); - $this->_policy->onClose($conn); - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/tests/unit/Server/IoConnectionTest.php b/digital_doctor/vendor/cboden/ratchet/tests/unit/Server/IoConnectionTest.php deleted file mode 100644 index 07130f6..0000000 --- a/digital_doctor/vendor/cboden/ratchet/tests/unit/Server/IoConnectionTest.php +++ /dev/null @@ -1,32 +0,0 @@ -sock = $this->getMock('\\React\\Socket\\ConnectionInterface'); - $this->conn = new IoConnection($this->sock); - } - - public function testCloseBubbles() { - $this->sock->expects($this->once())->method('end'); - $this->conn->close(); - } - - public function testSendBubbles() { - $msg = '6 hour rides are productive'; - - $this->sock->expects($this->once())->method('write')->with($msg); - $this->conn->send($msg); - } - - public function testSendReturnsSelf() { - $this->assertSame($this->conn, $this->conn->send('fluent interface')); - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/tests/unit/Server/IoServerTest.php b/digital_doctor/vendor/cboden/ratchet/tests/unit/Server/IoServerTest.php deleted file mode 100644 index e20115f..0000000 --- a/digital_doctor/vendor/cboden/ratchet/tests/unit/Server/IoServerTest.php +++ /dev/null @@ -1,127 +0,0 @@ -futureTick(function () use ($loop) { - $loop->stop(); - }); - - $loop->run(); - } - - public function setUp() { - $this->app = $this->getMock('\\Ratchet\\MessageComponentInterface'); - - $loop = new StreamSelectLoop; - $this->reactor = new Server(0, $loop); - - $uri = $this->reactor->getAddress(); - $this->port = parse_url((strpos($uri, '://') === false ? 'tcp://' : '') . $uri, PHP_URL_PORT); - $this->server = new IoServer($this->app, $this->reactor, $loop); - } - - public function testOnOpen() { - $this->app->expects($this->once())->method('onOpen')->with($this->isInstanceOf('\\Ratchet\\ConnectionInterface')); - - $client = stream_socket_client("tcp://localhost:{$this->port}"); - - $this->tickLoop($this->server->loop); - - //$this->assertTrue(is_string($this->app->last['onOpen'][0]->remoteAddress)); - //$this->assertTrue(is_int($this->app->last['onOpen'][0]->resourceId)); - } - - public function testOnData() { - $msg = 'Hello World!'; - - $this->app->expects($this->once())->method('onMessage')->with( - $this->isInstanceOf('\\Ratchet\\ConnectionInterface') - , $msg - ); - - $client = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); - socket_set_option($client, SOL_SOCKET, SO_REUSEADDR, 1); - socket_set_option($client, SOL_SOCKET, SO_SNDBUF, 4096); - socket_set_block($client); - socket_connect($client, 'localhost', $this->port); - - $this->tickLoop($this->server->loop); - - socket_write($client, $msg); - $this->tickLoop($this->server->loop); - - socket_shutdown($client, 1); - socket_shutdown($client, 0); - socket_close($client); - - $this->tickLoop($this->server->loop); - } - - public function testOnClose() { - $this->app->expects($this->once())->method('onClose')->with($this->isInstanceOf('\\Ratchet\\ConnectionInterface')); - - $client = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); - socket_set_option($client, SOL_SOCKET, SO_REUSEADDR, 1); - socket_set_option($client, SOL_SOCKET, SO_SNDBUF, 4096); - socket_set_block($client); - socket_connect($client, 'localhost', $this->port); - - $this->tickLoop($this->server->loop); - - socket_shutdown($client, 1); - socket_shutdown($client, 0); - socket_close($client); - - $this->tickLoop($this->server->loop); - } - - public function testFactory() { - $this->assertInstanceOf('\\Ratchet\\Server\\IoServer', IoServer::factory($this->app, 0)); - } - - public function testNoLoopProvidedError() { - $this->setExpectedException('RuntimeException'); - - $io = new IoServer($this->app, $this->reactor); - $io->run(); - } - - public function testOnErrorPassesException() { - $conn = $this->getMock('\\React\\Socket\\ConnectionInterface'); - $conn->decor = $this->getMock('\\Ratchet\\ConnectionInterface'); - $err = new \Exception("Nope"); - - $this->app->expects($this->once())->method('onError')->with($conn->decor, $err); - - $this->server->handleError($err, $conn); - } - - public function onErrorCalledWhenExceptionThrown() { - $this->markTestIncomplete("Need to learn how to throw an exception from a mock"); - - $conn = $this->getMock('\\React\\Socket\\ConnectionInterface'); - $this->server->handleConnect($conn); - - $e = new \Exception; - $this->app->expects($this->once())->method('onMessage')->with($this->isInstanceOf('\\Ratchet\\ConnectionInterface'), 'f')->will($e); - $this->app->expects($this->once())->method('onError')->with($this->instanceOf('\\Ratchet\\ConnectionInterface', $e)); - - $this->server->handleData('f', $conn); - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/tests/unit/Server/IpBlackListComponentTest.php b/digital_doctor/vendor/cboden/ratchet/tests/unit/Server/IpBlackListComponentTest.php deleted file mode 100644 index 90f4185..0000000 --- a/digital_doctor/vendor/cboden/ratchet/tests/unit/Server/IpBlackListComponentTest.php +++ /dev/null @@ -1,125 +0,0 @@ -mock = $this->getMock('\\Ratchet\\MessageComponentInterface'); - $this->blocker = new IpBlackList($this->mock); - } - - public function testOnOpen() { - $this->mock->expects($this->exactly(3))->method('onOpen'); - - $conn1 = $this->newConn(); - $conn2 = $this->newConn(); - $conn3 = $this->newConn(); - - $this->blocker->onOpen($conn1); - $this->blocker->onOpen($conn3); - $this->blocker->onOpen($conn2); - } - - public function testBlockDoesNotTriggerOnOpen() { - $conn = $this->newConn(); - - $this->blocker->blockAddress($conn->remoteAddress); - - $this->mock->expects($this->never())->method('onOpen'); - - $ret = $this->blocker->onOpen($conn); - } - - public function testBlockDoesNotTriggerOnClose() { - $conn = $this->newConn(); - - $this->blocker->blockAddress($conn->remoteAddress); - - $this->mock->expects($this->never())->method('onClose'); - - $ret = $this->blocker->onOpen($conn); - } - - public function testOnMessageDecoration() { - $conn = $this->newConn(); - $msg = 'Hello not being blocked'; - - $this->mock->expects($this->once())->method('onMessage')->with($conn, $msg); - - $this->blocker->onMessage($conn, $msg); - } - - public function testOnCloseDecoration() { - $conn = $this->newConn(); - - $this->mock->expects($this->once())->method('onClose')->with($conn); - - $this->blocker->onClose($conn); - } - - public function testBlockClosesConnection() { - $conn = $this->newConn(); - $this->blocker->blockAddress($conn->remoteAddress); - - $conn->expects($this->once())->method('close'); - - $this->blocker->onOpen($conn); - } - - public function testAddAndRemoveWithFluentInterfaces() { - $blockOne = '127.0.0.1'; - $blockTwo = '192.168.1.1'; - $unblock = '75.119.207.140'; - - $this->blocker - ->blockAddress($unblock) - ->blockAddress($blockOne) - ->unblockAddress($unblock) - ->blockAddress($blockTwo) - ; - - $this->assertEquals(array($blockOne, $blockTwo), $this->blocker->getBlockedAddresses()); - } - - public function testDecoratorPassesErrors() { - $conn = $this->newConn(); - $e = new \Exception('I threw an error'); - - $this->mock->expects($this->once())->method('onError')->with($conn, $e); - - $this->blocker->onError($conn, $e); - } - - public function addressProvider() { - return array( - array('127.0.0.1', '127.0.0.1') - , array('localhost', 'localhost') - , array('fe80::1%lo0', 'fe80::1%lo0') - , array('127.0.0.1', '127.0.0.1:6392') - ); - } - - /** - * @dataProvider addressProvider - */ - public function testFilterAddress($expected, $input) { - $this->assertEquals($expected, $this->blocker->filterAddress($input)); - } - - public function testUnblockingSilentlyFails() { - $this->assertInstanceOf('\\Ratchet\\Server\\IpBlackList', $this->blocker->unblockAddress('localhost')); - } - - protected function newConn() { - $conn = $this->getMock('\\Ratchet\\ConnectionInterface'); - $conn->remoteAddress = '127.0.0.1'; - - return $conn; - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/tests/unit/Session/Serialize/PhpHandlerTest.php b/digital_doctor/vendor/cboden/ratchet/tests/unit/Session/Serialize/PhpHandlerTest.php deleted file mode 100644 index 4acf5bc..0000000 --- a/digital_doctor/vendor/cboden/ratchet/tests/unit/Session/Serialize/PhpHandlerTest.php +++ /dev/null @@ -1,43 +0,0 @@ -_handler = new PhpHandler; - } - - public function serializedProvider() { - return array( - array( - '_sf2_attributes|a:2:{s:5:"hello";s:5:"world";s:4:"last";i:1332872102;}_sf2_flashes|a:0:{}' - , array( - '_sf2_attributes' => array( - 'hello' => 'world' - , 'last' => 1332872102 - ) - , '_sf2_flashes' => array() - ) - ) - ); - } - - /** - * @dataProvider serializedProvider - */ - public function testUnserialize($in, $expected) { - $this->assertEquals($expected, $this->_handler->unserialize($in)); - } - - /** - * @dataProvider serializedProvider - */ - public function testSerialize($serialized, $original) { - $this->assertEquals($serialized, $this->_handler->serialize($original)); - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/tests/unit/Session/SessionComponentTest.php b/digital_doctor/vendor/cboden/ratchet/tests/unit/Session/SessionComponentTest.php deleted file mode 100644 index ea452db..0000000 --- a/digital_doctor/vendor/cboden/ratchet/tests/unit/Session/SessionComponentTest.php +++ /dev/null @@ -1,126 +0,0 @@ -markTestIncomplete('Test needs to be updated for ini_set issue in PHP 7.2'); - - if (!class_exists('Symfony\Component\HttpFoundation\Session\Session')) { - return $this->markTestSkipped('Dependency of Symfony HttpFoundation failed'); - } - - parent::setUp(); - $this->_serv = new SessionProvider($this->_app, new NullSessionHandler); - } - - public function tearDown() { - ini_set('session.serialize_handler', 'php'); - } - - public function getConnectionClassString() { - return '\Ratchet\ConnectionInterface'; - } - - public function getDecoratorClassString() { - return '\Ratchet\NullComponent'; - } - - public function getComponentClassString() { - return '\Ratchet\Http\HttpServerInterface'; - } - - public function classCaseProvider() { - return array( - array('php', 'Php') - , array('php_binary', 'PhpBinary') - ); - } - - /** - * @dataProvider classCaseProvider - */ - public function testToClassCase($in, $out) { - $ref = new \ReflectionClass('\\Ratchet\\Session\\SessionProvider'); - $method = $ref->getMethod('toClassCase'); - $method->setAccessible(true); - - $component = new SessionProvider($this->getMock($this->getComponentClassString()), $this->getMock('\SessionHandlerInterface')); - $this->assertEquals($out, $method->invokeArgs($component, array($in))); - } - - /** - * I think I have severely butchered this test...it's not so much of a unit test as it is a full-fledged component test - */ - public function testConnectionValueFromPdo() { - if (!extension_loaded('PDO') || !extension_loaded('pdo_sqlite')) { - return $this->markTestSkipped('Session test requires PDO and pdo_sqlite'); - } - - $sessionId = md5('testSession'); - - $dbOptions = array( - 'db_table' => 'sessions' - , 'db_id_col' => 'sess_id' - , 'db_data_col' => 'sess_data' - , 'db_time_col' => 'sess_time' - , 'db_lifetime_col' => 'sess_lifetime' - ); - - $pdo = new \PDO("sqlite::memory:"); - $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); - $pdo->exec(vsprintf("CREATE TABLE %s (%s TEXT NOT NULL PRIMARY KEY, %s BLOB NOT NULL, %s INTEGER NOT NULL, %s INTEGER)", $dbOptions)); - - $pdoHandler = new PdoSessionHandler($pdo, $dbOptions); - $pdoHandler->write($sessionId, '_sf2_attributes|a:2:{s:5:"hello";s:5:"world";s:4:"last";i:1332872102;}_sf2_flashes|a:0:{}'); - - $component = new SessionProvider($this->getMock($this->getComponentClassString()), $pdoHandler, array('auto_start' => 1)); - $connection = $this->getMock('Ratchet\\ConnectionInterface'); - - $headers = $this->getMock('Psr\Http\Message\RequestInterface'); - $headers->expects($this->once())->method('getHeader')->will($this->returnValue([ini_get('session.name') . "={$sessionId};"])); - - $component->onOpen($connection, $headers); - - $this->assertEquals('world', $connection->Session->get('hello')); - } - - protected function newConn() { - $conn = $this->getMock('Ratchet\ConnectionInterface'); - - $headers = $this->getMock('Psr\Http\Message\Request', array('getCookie'), array('POST', '/', array())); - $headers->expects($this->once())->method('getCookie', array(ini_get('session.name')))->will($this->returnValue(null)); - - return $conn; - } - - public function testOnMessageDecorator() { - $message = "Database calls are usually blocking :("; - $this->_app->expects($this->once())->method('onMessage')->with($this->isExpectedConnection(), $message); - $this->_serv->onMessage($this->_conn, $message); - } - - public function testRejectInvalidSeralizers() { - if (!function_exists('wddx_serialize_value')) { - $this->markTestSkipped(); - } - - ini_set('session.serialize_handler', 'wddx'); - $this->setExpectedException('\RuntimeException'); - new SessionProvider($this->getMock($this->getComponentClassString()), $this->getMock('\SessionHandlerInterface')); - } - - protected function doOpen($conn) { - $request = $this->getMock('Psr\Http\Message\RequestInterface'); - $request->expects($this->any())->method('getHeader')->will($this->returnValue([])); - - $this->_serv->onOpen($conn, $request); - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/tests/unit/Session/Storage/VirtualSessionStoragePDOTest.php b/digital_doctor/vendor/cboden/ratchet/tests/unit/Session/Storage/VirtualSessionStoragePDOTest.php deleted file mode 100644 index 2727484..0000000 --- a/digital_doctor/vendor/cboden/ratchet/tests/unit/Session/Storage/VirtualSessionStoragePDOTest.php +++ /dev/null @@ -1,53 +0,0 @@ -markTestSkipped('Session test requires PDO and pdo_sqlite'); - } - - $schema = <<_pathToDB = tempnam(sys_get_temp_dir(), 'SQ3');; - $dsn = 'sqlite:' . $this->_pathToDB; - - $pdo = new \PDO($dsn); - $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); - $pdo->exec($schema); - $pdo = null; - - $sessionHandler = new PdoSessionHandler($dsn); - $serializer = new PhpHandler(); - $this->_virtualSessionStorage = new VirtualSessionStorage($sessionHandler, 'foobar', $serializer); - $this->_virtualSessionStorage->registerBag(new FlashBag()); - $this->_virtualSessionStorage->registerBag(new AttributeBag()); - } - - public function tearDown() { - unlink($this->_pathToDB); - } - - public function testStartWithDSN() { - $this->_virtualSessionStorage->start(); - - $this->assertTrue($this->_virtualSessionStorage->isStarted()); - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/tests/unit/Wamp/ServerProtocolTest.php b/digital_doctor/vendor/cboden/ratchet/tests/unit/Wamp/ServerProtocolTest.php deleted file mode 100644 index 8ff68c2..0000000 --- a/digital_doctor/vendor/cboden/ratchet/tests/unit/Wamp/ServerProtocolTest.php +++ /dev/null @@ -1,295 +0,0 @@ -_app = new TestComponent; - $this->_comp = new ServerProtocol($this->_app); - } - - protected function newConn() { - return new Connection; - } - - public function invalidMessageProvider() { - return [ - [0] - , [3] - , [4] - , [8] - , [9] - ]; - } - - /** - * @dataProvider invalidMessageProvider - */ - public function testInvalidMessages($type) { - $this->setExpectedException('\Ratchet\Wamp\Exception'); - - $conn = $this->newConn(); - $this->_comp->onOpen($conn); - $this->_comp->onMessage($conn, json_encode([$type])); - } - - public function testWelcomeMessage() { - $conn = $this->newConn(); - - $this->_comp->onOpen($conn); - - $message = $conn->last['send']; - $json = json_decode($message); - - $this->assertEquals(4, count($json)); - $this->assertEquals(0, $json[0]); - $this->assertTrue(is_string($json[1])); - $this->assertEquals(1, $json[2]); - } - - public function testSubscribe() { - $uri = 'http://example.com'; - $clientMessage = array(5, $uri); - - $conn = $this->newConn(); - - $this->_comp->onOpen($conn); - $this->_comp->onMessage($conn, json_encode($clientMessage)); - - $this->assertEquals($uri, $this->_app->last['onSubscribe'][1]); - } - - public function testUnSubscribe() { - $uri = 'http://example.com/endpoint'; - $clientMessage = array(6, $uri); - - $conn = $this->newConn(); - - $this->_comp->onOpen($conn); - $this->_comp->onMessage($conn, json_encode($clientMessage)); - - $this->assertEquals($uri, $this->_app->last['onUnSubscribe'][1]); - } - - public function callProvider() { - return [ - [2, 'a', 'b'] - , [2, ['a', 'b']] - , [1, 'one'] - , [3, 'one', 'two', 'three'] - , [3, ['un', 'deux', 'trois']] - , [2, 'hi', ['hello', 'world']] - , [2, ['hello', 'world'], 'hi'] - , [2, ['hello' => 'world', 'herp' => 'derp']] - ]; - } - - /** - * @dataProvider callProvider - */ - public function testCall() { - $args = func_get_args(); - $paramNum = array_shift($args); - - $uri = 'http://example.com/endpoint/' . rand(1, 100); - $id = uniqid('', false); - $clientMessage = array_merge(array(2, $id, $uri), $args); - - $conn = $this->newConn(); - - $this->_comp->onOpen($conn); - $this->_comp->onMessage($conn, json_encode($clientMessage)); - - $this->assertEquals($id, $this->_app->last['onCall'][1]); - $this->assertEquals($uri, $this->_app->last['onCall'][2]); - - $this->assertEquals($paramNum, count($this->_app->last['onCall'][3])); - } - - public function testPublish() { - $conn = $this->newConn(); - - $topic = 'pubsubhubbub'; - $event = 'Here I am, publishing data'; - - $clientMessage = array(7, $topic, $event); - - $this->_comp->onOpen($conn); - $this->_comp->onMessage($conn, json_encode($clientMessage)); - - $this->assertEquals($topic, $this->_app->last['onPublish'][1]); - $this->assertEquals($event, $this->_app->last['onPublish'][2]); - $this->assertEquals(array(), $this->_app->last['onPublish'][3]); - $this->assertEquals(array(), $this->_app->last['onPublish'][4]); - } - - public function testPublishAndExcludeMe() { - $conn = $this->newConn(); - - $this->_comp->onOpen($conn); - $this->_comp->onMessage($conn, json_encode(array(7, 'topic', 'event', true))); - - $this->assertEquals($conn->WAMP->sessionId, $this->_app->last['onPublish'][3][0]); - } - - public function testPublishAndEligible() { - $conn = $this->newConn(); - - $buddy = uniqid('', false); - $friend = uniqid('', false); - - $this->_comp->onOpen($conn); - $this->_comp->onMessage($conn, json_encode(array(7, 'topic', 'event', false, array($buddy, $friend)))); - - $this->assertEquals(array(), $this->_app->last['onPublish'][3]); - $this->assertEquals(2, count($this->_app->last['onPublish'][4])); - } - - public function eventProvider() { - return array( - array('http://example.com', array('one', 'two')) - , array('curie', array(array('hello' => 'world', 'herp' => 'derp'))) - ); - } - - /** - * @dataProvider eventProvider - */ - public function testEvent($topic, $payload) { - $conn = new WampConnection($this->newConn()); - $conn->event($topic, $payload); - - $eventString = $conn->last['send']; - - $this->assertSame(array(8, $topic, $payload), json_decode($eventString, true)); - } - - public function testOnClosePropagation() { - $conn = new Connection; - - $this->_comp->onOpen($conn); - $this->_comp->onClose($conn); - - $class = new \ReflectionClass('\\Ratchet\\Wamp\\WampConnection'); - $method = $class->getMethod('getConnection'); - $method->setAccessible(true); - - $check = $method->invokeArgs($this->_app->last['onClose'][0], array()); - - $this->assertSame($conn, $check); - } - - public function testOnErrorPropagation() { - $conn = new Connection; - - $e = new \Exception('Nope'); - - $this->_comp->onOpen($conn); - $this->_comp->onError($conn, $e); - - $class = new \ReflectionClass('\\Ratchet\\Wamp\\WampConnection'); - $method = $class->getMethod('getConnection'); - $method->setAccessible(true); - - $check = $method->invokeArgs($this->_app->last['onError'][0], array()); - - $this->assertSame($conn, $check); - $this->assertSame($e, $this->_app->last['onError'][1]); - } - - public function testPrefix() { - $conn = new WampConnection($this->newConn()); - $this->_comp->onOpen($conn); - - $prefix = 'incoming'; - $fullURI = "http://example.com/$prefix"; - $method = 'call'; - - $this->_comp->onMessage($conn, json_encode(array(1, $prefix, $fullURI))); - - $this->assertEquals($fullURI, $conn->WAMP->prefixes[$prefix]); - $this->assertEquals("$fullURI#$method", $conn->getUri("$prefix:$method")); - } - - public function testMessageMustBeJson() { - $this->setExpectedException('\\Ratchet\\Wamp\\JsonException'); - - $conn = new Connection; - - $this->_comp->onOpen($conn); - $this->_comp->onMessage($conn, 'Hello World!'); - } - - public function testGetSubProtocolsReturnsArray() { - $this->assertTrue(is_array($this->_comp->getSubProtocols())); - } - - public function testGetSubProtocolsGetFromApp() { - $this->_app->protocols = array('hello', 'world'); - - $this->assertGreaterThanOrEqual(3, count($this->_comp->getSubProtocols())); - } - - public function testWampOnMessageApp() { - $app = $this->getMock('\\Ratchet\\Wamp\\WampServerInterface'); - $wamp = new ServerProtocol($app); - - $this->assertContains('wamp', $wamp->getSubProtocols()); - } - - public function badFormatProvider() { - return array( - array(json_encode(true)) - , array('{"valid":"json", "invalid": "message"}') - , array('{"0": "fail", "hello": "world"}') - ); - } - - /** - * @dataProvider badFormatProvider - */ - public function testValidJsonButInvalidProtocol($message) { - $this->setExpectedException('\Ratchet\Wamp\Exception'); - - $conn = $this->newConn(); - $this->_comp->onOpen($conn); - $this->_comp->onMessage($conn, $message); - } - - public function testBadClientInputFromNonStringTopic() { - $this->setExpectedException('\Ratchet\Wamp\Exception'); - - $conn = new WampConnection($this->newConn()); - $this->_comp->onOpen($conn); - - $this->_comp->onMessage($conn, json_encode([5, ['hells', 'nope']])); - } - - public function testBadPrefixWithNonStringTopic() { - $this->setExpectedException('\Ratchet\Wamp\Exception'); - - $conn = new WampConnection($this->newConn()); - $this->_comp->onOpen($conn); - - $this->_comp->onMessage($conn, json_encode([1, ['hells', 'nope'], ['bad', 'input']])); - } - - public function testBadPublishWithNonStringTopic() { - $this->setExpectedException('\Ratchet\Wamp\Exception'); - - $conn = new WampConnection($this->newConn()); - $this->_comp->onOpen($conn); - - $this->_comp->onMessage($conn, json_encode([7, ['bad', 'input'], 'Hider'])); - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/tests/unit/Wamp/TopicManagerTest.php b/digital_doctor/vendor/cboden/ratchet/tests/unit/Wamp/TopicManagerTest.php deleted file mode 100644 index b21b6bc..0000000 --- a/digital_doctor/vendor/cboden/ratchet/tests/unit/Wamp/TopicManagerTest.php +++ /dev/null @@ -1,226 +0,0 @@ -conn = $this->getMock('\Ratchet\ConnectionInterface'); - $this->mock = $this->getMock('\Ratchet\Wamp\WampServerInterface'); - $this->mngr = new TopicManager($this->mock); - - $this->conn->WAMP = new \StdClass; - $this->mngr->onOpen($this->conn); - } - - public function testGetTopicReturnsTopicObject() { - $class = new \ReflectionClass('Ratchet\Wamp\TopicManager'); - $method = $class->getMethod('getTopic'); - $method->setAccessible(true); - - $topic = $method->invokeArgs($this->mngr, array('The Topic')); - - $this->assertInstanceOf('Ratchet\Wamp\Topic', $topic); - } - - public function testGetTopicCreatesTopicWithSameName() { - $name = 'The Topic'; - - $class = new \ReflectionClass('Ratchet\Wamp\TopicManager'); - $method = $class->getMethod('getTopic'); - $method->setAccessible(true); - - $topic = $method->invokeArgs($this->mngr, array($name)); - - $this->assertEquals($name, $topic->getId()); - } - - public function testGetTopicReturnsSameObject() { - $class = new \ReflectionClass('Ratchet\Wamp\TopicManager'); - $method = $class->getMethod('getTopic'); - $method->setAccessible(true); - - $topic = $method->invokeArgs($this->mngr, array('No copy')); - $again = $method->invokeArgs($this->mngr, array('No copy')); - - $this->assertSame($topic, $again); - } - - public function testOnOpen() { - $this->mock->expects($this->once())->method('onOpen'); - $this->mngr->onOpen($this->conn); - } - - public function testOnCall() { - $id = uniqid(); - - $this->mock->expects($this->once())->method('onCall')->with( - $this->conn - , $id - , $this->isInstanceOf('Ratchet\Wamp\Topic') - , array() - ); - - $this->mngr->onCall($this->conn, $id, 'new topic', array()); - } - - public function testOnSubscribeCreatesTopicObject() { - $this->mock->expects($this->once())->method('onSubscribe')->with( - $this->conn, $this->isInstanceOf('Ratchet\Wamp\Topic') - ); - - $this->mngr->onSubscribe($this->conn, 'new topic'); - } - - public function testTopicIsInConnectionOnSubscribe() { - $name = 'New Topic'; - - $class = new \ReflectionClass('Ratchet\Wamp\TopicManager'); - $method = $class->getMethod('getTopic'); - $method->setAccessible(true); - - $topic = $method->invokeArgs($this->mngr, array($name)); - - $this->mngr->onSubscribe($this->conn, $name); - - $this->assertTrue($this->conn->WAMP->subscriptions->contains($topic)); - } - - public function testDoubleSubscriptionFiresOnce() { - $this->mock->expects($this->exactly(1))->method('onSubscribe'); - - $this->mngr->onSubscribe($this->conn, 'same topic'); - $this->mngr->onSubscribe($this->conn, 'same topic'); - } - - public function testUnsubscribeEvent() { - $name = 'in and out'; - $this->mock->expects($this->once())->method('onUnsubscribe')->with( - $this->conn, $this->isInstanceOf('Ratchet\Wamp\Topic') - ); - - $this->mngr->onSubscribe($this->conn, $name); - $this->mngr->onUnsubscribe($this->conn, $name); - } - - public function testUnsubscribeFiresOnce() { - $name = 'getting sleepy'; - $this->mock->expects($this->exactly(1))->method('onUnsubscribe'); - - $this->mngr->onSubscribe($this->conn, $name); - $this->mngr->onUnsubscribe($this->conn, $name); - $this->mngr->onUnsubscribe($this->conn, $name); - } - - public function testUnsubscribeRemovesTopicFromConnection() { - $name = 'Bye Bye Topic'; - - $class = new \ReflectionClass('Ratchet\Wamp\TopicManager'); - $method = $class->getMethod('getTopic'); - $method->setAccessible(true); - - $topic = $method->invokeArgs($this->mngr, array($name)); - - $this->mngr->onSubscribe($this->conn, $name); - $this->mngr->onUnsubscribe($this->conn, $name); - - $this->assertFalse($this->conn->WAMP->subscriptions->contains($topic)); - } - - public function testOnPublishBubbles() { - $msg = 'Cover all the code!'; - - $this->mock->expects($this->once())->method('onPublish')->with( - $this->conn - , $this->isInstanceOf('Ratchet\Wamp\Topic') - , $msg - , $this->isType('array') - , $this->isType('array') - ); - - $this->mngr->onPublish($this->conn, 'topic coverage', $msg, array(), array()); - } - - public function testOnCloseBubbles() { - $this->mock->expects($this->once())->method('onClose')->with($this->conn); - $this->mngr->onClose($this->conn); - } - - protected function topicProvider($name) { - $class = new \ReflectionClass('Ratchet\Wamp\TopicManager'); - $method = $class->getMethod('getTopic'); - $method->setAccessible(true); - - $attribute = $class->getProperty('topicLookup'); - $attribute->setAccessible(true); - - $topic = $method->invokeArgs($this->mngr, array($name)); - - return array($topic, $attribute); - } - - public function testConnIsRemovedFromTopicOnClose() { - $name = 'State Testing'; - list($topic, $attribute) = $this->topicProvider($name); - - $this->assertCount(1, $attribute->getValue($this->mngr)); - - $this->mngr->onSubscribe($this->conn, $name); - $this->mngr->onClose($this->conn); - - $this->assertFalse($topic->has($this->conn)); - } - - public static function topicConnExpectationProvider() { - return [ - [ 'onClose', 0] - , ['onUnsubscribe', 0] - ]; - } - - /** - * @dataProvider topicConnExpectationProvider - */ - public function testTopicRetentionFromLeavingConnections($methodCall, $expectation) { - $topicName = 'checkTopic'; - list($topic, $attribute) = $this->topicProvider($topicName); - - $this->mngr->onSubscribe($this->conn, $topicName); - call_user_func_array(array($this->mngr, $methodCall), array($this->conn, $topicName)); - - $this->assertCount($expectation, $attribute->getValue($this->mngr)); - } - - public function testOnErrorBubbles() { - $e = new \Exception('All work and no play makes Chris a dull boy'); - $this->mock->expects($this->once())->method('onError')->with($this->conn, $e); - - $this->mngr->onError($this->conn, $e); - } - - public function testGetSubProtocolsReturnsArray() { - $this->assertInternalType('array', $this->mngr->getSubProtocols()); - } - - public function testGetSubProtocolsBubbles() { - $subs = array('hello', 'world'); - $app = $this->getMock('Ratchet\Wamp\Stub\WsWampServerInterface'); - $app->expects($this->once())->method('getSubProtocols')->will($this->returnValue($subs)); - $mngr = new TopicManager($app); - - $this->assertEquals($subs, $mngr->getSubProtocols()); - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/tests/unit/Wamp/TopicTest.php b/digital_doctor/vendor/cboden/ratchet/tests/unit/Wamp/TopicTest.php deleted file mode 100644 index b8685b7..0000000 --- a/digital_doctor/vendor/cboden/ratchet/tests/unit/Wamp/TopicTest.php +++ /dev/null @@ -1,164 +0,0 @@ -assertEquals($id, $topic->getId()); - } - - public function testAddAndCount() { - $topic = new Topic('merp'); - - $topic->add($this->newConn()); - $topic->add($this->newConn()); - $topic->add($this->newConn()); - - $this->assertEquals(3, count($topic)); - } - - public function testRemove() { - $topic = new Topic('boop'); - $tracked = $this->newConn(); - - $topic->add($this->newConn()); - $topic->add($tracked); - $topic->add($this->newConn()); - - $topic->remove($tracked); - - $this->assertEquals(2, count($topic)); - } - - public function testBroadcast() { - $msg = 'Hello World!'; - $name = 'Batman'; - $protocol = json_encode(array(8, $name, $msg)); - - $first = $this->getMock('Ratchet\\Wamp\\WampConnection', array('send'), array($this->getMock('\\Ratchet\\ConnectionInterface'))); - $second = $this->getMock('Ratchet\\Wamp\\WampConnection', array('send'), array($this->getMock('\\Ratchet\\ConnectionInterface'))); - - $first->expects($this->once()) - ->method('send') - ->with($this->equalTo($protocol)); - - $second->expects($this->once()) - ->method('send') - ->with($this->equalTo($protocol)); - - $topic = new Topic($name); - $topic->add($first); - $topic->add($second); - - $topic->broadcast($msg); - } - - public function testBroadcastWithExclude() { - $msg = 'Hello odd numbers'; - $name = 'Excluding'; - $protocol = json_encode(array(8, $name, $msg)); - - $first = $this->getMock('Ratchet\\Wamp\\WampConnection', array('send'), array($this->getMock('\\Ratchet\\ConnectionInterface'))); - $second = $this->getMock('Ratchet\\Wamp\\WampConnection', array('send'), array($this->getMock('\\Ratchet\\ConnectionInterface'))); - $third = $this->getMock('Ratchet\\Wamp\\WampConnection', array('send'), array($this->getMock('\\Ratchet\\ConnectionInterface'))); - - $first->expects($this->once()) - ->method('send') - ->with($this->equalTo($protocol)); - - $second->expects($this->never())->method('send'); - - $third->expects($this->once()) - ->method('send') - ->with($this->equalTo($protocol)); - - $topic = new Topic($name); - $topic->add($first); - $topic->add($second); - $topic->add($third); - - $topic->broadcast($msg, array($second->WAMP->sessionId)); - } - - public function testBroadcastWithEligible() { - $msg = 'Hello white list'; - $name = 'Eligible'; - $protocol = json_encode(array(8, $name, $msg)); - - $first = $this->getMock('Ratchet\\Wamp\\WampConnection', array('send'), array($this->getMock('\\Ratchet\\ConnectionInterface'))); - $second = $this->getMock('Ratchet\\Wamp\\WampConnection', array('send'), array($this->getMock('\\Ratchet\\ConnectionInterface'))); - $third = $this->getMock('Ratchet\\Wamp\\WampConnection', array('send'), array($this->getMock('\\Ratchet\\ConnectionInterface'))); - - $first->expects($this->once()) - ->method('send') - ->with($this->equalTo($protocol)); - - $second->expects($this->never())->method('send'); - - $third->expects($this->once()) - ->method('send') - ->with($this->equalTo($protocol)); - - $topic = new Topic($name); - $topic->add($first); - $topic->add($second); - $topic->add($third); - - $topic->broadcast($msg, array(), array($first->WAMP->sessionId, $third->WAMP->sessionId)); - } - - public function testIterator() { - $first = $this->newConn(); - $second = $this->newConn(); - $third = $this->newConn(); - - $topic = new Topic('Joker'); - $topic->add($first)->add($second)->add($third); - - $check = array($first, $second, $third); - - foreach ($topic as $mock) { - $this->assertNotSame(false, array_search($mock, $check)); - } - } - - public function testToString() { - $name = 'Bane'; - $topic = new Topic($name); - - $this->assertEquals($name, (string)$topic); - } - - public function testDoesHave() { - $conn = $this->newConn(); - $topic = new Topic('Two Face'); - $topic->add($conn); - - $this->assertTrue($topic->has($conn)); - } - - public function testDoesNotHave() { - $conn = $this->newConn(); - $topic = new Topic('Alfred'); - - $this->assertFalse($topic->has($conn)); - } - - public function testDoesNotHaveAfterRemove() { - $conn = $this->newConn(); - $topic = new Topic('Ras'); - - $topic->add($conn)->remove($conn); - - $this->assertFalse($topic->has($conn)); - } - - protected function newConn() { - return new WampConnection($this->getMock('\\Ratchet\\ConnectionInterface')); - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/tests/unit/Wamp/WampConnectionTest.php b/digital_doctor/vendor/cboden/ratchet/tests/unit/Wamp/WampConnectionTest.php deleted file mode 100644 index adf59d5..0000000 --- a/digital_doctor/vendor/cboden/ratchet/tests/unit/Wamp/WampConnectionTest.php +++ /dev/null @@ -1,77 +0,0 @@ -mock = $this->getMock('\\Ratchet\\ConnectionInterface'); - $this->conn = new WampConnection($this->mock); - } - - public function testCallResult() { - $callId = uniqid(); - $data = array('hello' => 'world', 'herp' => 'derp'); - - $this->mock->expects($this->once())->method('send')->with(json_encode(array(3, $callId, $data))); - - $this->conn->callResult($callId, $data); - } - - public function testCallError() { - $callId = uniqid(); - $uri = 'http://example.com/end/point'; - - $this->mock->expects($this->once())->method('send')->with(json_encode(array(4, $callId, $uri, ''))); - - $this->conn->callError($callId, $uri); - } - - public function testCallErrorWithTopic() { - $callId = uniqid(); - $uri = 'http://example.com/end/point'; - - $this->mock->expects($this->once())->method('send')->with(json_encode(array(4, $callId, $uri, ''))); - - $this->conn->callError($callId, new Topic($uri)); - } - - public function testDetailedCallError() { - $callId = uniqid(); - $uri = 'http://example.com/end/point'; - $desc = 'beep boop beep'; - $detail = 'Error: Too much awesome'; - - $this->mock->expects($this->once())->method('send')->with(json_encode(array(4, $callId, $uri, $desc, $detail))); - - $this->conn->callError($callId, $uri, $desc, $detail); - } - - public function testPrefix() { - $shortOut = 'outgoing'; - $longOut = 'http://example.com/outgoing'; - - $this->mock->expects($this->once())->method('send')->with(json_encode(array(1, $shortOut, $longOut))); - - $this->conn->prefix($shortOut, $longOut); - } - - public function testGetUriWhenNoCurieGiven() { - $uri = 'http://example.com/noshort'; - - $this->assertEquals($uri, $this->conn->getUri($uri)); - } - - public function testClose() { - $mock = $this->getMock('\\Ratchet\\ConnectionInterface'); - $conn = new WampConnection($mock); - - $mock->expects($this->once())->method('close'); - - $conn->close(); - } -} diff --git a/digital_doctor/vendor/cboden/ratchet/tests/unit/Wamp/WampServerTest.php b/digital_doctor/vendor/cboden/ratchet/tests/unit/Wamp/WampServerTest.php deleted file mode 100644 index 626b1ce..0000000 --- a/digital_doctor/vendor/cboden/ratchet/tests/unit/Wamp/WampServerTest.php +++ /dev/null @@ -1,49 +0,0 @@ -_app->expects($this->once())->method('onPublish')->with( - $this->isExpectedConnection() - , new \PHPUnit_Framework_Constraint_IsInstanceOf('\Ratchet\Wamp\Topic') - , $published - , array() - , array() - ); - - $this->_serv->onMessage($this->_conn, json_encode(array(7, 'topic', $published))); - } - - public function testGetSubProtocols() { - // todo: could expand on this - $this->assertInternalType('array', $this->_serv->getSubProtocols()); - } - - public function testConnectionClosesOnInvalidJson() { - $this->_conn->expects($this->once())->method('close'); - $this->_serv->onMessage($this->_conn, 'invalid json'); - } - - public function testConnectionClosesOnProtocolError() { - $this->_conn->expects($this->once())->method('close'); - $this->_serv->onMessage($this->_conn, json_encode(array('valid' => 'json', 'invalid' => 'protocol'))); - } -} diff --git a/digital_doctor/vendor/composer/installed.json b/digital_doctor/vendor/composer/installed.json index a94b176..22602ac 100644 --- a/digital_doctor/vendor/composer/installed.json +++ b/digital_doctor/vendor/composer/installed.json @@ -1,65 +1,5 @@ { "packages": [ - { - "name": "cboden/ratchet", - "version": "v0.4.4", - "version_normalized": "0.4.4.0", - "source": { - "type": "git", - "url": "https://github.com/ratchetphp/Ratchet.git", - "reference": "5012dc954541b40c5599d286fd40653f5716a38f" - }, - "dist": { - "type": "zip", - "url": "https://mirrors.huaweicloud.com/repository/php/cboden/ratchet/v0.4.4/cboden-ratchet-v0.4.4.zip", - "reference": "5012dc954541b40c5599d286fd40653f5716a38f", - "shasum": "" - }, - "require": { - "guzzlehttp/psr7": "^1.7|^2.0", - "php": ">=5.4.2", - "ratchet/rfc6455": "^0.3.1", - "react/event-loop": ">=0.4", - "react/socket": "^1.0 || ^0.8 || ^0.7 || ^0.6 || ^0.5", - "symfony/http-foundation": "^2.6|^3.0|^4.0|^5.0|^6.0", - "symfony/routing": "^2.6|^3.0|^4.0|^5.0|^6.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.8" - }, - "time": "2021-12-14T00:20:41+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Ratchet\\": "src/Ratchet" - } - }, - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Chris Boden", - "email": "cboden@gmail.com", - "role": "Developer" - }, - { - "name": "Matt Bonneau", - "role": "Developer" - } - ], - "description": "PHP WebSocket library", - "homepage": "http://socketo.me", - "keywords": [ - "Ratchet", - "WebSockets", - "server", - "sockets", - "websocket" - ], - "install-path": "../cboden/ratchet" - }, { "name": "doing/phpqrcode", "version": "dev-master", @@ -114,105 +54,6 @@ }, "install-path": "../doing/phpqrcode" }, - { - "name": "evenement/evenement", - "version": "v3.0.2", - "version_normalized": "3.0.2.0", - "source": { - "type": "git", - "url": "https://github.com/igorw/evenement.git", - "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc" - }, - "dist": { - "type": "zip", - "url": "https://mirrors.huaweicloud.com/repository/php/evenement/evenement/v3.0.2/evenement-evenement-v3.0.2.zip", - "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc", - "shasum": "" - }, - "require": { - "php": ">=7.0" - }, - "require-dev": { - "phpunit/phpunit": "^9 || ^6" - }, - "time": "2023-08-08T05:53:35+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Evenement\\": "src/" - } - }, - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Igor Wiedler", - "email": "igor@wiedler.ch" - } - ], - "description": "Événement is a very simple event dispatching library for PHP", - "keywords": [ - "event-dispatcher", - "event-emitter" - ], - "install-path": "../evenement/evenement" - }, - { - "name": "fig/http-message-util", - "version": "1.1.5", - "version_normalized": "1.1.5.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-message-util.git", - "reference": "9d94dc0154230ac39e5bf89398b324a86f63f765" - }, - "dist": { - "type": "zip", - "url": "https://mirrors.huaweicloud.com/repository/php/fig/http-message-util/1.1.5/fig-http-message-util-1.1.5.zip", - "reference": "9d94dc0154230ac39e5bf89398b324a86f63f765", - "shasum": "" - }, - "require": { - "php": "^5.3 || ^7.0 || ^8.0" - }, - "suggest": { - "psr/http-message": "The package containing the PSR-7 interfaces" - }, - "time": "2020-11-24T22:02:12+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Fig\\Http\\Message\\": "src/" - } - }, - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Utility classes and constants for use with PSR-7 (psr/http-message)", - "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" - ], - "install-path": "../fig/http-message-util" - }, { "name": "guzzlehttp/guzzle", "version": "7.8.1", @@ -861,24 +702,30 @@ }, { "name": "psr/http-factory", - "version": "1.1.0", - "version_normalized": "1.1.0.0", + "version": "1.0.2", + "version_normalized": "1.0.2.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-factory.git", - "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" + "reference": "e616d01114759c4c489f93b099585439f795fe35" }, "dist": { "type": "zip", - "url": "https://mirrors.huaweicloud.com/repository/php/psr/http-factory/1.1.0/psr-http-factory-1.1.0.zip", - "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", - "shasum": "" + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", + "reference": "e616d01114759c4c489f93b099585439f795fe35", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { - "php": ">=7.1", + "php": ">=7.0.0", "psr/http-message": "^1.0 || ^2.0" }, - "time": "2024-04-15T12:06:14+00:00", + "time": "2023-04-10T20:10:41+00:00", "type": "library", "extra": { "branch-alias": { @@ -891,6 +738,7 @@ "Psr\\Http\\Message\\": "src/" } }, + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -900,7 +748,7 @@ "homepage": "https://www.php-fig.org/" } ], - "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", + "description": "Common interfaces for PSR-7 HTTP message factories", "keywords": [ "factory", "http", @@ -911,6 +759,9 @@ "request", "response" ], + "support": { + "source": "https://github.com/php-fig/http-factory/tree/1.0.2" + }, "install-path": "../psr/http-factory" }, { @@ -1056,607 +907,31 @@ "description": "A polyfill for getallheaders.", "install-path": "../ralouphie/getallheaders" }, - { - "name": "ratchet/rfc6455", - "version": "v0.3.1", - "version_normalized": "0.3.1.0", - "source": { - "type": "git", - "url": "https://github.com/ratchetphp/RFC6455.git", - "reference": "7c964514e93456a52a99a20fcfa0de242a43ccdb" - }, - "dist": { - "type": "zip", - "url": "https://mirrors.huaweicloud.com/repository/php/ratchet/rfc6455/v0.3.1/ratchet-rfc6455-v0.3.1.zip", - "reference": "7c964514e93456a52a99a20fcfa0de242a43ccdb", - "shasum": "" - }, - "require": { - "guzzlehttp/psr7": "^2 || ^1.7", - "php": ">=5.4.2" - }, - "require-dev": { - "phpunit/phpunit": "^5.7", - "react/socket": "^1.3" - }, - "time": "2021-12-09T23:20:49+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Ratchet\\RFC6455\\": "src" - } - }, - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Chris Boden", - "email": "cboden@gmail.com", - "role": "Developer" - }, - { - "name": "Matt Bonneau", - "role": "Developer" - } - ], - "description": "RFC6455 WebSocket protocol handler", - "homepage": "http://socketo.me", - "keywords": [ - "WebSockets", - "rfc6455", - "websocket" - ], - "install-path": "../ratchet/rfc6455" - }, - { - "name": "react/cache", - "version": "v1.2.0", - "version_normalized": "1.2.0.0", - "source": { - "type": "git", - "url": "https://github.com/reactphp/cache.git", - "reference": "d47c472b64aa5608225f47965a484b75c7817d5b" - }, - "dist": { - "type": "zip", - "url": "https://mirrors.huaweicloud.com/repository/php/react/cache/v1.2.0/react-cache-v1.2.0.zip", - "reference": "d47c472b64aa5608225f47965a484b75c7817d5b", - "shasum": "" - }, - "require": { - "php": ">=5.3.0", - "react/promise": "^3.0 || ^2.0 || ^1.1" - }, - "require-dev": { - "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35" - }, - "time": "2022-11-30T15:59:55+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "React\\Cache\\": "src/" - } - }, - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Christian Lück", - "email": "christian@clue.engineering", - "homepage": "https://clue.engineering/" - }, - { - "name": "Cees-Jan Kiewiet", - "email": "reactphp@ceesjankiewiet.nl", - "homepage": "https://wyrihaximus.net/" - }, - { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com", - "homepage": "https://sorgalla.com/" - }, - { - "name": "Chris Boden", - "email": "cboden@gmail.com", - "homepage": "https://cboden.dev/" - } - ], - "description": "Async, Promise-based cache interface for ReactPHP", - "keywords": [ - "cache", - "caching", - "promise", - "reactphp" - ], - "funding": [ - { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" - } - ], - "install-path": "../react/cache" - }, - { - "name": "react/dns", - "version": "v1.13.0", - "version_normalized": "1.13.0.0", - "source": { - "type": "git", - "url": "https://github.com/reactphp/dns.git", - "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5" - }, - "dist": { - "type": "zip", - "url": "https://mirrors.huaweicloud.com/repository/php/react/dns/v1.13.0/react-dns-v1.13.0.zip", - "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5", - "shasum": "" - }, - "require": { - "php": ">=5.3.0", - "react/cache": "^1.0 || ^0.6 || ^0.5", - "react/event-loop": "^1.2", - "react/promise": "^3.2 || ^2.7 || ^1.2.1" - }, - "require-dev": { - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", - "react/async": "^4.3 || ^3 || ^2", - "react/promise-timer": "^1.11" - }, - "time": "2024-06-13T14:18:03+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "React\\Dns\\": "src/" - } - }, - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Christian Lück", - "email": "christian@clue.engineering", - "homepage": "https://clue.engineering/" - }, - { - "name": "Cees-Jan Kiewiet", - "email": "reactphp@ceesjankiewiet.nl", - "homepage": "https://wyrihaximus.net/" - }, - { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com", - "homepage": "https://sorgalla.com/" - }, - { - "name": "Chris Boden", - "email": "cboden@gmail.com", - "homepage": "https://cboden.dev/" - } - ], - "description": "Async DNS resolver for ReactPHP", - "keywords": [ - "async", - "dns", - "dns-resolver", - "reactphp" - ], - "funding": [ - { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" - } - ], - "install-path": "../react/dns" - }, - { - "name": "react/event-loop", - "version": "v1.5.0", - "version_normalized": "1.5.0.0", - "source": { - "type": "git", - "url": "https://github.com/reactphp/event-loop.git", - "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354" - }, - "dist": { - "type": "zip", - "url": "https://mirrors.huaweicloud.com/repository/php/react/event-loop/v1.5.0/react-event-loop-v1.5.0.zip", - "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" - }, - "suggest": { - "ext-pcntl": "For signal handling support when using the StreamSelectLoop" - }, - "time": "2023-11-13T13:48:05+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "React\\EventLoop\\": "src/" - } - }, - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Christian Lück", - "email": "christian@clue.engineering", - "homepage": "https://clue.engineering/" - }, - { - "name": "Cees-Jan Kiewiet", - "email": "reactphp@ceesjankiewiet.nl", - "homepage": "https://wyrihaximus.net/" - }, - { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com", - "homepage": "https://sorgalla.com/" - }, - { - "name": "Chris Boden", - "email": "cboden@gmail.com", - "homepage": "https://cboden.dev/" - } - ], - "description": "ReactPHP's core reactor event loop that libraries can use for evented I/O.", - "keywords": [ - "asynchronous", - "event-loop" - ], - "funding": [ - { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" - } - ], - "install-path": "../react/event-loop" - }, - { - "name": "react/http", - "version": "v1.10.0", - "version_normalized": "1.10.0.0", - "source": { - "type": "git", - "url": "https://github.com/reactphp/http.git", - "reference": "8111281ee57f22b7194f5dba225e609ba7ce4d20" - }, - "dist": { - "type": "zip", - "url": "https://mirrors.huaweicloud.com/repository/php/react/http/v1.10.0/react-http-v1.10.0.zip", - "reference": "8111281ee57f22b7194f5dba225e609ba7ce4d20", - "shasum": "" - }, - "require": { - "evenement/evenement": "^3.0 || ^2.0 || ^1.0", - "fig/http-message-util": "^1.1", - "php": ">=5.3.0", - "psr/http-message": "^1.0", - "react/event-loop": "^1.2", - "react/promise": "^3 || ^2.3 || ^1.2.1", - "react/socket": "^1.12", - "react/stream": "^1.2" - }, - "require-dev": { - "clue/http-proxy-react": "^1.8", - "clue/reactphp-ssh-proxy": "^1.4", - "clue/socks-react": "^1.4", - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", - "react/async": "^4 || ^3 || ^2", - "react/promise-stream": "^1.4", - "react/promise-timer": "^1.9" - }, - "time": "2024-03-27T17:20:46+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "React\\Http\\": "src/" - } - }, - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Christian Lück", - "email": "christian@clue.engineering", - "homepage": "https://clue.engineering/" - }, - { - "name": "Cees-Jan Kiewiet", - "email": "reactphp@ceesjankiewiet.nl", - "homepage": "https://wyrihaximus.net/" - }, - { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com", - "homepage": "https://sorgalla.com/" - }, - { - "name": "Chris Boden", - "email": "cboden@gmail.com", - "homepage": "https://cboden.dev/" - } - ], - "description": "Event-driven, streaming HTTP client and server implementation for ReactPHP", - "keywords": [ - "async", - "client", - "event-driven", - "http", - "http client", - "http server", - "https", - "psr-7", - "reactphp", - "server", - "streaming" - ], - "funding": [ - { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" - } - ], - "install-path": "../react/http" - }, - { - "name": "react/promise", - "version": "v3.2.0", - "version_normalized": "3.2.0.0", - "source": { - "type": "git", - "url": "https://github.com/reactphp/promise.git", - "reference": "8a164643313c71354582dc850b42b33fa12a4b63" - }, - "dist": { - "type": "zip", - "url": "https://mirrors.huaweicloud.com/repository/php/react/promise/v3.2.0/react-promise-v3.2.0.zip", - "reference": "8a164643313c71354582dc850b42b33fa12a4b63", - "shasum": "" - }, - "require": { - "php": ">=7.1.0" - }, - "require-dev": { - "phpstan/phpstan": "1.10.39 || 1.4.10", - "phpunit/phpunit": "^9.6 || ^7.5" - }, - "time": "2024-05-24T10:39:05+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "files": [ - "src/functions_include.php" - ], - "psr-4": { - "React\\Promise\\": "src/" - } - }, - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com", - "homepage": "https://sorgalla.com/" - }, - { - "name": "Christian Lück", - "email": "christian@clue.engineering", - "homepage": "https://clue.engineering/" - }, - { - "name": "Cees-Jan Kiewiet", - "email": "reactphp@ceesjankiewiet.nl", - "homepage": "https://wyrihaximus.net/" - }, - { - "name": "Chris Boden", - "email": "cboden@gmail.com", - "homepage": "https://cboden.dev/" - } - ], - "description": "A lightweight implementation of CommonJS Promises/A for PHP", - "keywords": [ - "promise", - "promises" - ], - "funding": [ - { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" - } - ], - "install-path": "../react/promise" - }, - { - "name": "react/socket", - "version": "v1.15.0", - "version_normalized": "1.15.0.0", - "source": { - "type": "git", - "url": "https://github.com/reactphp/socket.git", - "reference": "216d3aec0b87f04a40ca04f481e6af01bdd1d038" - }, - "dist": { - "type": "zip", - "url": "https://mirrors.huaweicloud.com/repository/php/react/socket/v1.15.0/react-socket-v1.15.0.zip", - "reference": "216d3aec0b87f04a40ca04f481e6af01bdd1d038", - "shasum": "" - }, - "require": { - "evenement/evenement": "^3.0 || ^2.0 || ^1.0", - "php": ">=5.3.0", - "react/dns": "^1.11", - "react/event-loop": "^1.2", - "react/promise": "^3 || ^2.6 || ^1.2.1", - "react/stream": "^1.2" - }, - "require-dev": { - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", - "react/async": "^4 || ^3 || ^2", - "react/promise-stream": "^1.4", - "react/promise-timer": "^1.10" - }, - "time": "2023-12-15T11:02:10+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "React\\Socket\\": "src/" - } - }, - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Christian Lück", - "email": "christian@clue.engineering", - "homepage": "https://clue.engineering/" - }, - { - "name": "Cees-Jan Kiewiet", - "email": "reactphp@ceesjankiewiet.nl", - "homepage": "https://wyrihaximus.net/" - }, - { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com", - "homepage": "https://sorgalla.com/" - }, - { - "name": "Chris Boden", - "email": "cboden@gmail.com", - "homepage": "https://cboden.dev/" - } - ], - "description": "Async, streaming plaintext TCP/IP and secure TLS socket server and client connections for ReactPHP", - "keywords": [ - "Connection", - "Socket", - "async", - "reactphp", - "stream" - ], - "funding": [ - { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" - } - ], - "install-path": "../react/socket" - }, - { - "name": "react/stream", - "version": "v1.4.0", - "version_normalized": "1.4.0.0", - "source": { - "type": "git", - "url": "https://github.com/reactphp/stream.git", - "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d" - }, - "dist": { - "type": "zip", - "url": "https://mirrors.huaweicloud.com/repository/php/react/stream/v1.4.0/react-stream-v1.4.0.zip", - "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d", - "shasum": "" - }, - "require": { - "evenement/evenement": "^3.0 || ^2.0 || ^1.0", - "php": ">=5.3.8", - "react/event-loop": "^1.2" - }, - "require-dev": { - "clue/stream-filter": "~1.2", - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" - }, - "time": "2024-06-11T12:45:25+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "React\\Stream\\": "src/" - } - }, - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Christian Lück", - "email": "christian@clue.engineering", - "homepage": "https://clue.engineering/" - }, - { - "name": "Cees-Jan Kiewiet", - "email": "reactphp@ceesjankiewiet.nl", - "homepage": "https://wyrihaximus.net/" - }, - { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com", - "homepage": "https://sorgalla.com/" - }, - { - "name": "Chris Boden", - "email": "cboden@gmail.com", - "homepage": "https://cboden.dev/" - } - ], - "description": "Event-driven readable and writable streams for non-blocking I/O in ReactPHP", - "keywords": [ - "event-driven", - "io", - "non-blocking", - "pipe", - "reactphp", - "readable", - "stream", - "writable" - ], - "funding": [ - { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" - } - ], - "install-path": "../react/stream" - }, { "name": "symfony/deprecation-contracts", - "version": "v2.5.3", - "version_normalized": "2.5.3.0", + "version": "v2.5.2", + "version_normalized": "2.5.2.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "80d075412b557d41002320b96a096ca65aa2c98d" + "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" }, "dist": { "type": "zip", - "url": "https://mirrors.huaweicloud.com/repository/php/symfony/deprecation-contracts/v2.5.3/symfony-deprecation-contracts-v2.5.3.zip", - "reference": "80d075412b557d41002320b96a096ca65aa2c98d", - "shasum": "" + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=7.1" }, - "time": "2023-01-24T14:02:46+00:00", + "time": "2022-01-02T09:53:40+00:00", "type": "library", "extra": { "branch-alias": { @@ -1673,6 +948,7 @@ "function.php" ] }, + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -1688,6 +964,9 @@ ], "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.2" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -1704,328 +983,6 @@ ], "install-path": "../symfony/deprecation-contracts" }, - { - "name": "symfony/http-foundation", - "version": "v5.4.40", - "version_normalized": "5.4.40.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-foundation.git", - "reference": "cf4893ca4eca3fac4ae06da1590afdbbb4217847" - }, - "dist": { - "type": "zip", - "url": "https://mirrors.huaweicloud.com/repository/php/symfony/http-foundation/v5.4.40/symfony-http-foundation-v5.4.40.zip", - "reference": "cf4893ca4eca3fac4ae06da1590afdbbb4217847", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-mbstring": "~1.1", - "symfony/polyfill-php80": "^1.16" - }, - "require-dev": { - "predis/predis": "^1.0|^2.0", - "symfony/cache": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4", - "symfony/mime": "^4.4|^5.0|^6.0", - "symfony/rate-limiter": "^5.2|^6.0" - }, - "suggest": { - "symfony/mime": "To use the file extension guesser" - }, - "time": "2024-05-31T14:33:22+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\HttpFoundation\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Defines an object-oriented layer for the HTTP specification", - "homepage": "https://symfony.com", - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/http-foundation" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.30.0", - "version_normalized": "1.30.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c" - }, - "dist": { - "type": "zip", - "url": "https://mirrors.huaweicloud.com/repository/php/symfony/polyfill-mbstring/v1.30.0/symfony-polyfill-mbstring-v1.30.0.zip", - "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "provide": { - "ext-mbstring": "*" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "time": "2024-06-19T12:30:46+00:00", - "type": "library", - "extra": { - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "installation-source": "dist", - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - } - }, - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/polyfill-mbstring" - }, - { - "name": "symfony/polyfill-php80", - "version": "v1.30.0", - "version_normalized": "1.30.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "77fa7995ac1b21ab60769b7323d600a991a90433" - }, - "dist": { - "type": "zip", - "url": "https://mirrors.huaweicloud.com/repository/php/symfony/polyfill-php80/v1.30.0/symfony-polyfill-php80-v1.30.0.zip", - "reference": "77fa7995ac1b21ab60769b7323d600a991a90433", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "time": "2024-05-31T15:07:36+00:00", - "type": "library", - "extra": { - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "installation-source": "dist", - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/polyfill-php80" - }, - { - "name": "symfony/routing", - "version": "v5.4.40", - "version_normalized": "5.4.40.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/routing.git", - "reference": "6df1dd8b306649303267a760699cf04cf39b1f7b" - }, - "dist": { - "type": "zip", - "url": "https://mirrors.huaweicloud.com/repository/php/symfony/routing/v5.4.40/symfony-routing-v5.4.40.zip", - "reference": "6df1dd8b306649303267a760699cf04cf39b1f7b", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16" - }, - "conflict": { - "doctrine/annotations": "<1.12", - "symfony/config": "<5.3", - "symfony/dependency-injection": "<4.4", - "symfony/yaml": "<4.4" - }, - "require-dev": { - "doctrine/annotations": "^1.12|^2", - "psr/log": "^1|^2|^3", - "symfony/config": "^5.3|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/http-foundation": "^4.4|^5.0|^6.0", - "symfony/yaml": "^4.4|^5.0|^6.0" - }, - "suggest": { - "symfony/config": "For using the all-in-one router or any loader", - "symfony/expression-language": "For using expression matching", - "symfony/http-foundation": "For using a Symfony Request object", - "symfony/yaml": "For using the YAML loader" - }, - "time": "2024-05-31T14:33:22+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Routing\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Maps an HTTP request to a set of configuration variables", - "homepage": "https://symfony.com", - "keywords": [ - "router", - "routing", - "uri", - "url" - ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/routing" - }, { "name": "textalk/websocket", "version": "1.6.3", diff --git a/digital_doctor/vendor/composer/installed.php b/digital_doctor/vendor/composer/installed.php index 60830eb..91638d0 100644 --- a/digital_doctor/vendor/composer/installed.php +++ b/digital_doctor/vendor/composer/installed.php @@ -5,20 +5,11 @@ 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), - 'reference' => 'e499661572c48662d059211606f96a9eb68c35dc', + 'reference' => '09ae48941229f26b04631d081e85a2f29bf91be2', 'name' => 'topthink/think', 'dev' => true, ), 'versions' => array( - 'cboden/ratchet' => array( - 'pretty_version' => 'v0.4.4', - 'version' => '0.4.4.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../cboden/ratchet', - 'aliases' => array(), - 'reference' => '5012dc954541b40c5599d286fd40653f5716a38f', - 'dev_requirement' => false, - ), 'doing/phpqrcode' => array( 'pretty_version' => 'dev-master', 'version' => 'dev-master', @@ -30,24 +21,6 @@ 'reference' => '600baab04cd4dfe2b307a321775ec5a66e330560', 'dev_requirement' => false, ), - 'evenement/evenement' => array( - 'pretty_version' => 'v3.0.2', - 'version' => '3.0.2.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../evenement/evenement', - 'aliases' => array(), - 'reference' => '0a16b0d71ab13284339abb99d9d2bd813640efbc', - 'dev_requirement' => false, - ), - 'fig/http-message-util' => array( - 'pretty_version' => '1.1.5', - 'version' => '1.1.5.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../fig/http-message-util', - 'aliases' => array(), - 'reference' => '9d94dc0154230ac39e5bf89398b324a86f63f765', - 'dev_requirement' => false, - ), 'guzzlehttp/guzzle' => array( 'pretty_version' => '7.8.1', 'version' => '7.8.1.0', @@ -136,12 +109,12 @@ ), ), 'psr/http-factory' => array( - 'pretty_version' => '1.1.0', - 'version' => '1.1.0.0', + 'pretty_version' => '1.0.2', + 'version' => '1.0.2.0', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/http-factory', 'aliases' => array(), - 'reference' => '2b4765fddfe3b508ac62f829e852b1501d3f6e8a', + 'reference' => 'e616d01114759c4c489f93b099585439f795fe35', 'dev_requirement' => false, ), 'psr/http-message' => array( @@ -183,121 +156,13 @@ 'reference' => '120b605dfeb996808c31b6477290a714d356e822', 'dev_requirement' => false, ), - 'ratchet/rfc6455' => array( - 'pretty_version' => 'v0.3.1', - 'version' => '0.3.1.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../ratchet/rfc6455', - 'aliases' => array(), - 'reference' => '7c964514e93456a52a99a20fcfa0de242a43ccdb', - 'dev_requirement' => false, - ), - 'react/cache' => array( - 'pretty_version' => 'v1.2.0', - 'version' => '1.2.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../react/cache', - 'aliases' => array(), - 'reference' => 'd47c472b64aa5608225f47965a484b75c7817d5b', - 'dev_requirement' => false, - ), - 'react/dns' => array( - 'pretty_version' => 'v1.13.0', - 'version' => '1.13.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../react/dns', - 'aliases' => array(), - 'reference' => 'eb8ae001b5a455665c89c1df97f6fb682f8fb0f5', - 'dev_requirement' => false, - ), - 'react/event-loop' => array( - 'pretty_version' => 'v1.5.0', - 'version' => '1.5.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../react/event-loop', - 'aliases' => array(), - 'reference' => 'bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354', - 'dev_requirement' => false, - ), - 'react/http' => array( - 'pretty_version' => 'v1.10.0', - 'version' => '1.10.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../react/http', - 'aliases' => array(), - 'reference' => '8111281ee57f22b7194f5dba225e609ba7ce4d20', - 'dev_requirement' => false, - ), - 'react/promise' => array( - 'pretty_version' => 'v3.2.0', - 'version' => '3.2.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../react/promise', - 'aliases' => array(), - 'reference' => '8a164643313c71354582dc850b42b33fa12a4b63', - 'dev_requirement' => false, - ), - 'react/socket' => array( - 'pretty_version' => 'v1.15.0', - 'version' => '1.15.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../react/socket', - 'aliases' => array(), - 'reference' => '216d3aec0b87f04a40ca04f481e6af01bdd1d038', - 'dev_requirement' => false, - ), - 'react/stream' => array( - 'pretty_version' => 'v1.4.0', - 'version' => '1.4.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../react/stream', - 'aliases' => array(), - 'reference' => '1e5b0acb8fe55143b5b426817155190eb6f5b18d', - 'dev_requirement' => false, - ), 'symfony/deprecation-contracts' => array( - 'pretty_version' => 'v2.5.3', - 'version' => '2.5.3.0', + 'pretty_version' => 'v2.5.2', + 'version' => '2.5.2.0', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/deprecation-contracts', 'aliases' => array(), - 'reference' => '80d075412b557d41002320b96a096ca65aa2c98d', - 'dev_requirement' => false, - ), - 'symfony/http-foundation' => array( - 'pretty_version' => 'v5.4.40', - 'version' => '5.4.40.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/http-foundation', - 'aliases' => array(), - 'reference' => 'cf4893ca4eca3fac4ae06da1590afdbbb4217847', - 'dev_requirement' => false, - ), - 'symfony/polyfill-mbstring' => array( - 'pretty_version' => 'v1.30.0', - 'version' => '1.30.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/polyfill-mbstring', - 'aliases' => array(), - 'reference' => 'fd22ab50000ef01661e2a31d850ebaa297f8e03c', - 'dev_requirement' => false, - ), - 'symfony/polyfill-php80' => array( - 'pretty_version' => 'v1.30.0', - 'version' => '1.30.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/polyfill-php80', - 'aliases' => array(), - 'reference' => '77fa7995ac1b21ab60769b7323d600a991a90433', - 'dev_requirement' => false, - ), - 'symfony/routing' => array( - 'pretty_version' => 'v5.4.40', - 'version' => '5.4.40.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/routing', - 'aliases' => array(), - 'reference' => '6df1dd8b306649303267a760699cf04cf39b1f7b', + 'reference' => 'e8b495ea28c1d97b5e0c121748d6f9b53d075c66', 'dev_requirement' => false, ), 'textalk/websocket' => array( @@ -324,7 +189,7 @@ 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), - 'reference' => 'e499661572c48662d059211606f96a9eb68c35dc', + 'reference' => '09ae48941229f26b04631d081e85a2f29bf91be2', 'dev_requirement' => false, ), 'topthink/think-installer' => array( diff --git a/digital_doctor/vendor/evenement/evenement/.gitattributes b/digital_doctor/vendor/evenement/evenement/.gitattributes deleted file mode 100644 index 8e493b8..0000000 --- a/digital_doctor/vendor/evenement/evenement/.gitattributes +++ /dev/null @@ -1,7 +0,0 @@ -/.github export-ignore -/doc export-ignore -/examples export-ignore -/tests export-ignore -/.gitignore export-ignore -/CHANGELOG.md export-ignore -/phpunit.xml.dist export-ignore diff --git a/digital_doctor/vendor/evenement/evenement/LICENSE b/digital_doctor/vendor/evenement/evenement/LICENSE deleted file mode 100644 index d9a37d0..0000000 --- a/digital_doctor/vendor/evenement/evenement/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2011 Igor Wiedler - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/digital_doctor/vendor/evenement/evenement/README.md b/digital_doctor/vendor/evenement/evenement/README.md deleted file mode 100644 index 455dd22..0000000 --- a/digital_doctor/vendor/evenement/evenement/README.md +++ /dev/null @@ -1,64 +0,0 @@ -# Événement - -Événement is a very simple event dispatching library for PHP. - -It has the same design goals as [Silex](https://silex.symfony.com/) and -[Pimple](https://github.com/silexphp/Pimple), to empower the user while staying concise -and simple. - -It is very strongly inspired by the [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter) API found in -[node.js](http://nodejs.org). - -![Continuous Integration](https://github.com/igorw/evenement/workflows/CI/badge.svg) -[![Latest Stable Version](https://poser.pugx.org/evenement/evenement/v/stable.png)](https://packagist.org/packages/evenement/evenement) -[![Total Downloads](https://poser.pugx.org/evenement/evenement/downloads.png)](https://packagist.org/packages/evenement/evenement/stats) -[![License](https://poser.pugx.org/evenement/evenement/license.png)](https://packagist.org/packages/evenement/evenement) - -## Fetch - -The recommended way to install Événement is [through composer](http://getcomposer.org). By running the following command: - - $ composer require evenement/evenement - -## Usage - -### Creating an Emitter - -```php -on('user.created', function (User $user) use ($logger) { - $logger->log(sprintf("User '%s' was created.", $user->getLogin())); -}); -``` - -### Removing Listeners - -```php -removeListener('user.created', function (User $user) use ($logger) { - $logger->log(sprintf("User '%s' was created.", $user->getLogin())); -}); -``` - -### Emitting Events - -```php -emit('user.created', [$user]); -``` - -Tests ------ - - $ ./vendor/bin/phpunit - -License -------- -MIT, see LICENSE. diff --git a/digital_doctor/vendor/evenement/evenement/composer.json b/digital_doctor/vendor/evenement/evenement/composer.json deleted file mode 100644 index 5444d93..0000000 --- a/digital_doctor/vendor/evenement/evenement/composer.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "name": "evenement/evenement", - "description": "Événement is a very simple event dispatching library for PHP", - "keywords": ["event-dispatcher", "event-emitter"], - "license": "MIT", - "authors": [ - { - "name": "Igor Wiedler", - "email": "igor@wiedler.ch" - } - ], - "require": { - "php": ">=7.0" - }, - "require-dev": { - "phpunit/phpunit": "^9 || ^6" - }, - "autoload": { - "psr-4": { - "Evenement\\": "src/" - } - }, - "autoload-dev": { - "psr-4": { - "Evenement\\Tests\\": "tests/" - }, - "files": ["tests/functions.php"] - } -} diff --git a/digital_doctor/vendor/evenement/evenement/src/EventEmitter.php b/digital_doctor/vendor/evenement/evenement/src/EventEmitter.php deleted file mode 100644 index db189b9..0000000 --- a/digital_doctor/vendor/evenement/evenement/src/EventEmitter.php +++ /dev/null @@ -1,17 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Evenement; - -class EventEmitter implements EventEmitterInterface -{ - use EventEmitterTrait; -} diff --git a/digital_doctor/vendor/evenement/evenement/src/EventEmitterInterface.php b/digital_doctor/vendor/evenement/evenement/src/EventEmitterInterface.php deleted file mode 100644 index 310631a..0000000 --- a/digital_doctor/vendor/evenement/evenement/src/EventEmitterInterface.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Evenement; - -interface EventEmitterInterface -{ - public function on($event, callable $listener); - public function once($event, callable $listener); - public function removeListener($event, callable $listener); - public function removeAllListeners($event = null); - public function listeners($event = null); - public function emit($event, array $arguments = []); -} diff --git a/digital_doctor/vendor/evenement/evenement/src/EventEmitterTrait.php b/digital_doctor/vendor/evenement/evenement/src/EventEmitterTrait.php deleted file mode 100644 index 1503429..0000000 --- a/digital_doctor/vendor/evenement/evenement/src/EventEmitterTrait.php +++ /dev/null @@ -1,154 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Evenement; - -use InvalidArgumentException; - -use function count; -use function array_keys; -use function array_merge; -use function array_search; -use function array_unique; -use function array_values; - -trait EventEmitterTrait -{ - protected $listeners = []; - protected $onceListeners = []; - - public function on($event, callable $listener) - { - if ($event === null) { - throw new InvalidArgumentException('event name must not be null'); - } - - if (!isset($this->listeners[$event])) { - $this->listeners[$event] = []; - } - - $this->listeners[$event][] = $listener; - - return $this; - } - - public function once($event, callable $listener) - { - if ($event === null) { - throw new InvalidArgumentException('event name must not be null'); - } - - if (!isset($this->onceListeners[$event])) { - $this->onceListeners[$event] = []; - } - - $this->onceListeners[$event][] = $listener; - - return $this; - } - - public function removeListener($event, callable $listener) - { - if ($event === null) { - throw new InvalidArgumentException('event name must not be null'); - } - - if (isset($this->listeners[$event])) { - $index = array_search($listener, $this->listeners[$event], true); - if (false !== $index) { - unset($this->listeners[$event][$index]); - if (count($this->listeners[$event]) === 0) { - unset($this->listeners[$event]); - } - } - } - - if (isset($this->onceListeners[$event])) { - $index = array_search($listener, $this->onceListeners[$event], true); - if (false !== $index) { - unset($this->onceListeners[$event][$index]); - if (count($this->onceListeners[$event]) === 0) { - unset($this->onceListeners[$event]); - } - } - } - } - - public function removeAllListeners($event = null) - { - if ($event !== null) { - unset($this->listeners[$event]); - } else { - $this->listeners = []; - } - - if ($event !== null) { - unset($this->onceListeners[$event]); - } else { - $this->onceListeners = []; - } - } - - public function listeners($event = null): array - { - if ($event === null) { - $events = []; - $eventNames = array_unique( - array_merge( - array_keys($this->listeners), - array_keys($this->onceListeners) - ) - ); - foreach ($eventNames as $eventName) { - $events[$eventName] = array_merge( - isset($this->listeners[$eventName]) ? $this->listeners[$eventName] : [], - isset($this->onceListeners[$eventName]) ? $this->onceListeners[$eventName] : [] - ); - } - return $events; - } - - return array_merge( - isset($this->listeners[$event]) ? $this->listeners[$event] : [], - isset($this->onceListeners[$event]) ? $this->onceListeners[$event] : [] - ); - } - - public function emit($event, array $arguments = []) - { - if ($event === null) { - throw new InvalidArgumentException('event name must not be null'); - } - - $listeners = []; - if (isset($this->listeners[$event])) { - $listeners = array_values($this->listeners[$event]); - } - - $onceListeners = []; - if (isset($this->onceListeners[$event])) { - $onceListeners = array_values($this->onceListeners[$event]); - } - - if(empty($listeners) === false) { - foreach ($listeners as $listener) { - $listener(...$arguments); - } - } - - if(empty($onceListeners) === false) { - unset($this->onceListeners[$event]); - foreach ($onceListeners as $listener) { - $listener(...$arguments); - } - } - } -} diff --git a/digital_doctor/vendor/fig/http-message-util/.gitignore b/digital_doctor/vendor/fig/http-message-util/.gitignore deleted file mode 100644 index 48b8bf9..0000000 --- a/digital_doctor/vendor/fig/http-message-util/.gitignore +++ /dev/null @@ -1 +0,0 @@ -vendor/ diff --git a/digital_doctor/vendor/fig/http-message-util/CHANGELOG.md b/digital_doctor/vendor/fig/http-message-util/CHANGELOG.md deleted file mode 100644 index 1a02e54..0000000 --- a/digital_doctor/vendor/fig/http-message-util/CHANGELOG.md +++ /dev/null @@ -1,147 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file, in reverse chronological order by release. - -## 1.1.5 - 2020-11-24 - -### Added - -- [#19](https://github.com/php-fig/http-message-util/pull/19) adds support for PHP 8. - -### Changed - -- Nothing. - -### Deprecated - -- Nothing. - -### Removed - -- Nothing. - -### Fixed - -- Nothing. - -## 1.1.4 - 2020-02-05 - -### Added - -- Nothing. - -### Changed - -- Nothing. - -### Deprecated - -- Nothing. - -### Removed - -- [#15](https://github.com/php-fig/http-message-util/pull/15) removes the dependency on psr/http-message, as it is not technically necessary for usage of this package. - -### Fixed - -- Nothing. - -## 1.1.3 - 2018-11-19 - -### Added - -- [#10](https://github.com/php-fig/http-message-util/pull/10) adds the constants `StatusCodeInterface::STATUS_EARLY_HINTS` (103) and - `StatusCodeInterface::STATUS_TOO_EARLY` (425). - -### Changed - -- Nothing. - -### Deprecated - -- Nothing. - -### Removed - -- Nothing. - -### Fixed - -- Nothing. - -## 1.1.2 - 2017-02-09 - -### Added - -- [#4](https://github.com/php-fig/http-message-util/pull/4) adds the constant - `StatusCodeInterface::STATUS_MISDIRECTED_REQUEST` (421). - -### Deprecated - -- Nothing. - -### Removed - -- Nothing. - -### Fixed - -- Nothing. - -## 1.1.1 - 2017-02-06 - -### Added - -- [#3](https://github.com/php-fig/http-message-util/pull/3) adds the constant - `StatusCodeInterface::STATUS_IM_A_TEAPOT` (418). - -### Deprecated - -- Nothing. - -### Removed - -- Nothing. - -### Fixed - -- Nothing. - -## 1.1.0 - 2016-09-19 - -### Added - -- [#1](https://github.com/php-fig/http-message-util/pull/1) adds - `Fig\Http\Message\StatusCodeInterface`, with constants named after common - status reason phrases, with values indicating the status codes themselves. - -### Deprecated - -- Nothing. - -### Removed - -- Nothing. - -### Fixed - -- Nothing. - -## 1.0.0 - 2017-08-05 - -### Added - -- Adds `Fig\Http\Message\RequestMethodInterface`, with constants covering the - most common HTTP request methods as specified by the IETF. - -### Deprecated - -- Nothing. - -### Removed - -- Nothing. - -### Fixed - -- Nothing. diff --git a/digital_doctor/vendor/fig/http-message-util/LICENSE b/digital_doctor/vendor/fig/http-message-util/LICENSE deleted file mode 100644 index e2fa347..0000000 --- a/digital_doctor/vendor/fig/http-message-util/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2016 PHP Framework Interoperability Group - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/digital_doctor/vendor/fig/http-message-util/README.md b/digital_doctor/vendor/fig/http-message-util/README.md deleted file mode 100644 index ea5b5aa..0000000 --- a/digital_doctor/vendor/fig/http-message-util/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# PSR Http Message Util - -This repository holds utility classes and constants to facilitate common -operations of [PSR-7](https://www.php-fig.org/psr/psr-7/); the primary purpose is -to provide constants for referring to request methods, response status codes and -messages, and potentially common headers. - -Implementation of PSR-7 interfaces is **not** within the scope of this package. - -## Installation - -Install by adding the package as a [Composer](https://getcomposer.org) -requirement: - -```bash -$ composer require fig/http-message-util -``` diff --git a/digital_doctor/vendor/fig/http-message-util/composer.json b/digital_doctor/vendor/fig/http-message-util/composer.json deleted file mode 100644 index 8645893..0000000 --- a/digital_doctor/vendor/fig/http-message-util/composer.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "fig/http-message-util", - "description": "Utility classes and constants for use with PSR-7 (psr/http-message)", - "keywords": ["psr", "psr-7", "http", "http-message", "request", "response"], - "license": "MIT", - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "require": { - "php": "^5.3 || ^7.0 || ^8.0" - }, - "suggest": { - "psr/http-message": "The package containing the PSR-7 interfaces" - }, - "autoload": { - "psr-4": { - "Fig\\Http\\Message\\": "src/" - } - }, - "extra": { - "branch-alias": { - "dev-master": "1.1.x-dev" - } - } -} diff --git a/digital_doctor/vendor/fig/http-message-util/src/RequestMethodInterface.php b/digital_doctor/vendor/fig/http-message-util/src/RequestMethodInterface.php deleted file mode 100644 index 97d9a93..0000000 --- a/digital_doctor/vendor/fig/http-message-util/src/RequestMethodInterface.php +++ /dev/null @@ -1,34 +0,0 @@ - - * class RequestFactory implements RequestMethodInterface - * { - * public static function factory( - * $uri = '/', - * $method = self::METHOD_GET, - * $data = [] - * ) { - * } - * } - * - */ -interface RequestMethodInterface -{ - const METHOD_HEAD = 'HEAD'; - const METHOD_GET = 'GET'; - const METHOD_POST = 'POST'; - const METHOD_PUT = 'PUT'; - const METHOD_PATCH = 'PATCH'; - const METHOD_DELETE = 'DELETE'; - const METHOD_PURGE = 'PURGE'; - const METHOD_OPTIONS = 'OPTIONS'; - const METHOD_TRACE = 'TRACE'; - const METHOD_CONNECT = 'CONNECT'; -} diff --git a/digital_doctor/vendor/fig/http-message-util/src/StatusCodeInterface.php b/digital_doctor/vendor/fig/http-message-util/src/StatusCodeInterface.php deleted file mode 100644 index 99b7e78..0000000 --- a/digital_doctor/vendor/fig/http-message-util/src/StatusCodeInterface.php +++ /dev/null @@ -1,107 +0,0 @@ - - * class ResponseFactory implements StatusCodeInterface - * { - * public function createResponse($code = self::STATUS_OK) - * { - * } - * } - * - */ -interface StatusCodeInterface -{ - // Informational 1xx - const STATUS_CONTINUE = 100; - const STATUS_SWITCHING_PROTOCOLS = 101; - const STATUS_PROCESSING = 102; - const STATUS_EARLY_HINTS = 103; - // Successful 2xx - const STATUS_OK = 200; - const STATUS_CREATED = 201; - const STATUS_ACCEPTED = 202; - const STATUS_NON_AUTHORITATIVE_INFORMATION = 203; - const STATUS_NO_CONTENT = 204; - const STATUS_RESET_CONTENT = 205; - const STATUS_PARTIAL_CONTENT = 206; - const STATUS_MULTI_STATUS = 207; - const STATUS_ALREADY_REPORTED = 208; - const STATUS_IM_USED = 226; - // Redirection 3xx - const STATUS_MULTIPLE_CHOICES = 300; - const STATUS_MOVED_PERMANENTLY = 301; - const STATUS_FOUND = 302; - const STATUS_SEE_OTHER = 303; - const STATUS_NOT_MODIFIED = 304; - const STATUS_USE_PROXY = 305; - const STATUS_RESERVED = 306; - const STATUS_TEMPORARY_REDIRECT = 307; - const STATUS_PERMANENT_REDIRECT = 308; - // Client Errors 4xx - const STATUS_BAD_REQUEST = 400; - const STATUS_UNAUTHORIZED = 401; - const STATUS_PAYMENT_REQUIRED = 402; - const STATUS_FORBIDDEN = 403; - const STATUS_NOT_FOUND = 404; - const STATUS_METHOD_NOT_ALLOWED = 405; - const STATUS_NOT_ACCEPTABLE = 406; - const STATUS_PROXY_AUTHENTICATION_REQUIRED = 407; - const STATUS_REQUEST_TIMEOUT = 408; - const STATUS_CONFLICT = 409; - const STATUS_GONE = 410; - const STATUS_LENGTH_REQUIRED = 411; - const STATUS_PRECONDITION_FAILED = 412; - const STATUS_PAYLOAD_TOO_LARGE = 413; - const STATUS_URI_TOO_LONG = 414; - const STATUS_UNSUPPORTED_MEDIA_TYPE = 415; - const STATUS_RANGE_NOT_SATISFIABLE = 416; - const STATUS_EXPECTATION_FAILED = 417; - const STATUS_IM_A_TEAPOT = 418; - const STATUS_MISDIRECTED_REQUEST = 421; - const STATUS_UNPROCESSABLE_ENTITY = 422; - const STATUS_LOCKED = 423; - const STATUS_FAILED_DEPENDENCY = 424; - const STATUS_TOO_EARLY = 425; - const STATUS_UPGRADE_REQUIRED = 426; - const STATUS_PRECONDITION_REQUIRED = 428; - const STATUS_TOO_MANY_REQUESTS = 429; - const STATUS_REQUEST_HEADER_FIELDS_TOO_LARGE = 431; - const STATUS_UNAVAILABLE_FOR_LEGAL_REASONS = 451; - // Server Errors 5xx - const STATUS_INTERNAL_SERVER_ERROR = 500; - const STATUS_NOT_IMPLEMENTED = 501; - const STATUS_BAD_GATEWAY = 502; - const STATUS_SERVICE_UNAVAILABLE = 503; - const STATUS_GATEWAY_TIMEOUT = 504; - const STATUS_VERSION_NOT_SUPPORTED = 505; - const STATUS_VARIANT_ALSO_NEGOTIATES = 506; - const STATUS_INSUFFICIENT_STORAGE = 507; - const STATUS_LOOP_DETECTED = 508; - const STATUS_NOT_EXTENDED = 510; - const STATUS_NETWORK_AUTHENTICATION_REQUIRED = 511; -} diff --git a/digital_doctor/vendor/psr/http-factory/composer.json b/digital_doctor/vendor/psr/http-factory/composer.json index 82a1d32..d1bbdde 100644 --- a/digital_doctor/vendor/psr/http-factory/composer.json +++ b/digital_doctor/vendor/psr/http-factory/composer.json @@ -1,6 +1,6 @@ { "name": "psr/http-factory", - "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", + "description": "Common interfaces for PSR-7 HTTP message factories", "keywords": [ "psr", "psr-7", @@ -18,11 +18,8 @@ "homepage": "https://www.php-fig.org/" } ], - "support": { - "source": "https://github.com/php-fig/http-factory" - }, "require": { - "php": ">=7.1", + "php": ">=7.0.0", "psr/http-message": "^1.0 || ^2.0" }, "autoload": { diff --git a/digital_doctor/vendor/psr/http-factory/src/UploadedFileFactoryInterface.php b/digital_doctor/vendor/psr/http-factory/src/UploadedFileFactoryInterface.php index d7adbf0..7db4e30 100644 --- a/digital_doctor/vendor/psr/http-factory/src/UploadedFileFactoryInterface.php +++ b/digital_doctor/vendor/psr/http-factory/src/UploadedFileFactoryInterface.php @@ -15,10 +15,10 @@ interface UploadedFileFactoryInterface * * @param StreamInterface $stream Underlying stream representing the * uploaded file content. - * @param int|null $size in bytes + * @param int $size in bytes * @param int $error PHP file upload error - * @param string|null $clientFilename Filename as provided by the client, if any. - * @param string|null $clientMediaType Media type as provided by the client, if any. + * @param string $clientFilename Filename as provided by the client, if any. + * @param string $clientMediaType Media type as provided by the client, if any. * * @return UploadedFileInterface * @@ -26,9 +26,9 @@ interface UploadedFileFactoryInterface */ public function createUploadedFile( StreamInterface $stream, - ?int $size = null, + int $size = null, int $error = \UPLOAD_ERR_OK, - ?string $clientFilename = null, - ?string $clientMediaType = null + string $clientFilename = null, + string $clientMediaType = null ): UploadedFileInterface; } diff --git a/digital_doctor/vendor/ratchet/rfc6455/.github/workflows/ci.yml b/digital_doctor/vendor/ratchet/rfc6455/.github/workflows/ci.yml deleted file mode 100644 index fb3698d..0000000 --- a/digital_doctor/vendor/ratchet/rfc6455/.github/workflows/ci.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: CI - -on: - push: - pull_request: - -jobs: - PHPUnit: - name: PHPUnit (PHP ${{ matrix.php }})(${{ matrix.env }}) - runs-on: ubuntu-20.04 - strategy: - matrix: - env: - - client - - server - php: - - 7.4 - - 7.3 - - 7.2 - - 7.1 - - 7.0 - - 5.6 - steps: - - uses: actions/checkout@v2 - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - coverage: xdebug - - run: docker pull crossbario/autobahn-testsuite - - run: composer install - - - run: sh tests/ab/run_ab_tests.sh - env: - ABTEST: ${{ matrix.env }} - SKIP_DEFLATE: _skip_deflate - if: ${{ matrix.php <= 5.6 }} - - - run: sh tests/ab/run_ab_tests.sh - env: - ABTEST: ${{ matrix.env }} - if: ${{ matrix.php >= 7.0 }} - - run: vendor/bin/phpunit --verbose diff --git a/digital_doctor/vendor/ratchet/rfc6455/.gitignore b/digital_doctor/vendor/ratchet/rfc6455/.gitignore deleted file mode 100644 index 42ab5d5..0000000 --- a/digital_doctor/vendor/ratchet/rfc6455/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -composer.lock -vendor -tests/ab/reports -reports diff --git a/digital_doctor/vendor/ratchet/rfc6455/LICENSE b/digital_doctor/vendor/ratchet/rfc6455/LICENSE deleted file mode 100644 index 52b4aef..0000000 --- a/digital_doctor/vendor/ratchet/rfc6455/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2011 Chris Boden - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/digital_doctor/vendor/ratchet/rfc6455/README.md b/digital_doctor/vendor/ratchet/rfc6455/README.md deleted file mode 100644 index 1dfebf6..0000000 --- a/digital_doctor/vendor/ratchet/rfc6455/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# RFC6455 - The WebSocket Protocol - -[![Build Status](https://github.com/ratchetphp/RFC6455/workflows/CI/badge.svg)](https://github.com/ratchetphp/RFC6455/actions) -[![Autobahn Testsuite](https://img.shields.io/badge/Autobahn-passing-brightgreen.svg)](http://socketo.me/reports/rfc-server/index.html) - -This library a protocol handler for the RFC6455 specification. -It contains components for both server and client side handshake and messaging protocol negotation. - -Aspects that are left open to interpretation in the specification are also left open in this library. -It is up to the implementation to determine how those interpretations are to be dealt with. - -This library is independent, framework agnostic, and does not deal with any I/O. -HTTP upgrade negotiation integration points are handled with PSR-7 interfaces. diff --git a/digital_doctor/vendor/ratchet/rfc6455/composer.json b/digital_doctor/vendor/ratchet/rfc6455/composer.json deleted file mode 100644 index 054a8fb..0000000 --- a/digital_doctor/vendor/ratchet/rfc6455/composer.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "name": "ratchet/rfc6455", - "type": "library", - "description": "RFC6455 WebSocket protocol handler", - "keywords": ["WebSockets", "websocket", "RFC6455"], - "homepage": "http://socketo.me", - "license": "MIT", - "authors": [ - { - "name": "Chris Boden" - , "email": "cboden@gmail.com" - , "role": "Developer" - }, - { - "name": "Matt Bonneau", - "role": "Developer" - } - ], - "support": { - "issues": "https://github.com/ratchetphp/RFC6455/issues", - "chat": "https://gitter.im/reactphp/reactphp" - }, - "autoload": { - "psr-4": { - "Ratchet\\RFC6455\\": "src" - } - }, - "require": { - "php": ">=5.4.2", - "guzzlehttp/psr7": "^2 || ^1.7" - }, - "require-dev": { - "phpunit/phpunit": "^5.7", - "react/socket": "^1.3" - }, - "scripts": { - "abtest-client": "ABTEST=client && sh tests/ab/run_ab_tests.sh", - "abtest-server": "ABTEST=server && sh tests/ab/run_ab_tests.sh", - "phpunit": "phpunit --colors=always", - "test": [ - "@abtest-client", - "@abtest-server", - "@phpunit" - ] - } -} diff --git a/digital_doctor/vendor/ratchet/rfc6455/phpunit.xml.dist b/digital_doctor/vendor/ratchet/rfc6455/phpunit.xml.dist deleted file mode 100644 index 8f2e7d1..0000000 --- a/digital_doctor/vendor/ratchet/rfc6455/phpunit.xml.dist +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - tests - - test/ab - - - - - - - ./src/ - - - \ No newline at end of file diff --git a/digital_doctor/vendor/ratchet/rfc6455/src/Handshake/ClientNegotiator.php b/digital_doctor/vendor/ratchet/rfc6455/src/Handshake/ClientNegotiator.php deleted file mode 100644 index c32a1cf..0000000 --- a/digital_doctor/vendor/ratchet/rfc6455/src/Handshake/ClientNegotiator.php +++ /dev/null @@ -1,71 +0,0 @@ -verifier = new ResponseVerifier; - - $this->defaultHeader = new Request('GET', '', [ - 'Connection' => 'Upgrade' - , 'Upgrade' => 'websocket' - , 'Sec-WebSocket-Version' => $this->getVersion() - , 'User-Agent' => "Ratchet" - ]); - - if ($perMessageDeflateOptions === null) { - $perMessageDeflateOptions = PermessageDeflateOptions::createDisabled(); - } - - // https://bugs.php.net/bug.php?id=73373 - // https://bugs.php.net/bug.php?id=74240 - need >=7.1.4 or >=7.0.18 - if ($perMessageDeflateOptions->isEnabled() && - !PermessageDeflateOptions::permessageDeflateSupported()) { - trigger_error('permessage-deflate is being disabled because it is not support by your PHP version.', E_USER_NOTICE); - $perMessageDeflateOptions = PermessageDeflateOptions::createDisabled(); - } - if ($perMessageDeflateOptions->isEnabled() && !function_exists('deflate_add')) { - trigger_error('permessage-deflate is being disabled because you do not have the zlib extension.', E_USER_NOTICE); - $perMessageDeflateOptions = PermessageDeflateOptions::createDisabled(); - } - - $this->defaultHeader = $perMessageDeflateOptions->addHeaderToRequest($this->defaultHeader); - } - - public function generateRequest(UriInterface $uri) { - return $this->defaultHeader->withUri($uri) - ->withHeader("Sec-WebSocket-Key", $this->generateKey()); - } - - public function validateResponse(RequestInterface $request, ResponseInterface $response) { - return $this->verifier->verifyAll($request, $response); - } - - public function generateKey() { - $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwzyz1234567890+/='; - $charRange = strlen($chars) - 1; - $key = ''; - for ($i = 0; $i < 16; $i++) { - $key .= $chars[mt_rand(0, $charRange)]; - } - - return base64_encode($key); - } - - public function getVersion() { - return 13; - } -} diff --git a/digital_doctor/vendor/ratchet/rfc6455/src/Handshake/InvalidPermessageDeflateOptionsException.php b/digital_doctor/vendor/ratchet/rfc6455/src/Handshake/InvalidPermessageDeflateOptionsException.php deleted file mode 100644 index 191e7a5..0000000 --- a/digital_doctor/vendor/ratchet/rfc6455/src/Handshake/InvalidPermessageDeflateOptionsException.php +++ /dev/null @@ -1,7 +0,0 @@ -deflateEnabled = true; - $new->client_max_window_bits = self::MAX_WINDOW_BITS; - $new->client_no_context_takeover = false; - $new->server_max_window_bits = self::MAX_WINDOW_BITS; - $new->server_no_context_takeover = false; - - return $new; - } - - public static function createDisabled() { - return new static(); - } - - public function withClientNoContextTakeover() { - $new = clone $this; - $new->client_no_context_takeover = true; - return $new; - } - - public function withoutClientNoContextTakeover() { - $new = clone $this; - $new->client_no_context_takeover = false; - return $new; - } - - public function withServerNoContextTakeover() { - $new = clone $this; - $new->server_no_context_takeover = true; - return $new; - } - - public function withoutServerNoContextTakeover() { - $new = clone $this; - $new->server_no_context_takeover = false; - return $new; - } - - public function withServerMaxWindowBits($bits = self::MAX_WINDOW_BITS) { - if (!in_array($bits, self::$VALID_BITS)) { - throw new \Exception('server_max_window_bits must have a value between 8 and 15.'); - } - $new = clone $this; - $new->server_max_window_bits = $bits; - return $new; - } - - public function withClientMaxWindowBits($bits = self::MAX_WINDOW_BITS) { - if (!in_array($bits, self::$VALID_BITS)) { - throw new \Exception('client_max_window_bits must have a value between 8 and 15.'); - } - $new = clone $this; - $new->client_max_window_bits = $bits; - return $new; - } - - /** - * https://tools.ietf.org/html/rfc6455#section-9.1 - * https://tools.ietf.org/html/rfc7692#section-7 - * - * @param MessageInterface $requestOrResponse - * @return PermessageDeflateOptions[] - * @throws \Exception - */ - public static function fromRequestOrResponse(MessageInterface $requestOrResponse) { - $optionSets = []; - - $extHeader = preg_replace('/\s+/', '', join(', ', $requestOrResponse->getHeader('Sec-Websocket-Extensions'))); - - $configurationRequests = explode(',', $extHeader); - foreach ($configurationRequests as $configurationRequest) { - $parts = explode(';', $configurationRequest); - if (count($parts) == 0) { - continue; - } - - if ($parts[0] !== 'permessage-deflate') { - continue; - } - - array_shift($parts); - $options = new static(); - $options->deflateEnabled = true; - foreach ($parts as $part) { - $kv = explode('=', $part); - $key = $kv[0]; - $value = count($kv) > 1 ? $kv[1] : null; - - switch ($key) { - case "server_no_context_takeover": - case "client_no_context_takeover": - if ($value !== null) { - throw new InvalidPermessageDeflateOptionsException($key . ' must not have a value.'); - } - $value = true; - break; - case "server_max_window_bits": - if (!in_array($value, self::$VALID_BITS)) { - throw new InvalidPermessageDeflateOptionsException($key . ' must have a value between 8 and 15.'); - } - break; - case "client_max_window_bits": - if ($value === null) { - $value = '15'; - } - if (!in_array($value, self::$VALID_BITS)) { - throw new InvalidPermessageDeflateOptionsException($key . ' must have no value or a value between 8 and 15.'); - } - break; - default: - throw new InvalidPermessageDeflateOptionsException('Option "' . $key . '"is not valid for permessage deflate'); - } - - if ($options->$key !== null) { - throw new InvalidPermessageDeflateOptionsException($key . ' specified more than once. Connection must be declined.'); - } - - $options->$key = $value; - } - - if ($options->getClientMaxWindowBits() === null) { - $options->client_max_window_bits = 15; - } - - if ($options->getServerMaxWindowBits() === null) { - $options->server_max_window_bits = 15; - } - - $optionSets[] = $options; - } - - // always put a disabled on the end - $optionSets[] = new static(); - - return $optionSets; - } - - /** - * @return mixed - */ - public function getServerNoContextTakeover() - { - return $this->server_no_context_takeover; - } - - /** - * @return mixed - */ - public function getClientNoContextTakeover() - { - return $this->client_no_context_takeover; - } - - /** - * @return mixed - */ - public function getServerMaxWindowBits() - { - return $this->server_max_window_bits; - } - - /** - * @return mixed - */ - public function getClientMaxWindowBits() - { - return $this->client_max_window_bits; - } - - /** - * @return bool - */ - public function isEnabled() - { - return $this->deflateEnabled; - } - - /** - * @param ResponseInterface $response - * @return ResponseInterface - */ - public function addHeaderToResponse(ResponseInterface $response) - { - if (!$this->deflateEnabled) { - return $response; - } - - $header = 'permessage-deflate'; - if ($this->client_max_window_bits != 15) { - $header .= '; client_max_window_bits='. $this->client_max_window_bits; - } - if ($this->client_no_context_takeover) { - $header .= '; client_no_context_takeover'; - } - if ($this->server_max_window_bits != 15) { - $header .= '; server_max_window_bits=' . $this->server_max_window_bits; - } - if ($this->server_no_context_takeover) { - $header .= '; server_no_context_takeover'; - } - - return $response->withAddedHeader('Sec-Websocket-Extensions', $header); - } - - public function addHeaderToRequest(RequestInterface $request) { - if (!$this->deflateEnabled) { - return $request; - } - - $header = 'permessage-deflate'; - if ($this->server_no_context_takeover) { - $header .= '; server_no_context_takeover'; - } - if ($this->client_no_context_takeover) { - $header .= '; client_no_context_takeover'; - } - if ($this->server_max_window_bits != 15) { - $header .= '; server_max_window_bits=' . $this->server_max_window_bits; - } - $header .= '; client_max_window_bits'; - if ($this->client_max_window_bits != 15) { - $header .= '='. $this->client_max_window_bits; - } - - return $request->withAddedHeader('Sec-Websocket-Extensions', $header); - } - - public static function permessageDeflateSupported($version = PHP_VERSION) { - if (!function_exists('deflate_init')) { - return false; - } - if (version_compare($version, '7.1.3', '>')) { - return true; - } - if (version_compare($version, '7.0.18', '>=') - && version_compare($version, '7.1.0', '<')) { - return true; - } - - return false; - } -} diff --git a/digital_doctor/vendor/ratchet/rfc6455/src/Handshake/RequestVerifier.php b/digital_doctor/vendor/ratchet/rfc6455/src/Handshake/RequestVerifier.php deleted file mode 100644 index 9e192c5..0000000 --- a/digital_doctor/vendor/ratchet/rfc6455/src/Handshake/RequestVerifier.php +++ /dev/null @@ -1,163 +0,0 @@ -verifyMethod($request->getMethod()); - $passes += (int)$this->verifyHTTPVersion($request->getProtocolVersion()); - $passes += (int)$this->verifyRequestURI($request->getUri()->getPath()); - $passes += (int)$this->verifyHost($request->getHeader('Host')); - $passes += (int)$this->verifyUpgradeRequest($request->getHeader('Upgrade')); - $passes += (int)$this->verifyConnection($request->getHeader('Connection')); - $passes += (int)$this->verifyKey($request->getHeader('Sec-WebSocket-Key')); - $passes += (int)$this->verifyVersion($request->getHeader('Sec-WebSocket-Version')); - - return (8 === $passes); - } - - /** - * Test the HTTP method. MUST be "GET" - * @param string - * @return bool - */ - public function verifyMethod($val) { - return ('get' === strtolower($val)); - } - - /** - * Test the HTTP version passed. MUST be 1.1 or greater - * @param string|int - * @return bool - */ - public function verifyHTTPVersion($val) { - return (1.1 <= (double)$val); - } - - /** - * @param string - * @return bool - */ - public function verifyRequestURI($val) { - if ($val[0] !== '/') { - return false; - } - - if (false !== strstr($val, '#')) { - return false; - } - - if (!extension_loaded('mbstring')) { - return true; - } - - return mb_check_encoding($val, 'US-ASCII'); - } - - /** - * @param array $hostHeader - * @return bool - * @todo Once I fix HTTP::getHeaders just verify this isn't NULL or empty...or maybe need to verify it's a valid domain??? Or should it equal $_SERVER['HOST'] ? - */ - public function verifyHost(array $hostHeader) { - return (1 === count($hostHeader)); - } - - /** - * Verify the Upgrade request to WebSockets. - * @param array $upgradeHeader MUST equal "websocket" - * @return bool - */ - public function verifyUpgradeRequest(array $upgradeHeader) { - return (1 === count($upgradeHeader) && 'websocket' === strtolower($upgradeHeader[0])); - } - - /** - * Verify the Connection header - * @param array $connectionHeader MUST include "Upgrade" - * @return bool - */ - public function verifyConnection(array $connectionHeader) { - foreach ($connectionHeader as $l) { - $upgrades = array_filter( - array_map('trim', array_map('strtolower', explode(',', $l))), - function ($x) { - return 'upgrade' === $x; - } - ); - if (count($upgrades) > 0) { - return true; - } - } - return false; - } - - /** - * This function verifies the nonce is valid (64 big encoded, 16 bytes random string) - * @param array $keyHeader - * @return bool - * @todo The spec says we don't need to base64_decode - can I just check if the length is 24 and not decode? - * @todo Check the spec to see what the encoding of the key could be - */ - public function verifyKey(array $keyHeader) { - return (1 === count($keyHeader) && 16 === strlen(base64_decode($keyHeader[0]))); - } - - /** - * Verify the version passed matches this RFC - * @param string[] $versionHeader MUST equal ["13"] - * @return bool - */ - public function verifyVersion(array $versionHeader) { - return (1 === count($versionHeader) && static::VERSION === (int)$versionHeader[0]); - } - - /** - * @todo Write logic for this method. See section 4.2.1.8 - */ - public function verifyProtocol($val) { - } - - /** - * @todo Write logic for this method. See section 4.2.1.9 - */ - public function verifyExtensions($val) { - } - - public function getPermessageDeflateOptions(array $requestHeader, array $responseHeader) { - $deflate = true; - if (!isset($requestHeader['Sec-WebSocket-Extensions']) || count(array_filter($requestHeader['Sec-WebSocket-Extensions'], function ($val) { - return 'permessage-deflate' === substr($val, 0, strlen('permessage-deflate')); - })) === 0) { - $deflate = false; - } - - if (!isset($responseHeader['Sec-WebSocket-Extensions']) || count(array_filter($responseHeader['Sec-WebSocket-Extensions'], function ($val) { - return 'permessage-deflate' === substr($val, 0, strlen('permessage-deflate')); - })) === 0) { - $deflate = false; - } - - return [ - 'deflate' => $deflate, - 'no_context_takeover' => false, - 'max_window_bits' => null, - 'request_no_context_takeover' => false, - 'request_max_window_bits' => null - ]; - } -} diff --git a/digital_doctor/vendor/ratchet/rfc6455/src/Handshake/ResponseVerifier.php b/digital_doctor/vendor/ratchet/rfc6455/src/Handshake/ResponseVerifier.php deleted file mode 100644 index 453f9d6..0000000 --- a/digital_doctor/vendor/ratchet/rfc6455/src/Handshake/ResponseVerifier.php +++ /dev/null @@ -1,70 +0,0 @@ -verifyStatus($response->getStatusCode()); - $passes += (int)$this->verifyUpgrade($response->getHeader('Upgrade')); - $passes += (int)$this->verifyConnection($response->getHeader('Connection')); - $passes += (int)$this->verifySecWebSocketAccept( - $response->getHeader('Sec-WebSocket-Accept') - , $request->getHeader('Sec-WebSocket-Key') - ); - $passes += (int)$this->verifySubProtocol( - $request->getHeader('Sec-WebSocket-Protocol') - , $response->getHeader('Sec-WebSocket-Protocol') - ); - $passes += (int)$this->verifyExtensions( - $request->getHeader('Sec-WebSocket-Extensions') - , $response->getHeader('Sec-WebSocket-Extensions') - ); - - return (6 === $passes); - } - - public function verifyStatus($status) { - return ((int)$status === 101); - } - - public function verifyUpgrade(array $upgrade) { - return (in_array('websocket', array_map('strtolower', $upgrade))); - } - - public function verifyConnection(array $connection) { - return (in_array('upgrade', array_map('strtolower', $connection))); - } - - public function verifySecWebSocketAccept($swa, $key) { - return ( - 1 === count($swa) && - 1 === count($key) && - $swa[0] === $this->sign($key[0]) - ); - } - - public function sign($key) { - return base64_encode(sha1($key . NegotiatorInterface::GUID, true)); - } - - public function verifySubProtocol(array $requestHeader, array $responseHeader) { - if (0 === count($responseHeader)) { - return true; - } - - $requestedProtocols = array_map('trim', explode(',', implode(',', $requestHeader))); - - return count($responseHeader) === 1 && count(array_intersect($responseHeader, $requestedProtocols)) === 1; - } - - public function verifyExtensions(array $requestHeader, array $responseHeader) { - if (in_array('permessage-deflate', $responseHeader)) { - return strpos(implode(',', $requestHeader), 'permessage-deflate') !== false ? 1 : 0; - } - - return 1; - } -} diff --git a/digital_doctor/vendor/ratchet/rfc6455/src/Handshake/ServerNegotiator.php b/digital_doctor/vendor/ratchet/rfc6455/src/Handshake/ServerNegotiator.php deleted file mode 100644 index e4ce79b..0000000 --- a/digital_doctor/vendor/ratchet/rfc6455/src/Handshake/ServerNegotiator.php +++ /dev/null @@ -1,162 +0,0 @@ -verifier = $requestVerifier; - - // https://bugs.php.net/bug.php?id=73373 - // https://bugs.php.net/bug.php?id=74240 - need >=7.1.4 or >=7.0.18 - $supported = PermessageDeflateOptions::permessageDeflateSupported(); - if ($enablePerMessageDeflate && !$supported) { - throw new \Exception('permessage-deflate is not supported by your PHP version (need >=7.1.4 or >=7.0.18).'); - } - if ($enablePerMessageDeflate && !function_exists('deflate_add')) { - throw new \Exception('permessage-deflate is not supported because you do not have the zlib extension.'); - } - - $this->enablePerMessageDeflate = $enablePerMessageDeflate; - } - - /** - * {@inheritdoc} - */ - public function isProtocol(RequestInterface $request) { - return $this->verifier->verifyVersion($request->getHeader('Sec-WebSocket-Version')); - } - - /** - * {@inheritdoc} - */ - public function getVersionNumber() { - return RequestVerifier::VERSION; - } - - /** - * {@inheritdoc} - */ - public function handshake(RequestInterface $request) { - if (true !== $this->verifier->verifyMethod($request->getMethod())) { - return new Response(405, ['Allow' => 'GET']); - } - - if (true !== $this->verifier->verifyHTTPVersion($request->getProtocolVersion())) { - return new Response(505); - } - - if (true !== $this->verifier->verifyRequestURI($request->getUri()->getPath())) { - return new Response(400); - } - - if (true !== $this->verifier->verifyHost($request->getHeader('Host'))) { - return new Response(400); - } - - $upgradeSuggestion = [ - 'Connection' => 'Upgrade', - 'Upgrade' => 'websocket', - 'Sec-WebSocket-Version' => $this->getVersionNumber() - ]; - if (count($this->_supportedSubProtocols) > 0) { - $upgradeSuggestion['Sec-WebSocket-Protocol'] = implode(', ', array_keys($this->_supportedSubProtocols)); - } - if (true !== $this->verifier->verifyUpgradeRequest($request->getHeader('Upgrade'))) { - return new Response(426, $upgradeSuggestion, null, '1.1', 'Upgrade header MUST be provided'); - } - - if (true !== $this->verifier->verifyConnection($request->getHeader('Connection'))) { - return new Response(400, [], null, '1.1', 'Connection Upgrade MUST be requested'); - } - - if (true !== $this->verifier->verifyKey($request->getHeader('Sec-WebSocket-Key'))) { - return new Response(400, [], null, '1.1', 'Invalid Sec-WebSocket-Key'); - } - - if (true !== $this->verifier->verifyVersion($request->getHeader('Sec-WebSocket-Version'))) { - return new Response(426, $upgradeSuggestion); - } - - $headers = []; - $subProtocols = $request->getHeader('Sec-WebSocket-Protocol'); - if (count($subProtocols) > 0 || (count($this->_supportedSubProtocols) > 0 && $this->_strictSubProtocols)) { - $subProtocols = array_map('trim', explode(',', implode(',', $subProtocols))); - - $match = array_reduce($subProtocols, function($accumulator, $protocol) { - return $accumulator ?: (isset($this->_supportedSubProtocols[$protocol]) ? $protocol : null); - }, null); - - if ($this->_strictSubProtocols && null === $match) { - return new Response(426, $upgradeSuggestion, null, '1.1', 'No Sec-WebSocket-Protocols requested supported'); - } - - if (null !== $match) { - $headers['Sec-WebSocket-Protocol'] = $match; - } - } - - $response = new Response(101, array_merge($headers, [ - 'Upgrade' => 'websocket' - , 'Connection' => 'Upgrade' - , 'Sec-WebSocket-Accept' => $this->sign((string)$request->getHeader('Sec-WebSocket-Key')[0]) - , 'X-Powered-By' => 'Ratchet' - ])); - - try { - $perMessageDeflateRequest = PermessageDeflateOptions::fromRequestOrResponse($request)[0]; - } catch (InvalidPermessageDeflateOptionsException $e) { - return new Response(400, [], null, '1.1', $e->getMessage()); - } - - if ($this->enablePerMessageDeflate && $perMessageDeflateRequest->isEnabled()) { - $response = $perMessageDeflateRequest->addHeaderToResponse($response); - } - - return $response; - } - - /** - * Used when doing the handshake to encode the key, verifying client/server are speaking the same language - * @param string $key - * @return string - * @internal - */ - public function sign($key) { - return base64_encode(sha1($key . static::GUID, true)); - } - - /** - * @param array $protocols - */ - function setSupportedSubProtocols(array $protocols) { - $this->_supportedSubProtocols = array_flip($protocols); - } - - /** - * If enabled and support for a subprotocol has been added handshake - * will not upgrade if a match between request and supported subprotocols - * @param boolean $enable - * @todo Consider extending this interface and moving this there. - * The spec does says the server can fail for this reason, but - * it is not a requirement. This is an implementation detail. - */ - function setStrictSubProtocolCheck($enable) { - $this->_strictSubProtocols = (boolean)$enable; - } -} diff --git a/digital_doctor/vendor/ratchet/rfc6455/src/Messaging/CloseFrameChecker.php b/digital_doctor/vendor/ratchet/rfc6455/src/Messaging/CloseFrameChecker.php deleted file mode 100644 index 3d800e5..0000000 --- a/digital_doctor/vendor/ratchet/rfc6455/src/Messaging/CloseFrameChecker.php +++ /dev/null @@ -1,24 +0,0 @@ -validCloseCodes = [ - Frame::CLOSE_NORMAL, - Frame::CLOSE_GOING_AWAY, - Frame::CLOSE_PROTOCOL, - Frame::CLOSE_BAD_DATA, - Frame::CLOSE_BAD_PAYLOAD, - Frame::CLOSE_POLICY, - Frame::CLOSE_TOO_BIG, - Frame::CLOSE_MAND_EXT, - Frame::CLOSE_SRV_ERR, - ]; - } - - public function __invoke($val) { - return ($val >= 3000 && $val <= 4999) || in_array($val, $this->validCloseCodes); - } -} diff --git a/digital_doctor/vendor/ratchet/rfc6455/src/Messaging/DataInterface.php b/digital_doctor/vendor/ratchet/rfc6455/src/Messaging/DataInterface.php deleted file mode 100644 index 18aa2e3..0000000 --- a/digital_doctor/vendor/ratchet/rfc6455/src/Messaging/DataInterface.php +++ /dev/null @@ -1,34 +0,0 @@ - $ufExceptionFactory - */ - public function __construct($payload = null, $final = true, $opcode = 1, callable $ufExceptionFactory = null) { - $this->ufeg = $ufExceptionFactory ?: static function($msg = '') { - return new \UnderflowException($msg); - }; - - if (null === $payload) { - return; - } - - $this->defPayLen = strlen($payload); - $this->firstByte = ($final ? 128 : 0) + $opcode; - $this->secondByte = $this->defPayLen; - $this->isCoalesced = true; - - $ext = ''; - if ($this->defPayLen > 65535) { - $ext = pack('NN', 0, $this->defPayLen); - $this->secondByte = 127; - } elseif ($this->defPayLen > 125) { - $ext = pack('n', $this->defPayLen); - $this->secondByte = 126; - } - - $this->data = chr($this->firstByte) . chr($this->secondByte) . $ext . $payload; - $this->bytesRecvd = 2 + strlen($ext) + $this->defPayLen; - } - - /** - * {@inheritdoc} - */ - public function isCoalesced() { - if (true === $this->isCoalesced) { - return true; - } - - try { - $payload_length = $this->getPayloadLength(); - $payload_start = $this->getPayloadStartingByte(); - } catch (\UnderflowException $e) { - return false; - } - - $this->isCoalesced = $this->bytesRecvd >= $payload_length + $payload_start; - - return $this->isCoalesced; - } - - /** - * {@inheritdoc} - */ - public function addBuffer($buf) { - $len = strlen($buf); - - $this->data .= $buf; - $this->bytesRecvd += $len; - - if ($this->firstByte === -1 && $this->bytesRecvd !== 0) { - $this->firstByte = ord($this->data[0]); - } - - if ($this->secondByte === -1 && $this->bytesRecvd >= 2) { - $this->secondByte = ord($this->data[1]); - } - } - - /** - * {@inheritdoc} - */ - public function isFinal() { - if (-1 === $this->firstByte) { - throw call_user_func($this->ufeg, 'Not enough bytes received to determine if this is the final frame in message'); - } - - return 128 === ($this->firstByte & 128); - } - - public function setRsv1($value = true) { - if (strlen($this->data) == 0) { - throw new \UnderflowException("Cannot set Rsv1 because there is no data."); - } - - $this->firstByte = - ($this->isFinal() ? 128 : 0) - + $this->getOpcode() - + ($value ? 64 : 0) - + ($this->getRsv2() ? 32 : 0) - + ($this->getRsv3() ? 16 : 0) - ; - - $this->data[0] = chr($this->firstByte); - return $this; - } - - /** - * @return boolean - * @throws \UnderflowException - */ - public function getRsv1() { - if (-1 === $this->firstByte) { - throw call_user_func($this->ufeg, 'Not enough bytes received to determine reserved bit'); - } - - return 64 === ($this->firstByte & 64); - } - - /** - * @return boolean - * @throws \UnderflowException - */ - public function getRsv2() { - if (-1 === $this->firstByte) { - throw call_user_func($this->ufeg, 'Not enough bytes received to determine reserved bit'); - } - - return 32 === ($this->firstByte & 32); - } - - /** - * @return boolean - * @throws \UnderflowException - */ - public function getRsv3() { - if (-1 === $this->firstByte) { - throw call_user_func($this->ufeg, 'Not enough bytes received to determine reserved bit'); - } - - return 16 === ($this->firstByte & 16); - } - - /** - * {@inheritdoc} - */ - public function isMasked() { - if (-1 === $this->secondByte) { - throw call_user_func($this->ufeg, "Not enough bytes received ({$this->bytesRecvd}) to determine if mask is set"); - } - - return 128 === ($this->secondByte & 128); - } - - /** - * {@inheritdoc} - */ - public function getMaskingKey() { - if (!$this->isMasked()) { - return ''; - } - - $start = 1 + $this->getNumPayloadBytes(); - - if ($this->bytesRecvd < $start + static::MASK_LENGTH) { - throw call_user_func($this->ufeg, 'Not enough data buffered to calculate the masking key'); - } - - return substr($this->data, $start, static::MASK_LENGTH); - } - - /** - * Create a 4 byte masking key - * @return string - */ - public function generateMaskingKey() { - $mask = ''; - - for ($i = 1; $i <= static::MASK_LENGTH; $i++) { - $mask .= chr(rand(32, 126)); - } - - return $mask; - } - - /** - * Apply a mask to the payload - * @param string|null If NULL is passed a masking key will be generated - * @throws \OutOfBoundsException - * @throws \InvalidArgumentException If there is an issue with the given masking key - * @return Frame - */ - public function maskPayload($maskingKey = null) { - if (null === $maskingKey) { - $maskingKey = $this->generateMaskingKey(); - } - - if (static::MASK_LENGTH !== strlen($maskingKey)) { - throw new \InvalidArgumentException("Masking key must be " . static::MASK_LENGTH ." characters"); - } - - if (extension_loaded('mbstring') && true !== mb_check_encoding($maskingKey, 'US-ASCII')) { - throw new \OutOfBoundsException("Masking key MUST be ASCII"); - } - - $this->unMaskPayload(); - - $this->secondByte = $this->secondByte | 128; - $this->data[1] = chr($this->secondByte); - - $this->data = substr_replace($this->data, $maskingKey, $this->getNumPayloadBytes() + 1, 0); - - $this->bytesRecvd += static::MASK_LENGTH; - $this->data = substr_replace($this->data, $this->applyMask($maskingKey), $this->getPayloadStartingByte(), $this->getPayloadLength()); - - return $this; - } - - /** - * Remove a mask from the payload - * @throws \UnderFlowException If the frame is not coalesced - * @return Frame - */ - public function unMaskPayload() { - if (!$this->isCoalesced()) { - throw call_user_func($this->ufeg, 'Frame must be coalesced before applying mask'); - } - - if (!$this->isMasked()) { - return $this; - } - - $maskingKey = $this->getMaskingKey(); - - $this->secondByte = $this->secondByte & ~128; - $this->data[1] = chr($this->secondByte); - - $this->data = substr_replace($this->data, '', $this->getNumPayloadBytes() + 1, static::MASK_LENGTH); - - $this->bytesRecvd -= static::MASK_LENGTH; - $this->data = substr_replace($this->data, $this->applyMask($maskingKey), $this->getPayloadStartingByte(), $this->getPayloadLength()); - - return $this; - } - - /** - * Apply a mask to a string or the payload of the instance - * @param string $maskingKey The 4 character masking key to be applied - * @param string|null $payload A string to mask or null to use the payload - * @throws \UnderflowException If using the payload but enough hasn't been buffered - * @return string The masked string - */ - public function applyMask($maskingKey, $payload = null) { - if (null === $payload) { - if (!$this->isCoalesced()) { - throw call_user_func($this->ufeg, 'Frame must be coalesced to apply a mask'); - } - - $payload = substr($this->data, $this->getPayloadStartingByte(), $this->getPayloadLength()); - } - - $len = strlen($payload); - - if (0 === $len) { - return ''; - } - - return $payload ^ str_pad('', $len, $maskingKey, STR_PAD_RIGHT); - } - - /** - * {@inheritdoc} - */ - public function getOpcode() { - if (-1 === $this->firstByte) { - throw call_user_func($this->ufeg, 'Not enough bytes received to determine opcode'); - } - - return ($this->firstByte & ~240); - } - - /** - * Gets the decimal value of bits 9 (10th) through 15 inclusive - * @return int - * @throws \UnderflowException If the buffer doesn't have enough data to determine this - */ - protected function getFirstPayloadVal() { - if (-1 === $this->secondByte) { - throw call_user_func($this->ufeg, 'Not enough bytes received'); - } - - return $this->secondByte & 127; - } - - /** - * @return int (7|23|71) Number of bits defined for the payload length in the fame - * @throws \UnderflowException - */ - protected function getNumPayloadBits() { - if (-1 === $this->secondByte) { - throw call_user_func($this->ufeg, 'Not enough bytes received'); - } - - // By default 7 bits are used to describe the payload length - // These are bits 9 (10th) through 15 inclusive - $bits = 7; - - // Get the value of those bits - $check = $this->getFirstPayloadVal(); - - // If the value is 126 the 7 bits plus the next 16 are used to describe the payload length - if ($check >= 126) { - $bits += 16; - } - - // If the value of the initial payload length are is 127 an additional 48 bits are used to describe length - // Note: The documentation specifies the length is to be 63 bits, but I think that's a typo and is 64 (16+48) - if ($check === 127) { - $bits += 48; - } - - return $bits; - } - - /** - * This just returns the number of bytes used in the frame to describe the payload length (as opposed to # of bits) - * @see getNumPayloadBits - */ - protected function getNumPayloadBytes() { - return (1 + $this->getNumPayloadBits()) / 8; - } - - /** - * {@inheritdoc} - */ - public function getPayloadLength() { - if ($this->defPayLen !== -1) { - return $this->defPayLen; - } - - $this->defPayLen = $this->getFirstPayloadVal(); - if ($this->defPayLen <= 125) { - return $this->getPayloadLength(); - } - - $byte_length = $this->getNumPayloadBytes(); - if ($this->bytesRecvd < 1 + $byte_length) { - $this->defPayLen = -1; - throw call_user_func($this->ufeg, 'Not enough data buffered to determine payload length'); - } - - $len = 0; - for ($i = 2; $i <= $byte_length; $i++) { - $len <<= 8; - $len += ord($this->data[$i]); - } - - $this->defPayLen = $len; - - return $this->getPayloadLength(); - } - - /** - * {@inheritdoc} - */ - public function getPayloadStartingByte() { - return 1 + $this->getNumPayloadBytes() + ($this->isMasked() ? static::MASK_LENGTH : 0); - } - - /** - * {@inheritdoc} - * @todo Consider not checking mask, always returning the payload, masked or not - */ - public function getPayload() { - if (!$this->isCoalesced()) { - throw call_user_func($this->ufeg, 'Can not return partial message'); - } - - return $this->__toString(); - } - - /** - * Get the raw contents of the frame - * @todo This is untested, make sure the substr is right - trying to return the frame w/o the overflow - */ - public function getContents() { - return substr($this->data, 0, $this->getPayloadStartingByte() + $this->getPayloadLength()); - } - - public function __toString() { - $payload = (string)substr($this->data, $this->getPayloadStartingByte(), $this->getPayloadLength()); - - if ($this->isMasked()) { - $payload = $this->applyMask($this->getMaskingKey(), $payload); - } - - return $payload; - } - - /** - * Sometimes clients will concatenate more than one frame over the wire - * This method will take the extra bytes off the end and return them - * @return string - */ - public function extractOverflow() { - if ($this->isCoalesced()) { - $endPoint = $this->getPayloadLength(); - $endPoint += $this->getPayloadStartingByte(); - - if ($this->bytesRecvd > $endPoint) { - $overflow = substr($this->data, $endPoint); - $this->data = substr($this->data, 0, $endPoint); - - return $overflow; - } - } - - return ''; - } -} diff --git a/digital_doctor/vendor/ratchet/rfc6455/src/Messaging/FrameInterface.php b/digital_doctor/vendor/ratchet/rfc6455/src/Messaging/FrameInterface.php deleted file mode 100644 index dc24091..0000000 --- a/digital_doctor/vendor/ratchet/rfc6455/src/Messaging/FrameInterface.php +++ /dev/null @@ -1,38 +0,0 @@ -_frames = new \SplDoublyLinkedList; - $this->len = 0; - } - - #[\ReturnTypeWillChange] - public function getIterator() { - return $this->_frames; - } - - /** - * {@inheritdoc} - */ - #[\ReturnTypeWillChange] - public function count() { - return count($this->_frames); - } - - /** - * {@inheritdoc} - */ - #[\ReturnTypeWillChange] - public function isCoalesced() { - if (count($this->_frames) == 0) { - return false; - } - - $last = $this->_frames->top(); - - return ($last->isCoalesced() && $last->isFinal()); - } - - /** - * {@inheritdoc} - */ - public function addFrame(FrameInterface $fragment) { - $this->len += $fragment->getPayloadLength(); - $this->_frames->push($fragment); - - return $this; - } - - /** - * {@inheritdoc} - */ - public function getOpcode() { - if (count($this->_frames) == 0) { - throw new \UnderflowException('No frames have been added to this message'); - } - - return $this->_frames->bottom()->getOpcode(); - } - - /** - * {@inheritdoc} - */ - public function getPayloadLength() { - return $this->len; - } - - /** - * {@inheritdoc} - */ - public function getPayload() { - if (!$this->isCoalesced()) { - throw new \UnderflowException('Message has not been put back together yet'); - } - - return $this->__toString(); - } - - /** - * {@inheritdoc} - */ - public function getContents() { - if (!$this->isCoalesced()) { - throw new \UnderflowException("Message has not been put back together yet"); - } - - $buffer = ''; - - foreach ($this->_frames as $frame) { - $buffer .= $frame->getContents(); - } - - return $buffer; - } - - public function __toString() { - $buffer = ''; - - foreach ($this->_frames as $frame) { - $buffer .= $frame->getPayload(); - } - - return $buffer; - } - - /** - * @return boolean - */ - public function isBinary() { - if ($this->_frames->isEmpty()) { - throw new \UnderflowException('Not enough data has been received to determine if message is binary'); - } - - return Frame::OP_BINARY === $this->_frames->bottom()->getOpcode(); - } - - /** - * @return boolean - */ - public function getRsv1() { - if ($this->_frames->isEmpty()) { - return false; - //throw new \UnderflowException('Not enough data has been received to determine if message is binary'); - } - - return $this->_frames->bottom()->getRsv1(); - } -} diff --git a/digital_doctor/vendor/ratchet/rfc6455/src/Messaging/MessageBuffer.php b/digital_doctor/vendor/ratchet/rfc6455/src/Messaging/MessageBuffer.php deleted file mode 100644 index e5d197b..0000000 --- a/digital_doctor/vendor/ratchet/rfc6455/src/Messaging/MessageBuffer.php +++ /dev/null @@ -1,550 +0,0 @@ -closeFrameChecker = $frameChecker; - $this->checkForMask = (bool)$expectMask; - - $this->exceptionFactory ?: $exceptionFactory = function($msg) { - return new \UnderflowException($msg); - }; - - $this->onMessage = $onMessage; - $this->onControl = $onControl ?: function() {}; - - $this->sender = $sender; - - $this->permessageDeflateOptions = $permessageDeflateOptions ?: PermessageDeflateOptions::createDisabled(); - - $this->deflateEnabled = $this->permessageDeflateOptions->isEnabled(); - - if ($this->deflateEnabled && !is_callable($this->sender)) { - throw new \InvalidArgumentException('sender must be set when deflate is enabled'); - } - - $this->compressedMessage = false; - - $this->leftovers = ''; - - $memory_limit_bytes = static::getMemoryLimit(); - - if ($maxMessagePayloadSize === null) { - $maxMessagePayloadSize = (int)($memory_limit_bytes / 4); - } - if ($maxFramePayloadSize === null) { - $maxFramePayloadSize = (int)($memory_limit_bytes / 4); - } - - if (!is_int($maxFramePayloadSize) || $maxFramePayloadSize > 0x7FFFFFFFFFFFFFFF || $maxFramePayloadSize < 0) { // this should be interesting on non-64 bit systems - throw new \InvalidArgumentException($maxFramePayloadSize . ' is not a valid maxFramePayloadSize'); - } - $this->maxFramePayloadSize = $maxFramePayloadSize; - - if (!is_int($maxMessagePayloadSize) || $maxMessagePayloadSize > 0x7FFFFFFFFFFFFFFF || $maxMessagePayloadSize < 0) { - throw new \InvalidArgumentException($maxMessagePayloadSize . 'is not a valid maxMessagePayloadSize'); - } - $this->maxMessagePayloadSize = $maxMessagePayloadSize; - } - - public function onData($data) { - $data = $this->leftovers . $data; - $dataLen = strlen($data); - - if ($dataLen < 2) { - $this->leftovers = $data; - - return; - } - - $frameStart = 0; - while ($frameStart + 2 <= $dataLen) { - $headerSize = 2; - $payload_length = unpack('C', $data[$frameStart + 1] & "\x7f")[1]; - $isMasked = ($data[$frameStart + 1] & "\x80") === "\x80"; - $headerSize += $isMasked ? 4 : 0; - if ($payload_length > 125 && ($dataLen - $frameStart < $headerSize + 125)) { - // no point of checking - this frame is going to be bigger than the buffer is right now - break; - } - if ($payload_length > 125) { - $payloadLenBytes = $payload_length === 126 ? 2 : 8; - $headerSize += $payloadLenBytes; - $bytesToUpack = substr($data, $frameStart + 2, $payloadLenBytes); - $payload_length = $payload_length === 126 - ? unpack('n', $bytesToUpack)[1] - : unpack('J', $bytesToUpack)[1]; - } - - $closeFrame = null; - - if ($payload_length < 0) { - // this can happen when unpacking in php - $closeFrame = $this->newCloseFrame(Frame::CLOSE_PROTOCOL, 'Invalid frame length'); - } - - if (!$closeFrame && $this->maxFramePayloadSize > 1 && $payload_length > $this->maxFramePayloadSize) { - $closeFrame = $this->newCloseFrame(Frame::CLOSE_TOO_BIG, 'Maximum frame size exceeded'); - } - - if (!$closeFrame && $this->maxMessagePayloadSize > 0 - && $payload_length + ($this->messageBuffer ? $this->messageBuffer->getPayloadLength() : 0) > $this->maxMessagePayloadSize) { - $closeFrame = $this->newCloseFrame(Frame::CLOSE_TOO_BIG, 'Maximum message size exceeded'); - } - - if ($closeFrame !== null) { - $onControl = $this->onControl; - $onControl($closeFrame); - $this->leftovers = ''; - - return; - } - - $isCoalesced = $dataLen - $frameStart >= $payload_length + $headerSize; - if (!$isCoalesced) { - break; - } - $this->processData(substr($data, $frameStart, $payload_length + $headerSize)); - $frameStart = $frameStart + $payload_length + $headerSize; - } - - $this->leftovers = substr($data, $frameStart); - } - - /** - * @param string $data - * @return null - */ - private function processData($data) { - $this->messageBuffer ?: $this->messageBuffer = $this->newMessage(); - $this->frameBuffer ?: $this->frameBuffer = $this->newFrame(); - - $this->frameBuffer->addBuffer($data); - - $onMessage = $this->onMessage; - $onControl = $this->onControl; - - $this->frameBuffer = $this->frameCheck($this->frameBuffer); - - $this->frameBuffer->unMaskPayload(); - - $opcode = $this->frameBuffer->getOpcode(); - - if ($opcode > 2) { - $onControl($this->frameBuffer, $this); - - if (Frame::OP_CLOSE === $opcode) { - return ''; - } - } else { - if ($this->messageBuffer->count() === 0 && $this->frameBuffer->getRsv1()) { - $this->compressedMessage = true; - } - if ($this->compressedMessage) { - $this->frameBuffer = $this->inflateFrame($this->frameBuffer); - } - - $this->messageBuffer->addFrame($this->frameBuffer); - } - - $this->frameBuffer = null; - - if ($this->messageBuffer->isCoalesced()) { - $msgCheck = $this->checkMessage($this->messageBuffer); - - $msgBuffer = $this->messageBuffer; - $this->messageBuffer = null; - - if (true !== $msgCheck) { - $onControl($this->newCloseFrame($msgCheck, 'Ratchet detected an invalid UTF-8 payload'), $this); - } else { - $onMessage($msgBuffer, $this); - } - - $this->messageBuffer = null; - $this->compressedMessage = false; - - if ($this->permessageDeflateOptions->getServerNoContextTakeover()) { - $this->inflator = null; - } - } - } - - /** - * Check a frame to be added to the current message buffer - * @param \Ratchet\RFC6455\Messaging\FrameInterface|FrameInterface $frame - * @return \Ratchet\RFC6455\Messaging\FrameInterface|FrameInterface - */ - public function frameCheck(FrameInterface $frame) { - if ((false !== $frame->getRsv1() && !$this->deflateEnabled) || - false !== $frame->getRsv2() || - false !== $frame->getRsv3() - ) { - return $this->newCloseFrame(Frame::CLOSE_PROTOCOL, 'Ratchet detected an invalid reserve code'); - } - - if ($this->checkForMask && !$frame->isMasked()) { - return $this->newCloseFrame(Frame::CLOSE_PROTOCOL, 'Ratchet detected an incorrect frame mask'); - } - - $opcode = $frame->getOpcode(); - - if ($opcode > 2) { - if ($frame->getPayloadLength() > 125 || !$frame->isFinal()) { - return $this->newCloseFrame(Frame::CLOSE_PROTOCOL, 'Ratchet detected a mismatch between final bit and indicated payload length'); - } - - switch ($opcode) { - case Frame::OP_CLOSE: - $closeCode = 0; - - $bin = $frame->getPayload(); - - if (empty($bin)) { - return $this->newCloseFrame(Frame::CLOSE_NORMAL); - } - - if (strlen($bin) === 1) { - return $this->newCloseFrame(Frame::CLOSE_PROTOCOL, 'Ratchet detected an invalid close code'); - } - - if (strlen($bin) >= 2) { - list($closeCode) = array_merge(unpack('n*', substr($bin, 0, 2))); - } - - $checker = $this->closeFrameChecker; - if (!$checker($closeCode)) { - return $this->newCloseFrame(Frame::CLOSE_PROTOCOL, 'Ratchet detected an invalid close code'); - } - - if (!$this->checkUtf8(substr($bin, 2))) { - return $this->newCloseFrame(Frame::CLOSE_BAD_PAYLOAD, 'Ratchet detected an invalid UTF-8 payload in the close reason'); - } - - return $frame; - break; - case Frame::OP_PING: - case Frame::OP_PONG: - break; - default: - return $this->newCloseFrame(Frame::CLOSE_PROTOCOL, 'Ratchet detected an invalid OP code'); - break; - } - - return $frame; - } - - if (Frame::OP_CONTINUE === $frame->getOpcode() && 0 === count($this->messageBuffer)) { - return $this->newCloseFrame(Frame::CLOSE_PROTOCOL, 'Ratchet detected the first frame of a message was a continue'); - } - - if (count($this->messageBuffer) > 0 && Frame::OP_CONTINUE !== $frame->getOpcode()) { - return $this->newCloseFrame(Frame::CLOSE_PROTOCOL, 'Ratchet detected invalid OP code when expecting continue frame'); - } - - return $frame; - } - - /** - * Determine if a message is valid - * @param \Ratchet\RFC6455\Messaging\MessageInterface - * @return bool|int true if valid - false if incomplete - int of recommended close code - */ - public function checkMessage(MessageInterface $message) { - if (!$message->isBinary()) { - if (!$this->checkUtf8($message->getPayload())) { - return Frame::CLOSE_BAD_PAYLOAD; - } - } - - return true; - } - - private function checkUtf8($string) { - if (extension_loaded('mbstring')) { - return mb_check_encoding($string, 'UTF-8'); - } - - return preg_match('//u', $string); - } - - /** - * @return \Ratchet\RFC6455\Messaging\MessageInterface - */ - public function newMessage() { - return new Message; - } - - /** - * @param string|null $payload - * @param bool|null $final - * @param int|null $opcode - * @return \Ratchet\RFC6455\Messaging\FrameInterface - */ - public function newFrame($payload = null, $final = null, $opcode = null) { - return new Frame($payload, $final, $opcode, $this->exceptionFactory); - } - - public function newCloseFrame($code, $reason = '') { - return $this->newFrame(pack('n', $code) . $reason, true, Frame::OP_CLOSE); - } - - public function sendFrame(Frame $frame) { - if ($this->sender === null) { - throw new \Exception('To send frames using the MessageBuffer, sender must be set.'); - } - - if ($this->deflateEnabled && - ($frame->getOpcode() === Frame::OP_TEXT || $frame->getOpcode() === Frame::OP_BINARY)) { - $frame = $this->deflateFrame($frame); - } - - if (!$this->checkForMask) { - $frame->maskPayload(); - } - - $sender = $this->sender; - $sender($frame->getContents()); - } - - public function sendMessage($messagePayload, $final = true, $isBinary = false) { - $opCode = $isBinary ? Frame::OP_BINARY : Frame::OP_TEXT; - if ($this->streamingMessageOpCode === -1) { - $this->streamingMessageOpCode = $opCode; - } - - if ($this->streamingMessageOpCode !== $opCode) { - throw new \Exception('Binary and text message parts cannot be streamed together.'); - } - - $frame = $this->newFrame($messagePayload, $final, $opCode); - - $this->sendFrame($frame); - - if ($final) { - // reset deflator if client doesn't remember contexts - if ($this->getDeflateNoContextTakeover()) { - $this->deflator = null; - } - $this->streamingMessageOpCode = -1; - } - } - - private $inflator; - - private function getDeflateNoContextTakeover() { - return $this->checkForMask ? - $this->permessageDeflateOptions->getServerNoContextTakeover() : - $this->permessageDeflateOptions->getClientNoContextTakeover(); - } - - private function getDeflateWindowBits() { - return $this->checkForMask ? $this->permessageDeflateOptions->getServerMaxWindowBits() : $this->permessageDeflateOptions->getClientMaxWindowBits(); - } - - private function getInflateNoContextTakeover() { - return $this->checkForMask ? - $this->permessageDeflateOptions->getClientNoContextTakeover() : - $this->permessageDeflateOptions->getServerNoContextTakeover(); - } - - private function getInflateWindowBits() { - return $this->checkForMask ? $this->permessageDeflateOptions->getClientMaxWindowBits() : $this->permessageDeflateOptions->getServerMaxWindowBits(); - } - - private function inflateFrame(Frame $frame) { - if ($this->inflator === null) { - $this->inflator = inflate_init( - ZLIB_ENCODING_RAW, - [ - 'level' => -1, - 'memory' => 8, - 'window' => $this->getInflateWindowBits(), - 'strategy' => ZLIB_DEFAULT_STRATEGY - ] - ); - } - - $terminator = ''; - if ($frame->isFinal()) { - $terminator = "\x00\x00\xff\xff"; - } - - gc_collect_cycles(); // memory runs away if we don't collect ?? - - return new Frame( - inflate_add($this->inflator, $frame->getPayload() . $terminator), - $frame->isFinal(), - $frame->getOpcode() - ); - } - - private $deflator; - - private function deflateFrame(Frame $frame) - { - if ($frame->getRsv1()) { - return $frame; // frame is already deflated - } - - if ($this->deflator === null) { - $bits = (int)$this->getDeflateWindowBits(); - if ($bits === 8) { - $bits = 9; - } - $this->deflator = deflate_init( - ZLIB_ENCODING_RAW, - [ - 'level' => -1, - 'memory' => 8, - 'window' => $bits, - 'strategy' => ZLIB_DEFAULT_STRATEGY - ] - ); - } - - // there is an issue in the zlib extension for php where - // deflate_add does not check avail_out to see if the buffer filled - // this only seems to be an issue for payloads between 16 and 64 bytes - // This if statement is a hack fix to break the output up allowing us - // to call deflate_add twice which should clear the buffer issue -// if ($frame->getPayloadLength() >= 16 && $frame->getPayloadLength() <= 64) { -// // try processing in 8 byte chunks -// // https://bugs.php.net/bug.php?id=73373 -// $payload = ""; -// $orig = $frame->getPayload(); -// $partSize = 8; -// while (strlen($orig) > 0) { -// $part = substr($orig, 0, $partSize); -// $orig = substr($orig, strlen($part)); -// $flags = strlen($orig) > 0 ? ZLIB_PARTIAL_FLUSH : ZLIB_SYNC_FLUSH; -// $payload .= deflate_add($this->deflator, $part, $flags); -// } -// } else { - $payload = deflate_add( - $this->deflator, - $frame->getPayload(), - ZLIB_SYNC_FLUSH - ); -// } - - $deflatedFrame = new Frame( - substr($payload, 0, $frame->isFinal() ? -4 : strlen($payload)), - $frame->isFinal(), - $frame->getOpcode() - ); - - if ($frame->isFinal()) { - $deflatedFrame->setRsv1(); - } - - return $deflatedFrame; - } - - /** - * This is a separate function for testing purposes - * $memory_limit is only used for testing - * - * @param null|string $memory_limit - * @return int - */ - private static function getMemoryLimit($memory_limit = null) { - $memory_limit = $memory_limit === null ? \trim(\ini_get('memory_limit')) : $memory_limit; - $memory_limit_bytes = 0; - if ($memory_limit !== '') { - $shifty = ['k' => 0, 'm' => 10, 'g' => 20]; - $multiplier = strlen($memory_limit) > 1 ? substr(strtolower($memory_limit), -1) : ''; - $memory_limit = (int)$memory_limit; - $memory_limit_bytes = in_array($multiplier, array_keys($shifty), true) ? $memory_limit * 1024 << $shifty[$multiplier] : $memory_limit; - } - - return $memory_limit_bytes < 0 ? 0 : $memory_limit_bytes; - } -} diff --git a/digital_doctor/vendor/ratchet/rfc6455/src/Messaging/MessageInterface.php b/digital_doctor/vendor/ratchet/rfc6455/src/Messaging/MessageInterface.php deleted file mode 100644 index fd7212e..0000000 --- a/digital_doctor/vendor/ratchet/rfc6455/src/Messaging/MessageInterface.php +++ /dev/null @@ -1,20 +0,0 @@ -markTestSkipped('Autobahn TestSuite results not found'); - } - - $resultsJson = file_get_contents($fileName); - $results = json_decode($resultsJson); - $agentName = array_keys(get_object_vars($results))[0]; - - foreach ($results->$agentName as $name => $result) { - if ($result->behavior === "INFORMATIONAL") { - continue; - } - - $this->assertTrue(in_array($result->behavior, ["OK", "NON-STRICT"]), "Autobahn test case " . $name . " in " . $fileName); - } - } - - public function testAutobahnClientResults() { - $this->verifyAutobahnResults(__DIR__ . '/ab/reports/clients/index.json'); - } - - public function testAutobahnServerResults() { - $this->verifyAutobahnResults(__DIR__ . '/ab/reports/servers/index.json'); - } -} diff --git a/digital_doctor/vendor/ratchet/rfc6455/tests/ab/clientRunner.php b/digital_doctor/vendor/ratchet/rfc6455/tests/ab/clientRunner.php deleted file mode 100644 index c6becbc..0000000 --- a/digital_doctor/vendor/ratchet/rfc6455/tests/ab/clientRunner.php +++ /dev/null @@ -1,268 +0,0 @@ - 1 ? $argv[1] : "127.0.0.1"; - -$loop = React\EventLoop\Factory::create(); - -$connector = new Connector($loop); - -function echoStreamerFactory($conn, $permessageDeflateOptions = null) -{ - $permessageDeflateOptions = $permessageDeflateOptions ?: PermessageDeflateOptions::createDisabled(); - - return new \Ratchet\RFC6455\Messaging\MessageBuffer( - new \Ratchet\RFC6455\Messaging\CloseFrameChecker, - function (\Ratchet\RFC6455\Messaging\MessageInterface $msg, MessageBuffer $messageBuffer) use ($conn) { - $messageBuffer->sendMessage($msg->getPayload(), true, $msg->isBinary()); - }, - function (\Ratchet\RFC6455\Messaging\FrameInterface $frame, MessageBuffer $messageBuffer) use ($conn) { - switch ($frame->getOpcode()) { - case Frame::OP_PING: - return $conn->write((new Frame($frame->getPayload(), true, Frame::OP_PONG))->maskPayload()->getContents()); - break; - case Frame::OP_CLOSE: - return $conn->end((new Frame($frame->getPayload(), true, Frame::OP_CLOSE))->maskPayload()->getContents()); - break; - } - }, - false, - null, - null, - null, - [$conn, 'write'], - $permessageDeflateOptions - ); -} - -function getTestCases() { - global $testServer; - global $connector; - - $deferred = new Deferred(); - - $connector->connect($testServer . ':9002')->then(function (ConnectionInterface $connection) use ($deferred, $testServer) { - $cn = new ClientNegotiator(); - $cnRequest = $cn->generateRequest(new Uri('ws://' . $testServer . ':9002/getCaseCount')); - - $rawResponse = ""; - $response = null; - - /** @var MessageBuffer $ms */ - $ms = null; - - $connection->on('data', function ($data) use ($connection, &$rawResponse, &$response, &$ms, $cn, $deferred, &$context, $cnRequest) { - if ($response === null) { - $rawResponse .= $data; - $pos = strpos($rawResponse, "\r\n\r\n"); - if ($pos) { - $data = substr($rawResponse, $pos + 4); - $rawResponse = substr($rawResponse, 0, $pos + 4); - $response = Message::parseResponse($rawResponse); - - if (!$cn->validateResponse($cnRequest, $response)) { - $connection->end(); - $deferred->reject(); - } else { - $ms = new MessageBuffer( - new CloseFrameChecker, - function (MessageInterface $msg) use ($deferred, $connection) { - $deferred->resolve($msg->getPayload()); - $connection->close(); - }, - null, - false, - null, - null, - null, - function () {} - ); - } - } - } - - // feed the message streamer - if ($ms) { - $ms->onData($data); - } - }); - - $connection->write(Message::toString($cnRequest)); - }); - - return $deferred->promise(); -} - -$cn = new \Ratchet\RFC6455\Handshake\ClientNegotiator( - PermessageDeflateOptions::permessageDeflateSupported() ? PermessageDeflateOptions::createEnabled() : null); - -function runTest($case) -{ - global $connector; - global $testServer; - global $cn; - - $casePath = "/runCase?case={$case}&agent=" . AGENT; - - $deferred = new Deferred(); - - $connector->connect($testServer . ':9002')->then(function (ConnectionInterface $connection) use ($deferred, $casePath, $case, $testServer) { - $cn = new ClientNegotiator( - PermessageDeflateOptions::permessageDeflateSupported() ? PermessageDeflateOptions::createEnabled() : null); - $cnRequest = $cn->generateRequest(new Uri('ws://' . $testServer . ':9002' . $casePath)); - - $rawResponse = ""; - $response = null; - - $ms = null; - - $connection->on('data', function ($data) use ($connection, &$rawResponse, &$response, &$ms, $cn, $deferred, &$context, $cnRequest) { - if ($response === null) { - $rawResponse .= $data; - $pos = strpos($rawResponse, "\r\n\r\n"); - if ($pos) { - $data = substr($rawResponse, $pos + 4); - $rawResponse = substr($rawResponse, 0, $pos + 4); - $response = Message::parseResponse($rawResponse); - - if (!$cn->validateResponse($cnRequest, $response)) { - echo "Invalid response.\n"; - $connection->end(); - $deferred->reject(); - } else { - try { - $permessageDeflateOptions = PermessageDeflateOptions::fromRequestOrResponse($response)[0]; - $ms = echoStreamerFactory( - $connection, - $permessageDeflateOptions - ); - } catch (InvalidPermessageDeflateOptionsException $e) { - $connection->end(); - } - } - } - } - - // feed the message streamer - if ($ms) { - $ms->onData($data); - } - }); - - $connection->on('close', function () use ($deferred) { - $deferred->resolve(); - }); - - $connection->write(Message::toString($cnRequest)); - }); - - return $deferred->promise(); -} - -function createReport() { - global $connector; - global $testServer; - - $deferred = new Deferred(); - - $connector->connect($testServer . ':9002')->then(function (ConnectionInterface $connection) use ($deferred, $testServer) { - // $reportPath = "/updateReports?agent=" . AGENT . "&shutdownOnComplete=true"; - // we will stop it using docker now instead of just shutting down - $reportPath = "/updateReports?agent=" . AGENT; - $cn = new ClientNegotiator(); - $cnRequest = $cn->generateRequest(new Uri('ws://' . $testServer . ':9002' . $reportPath)); - - $rawResponse = ""; - $response = null; - - /** @var MessageBuffer $ms */ - $ms = null; - - $connection->on('data', function ($data) use ($connection, &$rawResponse, &$response, &$ms, $cn, $deferred, &$context, $cnRequest) { - if ($response === null) { - $rawResponse .= $data; - $pos = strpos($rawResponse, "\r\n\r\n"); - if ($pos) { - $data = substr($rawResponse, $pos + 4); - $rawResponse = substr($rawResponse, 0, $pos + 4); - $response = Message::parseResponse($rawResponse); - - if (!$cn->validateResponse($cnRequest, $response)) { - $connection->end(); - $deferred->reject(); - } else { - $ms = new MessageBuffer( - new CloseFrameChecker, - function (MessageInterface $msg) use ($deferred, $connection) { - $deferred->resolve($msg->getPayload()); - $connection->close(); - }, - null, - false, - null, - null, - null, - function () {} - ); - } - } - } - - // feed the message streamer - if ($ms) { - $ms->onData($data); - } - }); - - $connection->write(Message::toString($cnRequest)); - }); - - return $deferred->promise(); -} - - -$testPromises = []; - -getTestCases()->then(function ($count) use ($loop) { - $allDeferred = new Deferred(); - - $runNextCase = function () use (&$i, &$runNextCase, $count, $allDeferred) { - $i++; - if ($i > $count) { - $allDeferred->resolve(); - return; - } - echo "Running test $i/$count..."; - $startTime = microtime(true); - runTest($i) - ->then(function () use ($startTime) { - echo " completed " . round((microtime(true) - $startTime) * 1000) . " ms\n"; - }) - ->then($runNextCase); - }; - - $i = 0; - $runNextCase(); - - $allDeferred->promise()->then(function () { - createReport(); - }); -}); - -$loop->run(); diff --git a/digital_doctor/vendor/ratchet/rfc6455/tests/ab/docker_bootstrap.sh b/digital_doctor/vendor/ratchet/rfc6455/tests/ab/docker_bootstrap.sh deleted file mode 100644 index 44d4581..0000000 --- a/digital_doctor/vendor/ratchet/rfc6455/tests/ab/docker_bootstrap.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -set -x - -echo "Running $0" - -echo Adding "$1 host.ratchet.internal" to /etc/hosts file - -echo $1 host.ratchet.internal >> /etc/hosts - -echo /etc/hosts contains: -cat /etc/hosts -echo diff --git a/digital_doctor/vendor/ratchet/rfc6455/tests/ab/fuzzingclient.json b/digital_doctor/vendor/ratchet/rfc6455/tests/ab/fuzzingclient.json deleted file mode 100644 index d410be3..0000000 --- a/digital_doctor/vendor/ratchet/rfc6455/tests/ab/fuzzingclient.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "options": { - "failByDrop": false - } - , "outdir": "/reports/servers" - , "servers": [{ - "agent": "RatchetRFC/0.3" - , "url": "ws://host.ratchet.internal:9001" - , "options": {"version": 18} - }] - , "cases": [ - "*" - ] - , "exclude-cases": [] - , "exclude-agent-cases": {} -} diff --git a/digital_doctor/vendor/ratchet/rfc6455/tests/ab/fuzzingclient_skip_deflate.json b/digital_doctor/vendor/ratchet/rfc6455/tests/ab/fuzzingclient_skip_deflate.json deleted file mode 100644 index b1fddbe..0000000 --- a/digital_doctor/vendor/ratchet/rfc6455/tests/ab/fuzzingclient_skip_deflate.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "options": { - "failByDrop": false - } - , "outdir": "/reports/servers" - , "servers": [{ - "agent": "RatchetRFC/0.3" - , "url": "ws://host.ratchet.internal:9001" - , "options": {"version": 18} - }] - , "cases": ["*"] - , "exclude-cases": ["12.*", "13.*"] - , "exclude-agent-cases": {} -} diff --git a/digital_doctor/vendor/ratchet/rfc6455/tests/ab/fuzzingserver.json b/digital_doctor/vendor/ratchet/rfc6455/tests/ab/fuzzingserver.json deleted file mode 100644 index 9f10403..0000000 --- a/digital_doctor/vendor/ratchet/rfc6455/tests/ab/fuzzingserver.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "url": "ws://127.0.0.1:9002" - , "options": { - "failByDrop": false - } - , "outdir": "./reports/clients" - , "cases": [ - "*" - ] - , "exclude-cases": [] - , "exclude-agent-cases": {} -} diff --git a/digital_doctor/vendor/ratchet/rfc6455/tests/ab/fuzzingserver_skip_deflate.json b/digital_doctor/vendor/ratchet/rfc6455/tests/ab/fuzzingserver_skip_deflate.json deleted file mode 100644 index 9323191..0000000 --- a/digital_doctor/vendor/ratchet/rfc6455/tests/ab/fuzzingserver_skip_deflate.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "url": "ws://127.0.0.1:9002" - , "options": { - "failByDrop": false - } - , "outdir": "./reports/clients" - , "cases": ["*"] - , "exclude-cases": ["12.*", "13.*"] - , "exclude-agent-cases": {} -} diff --git a/digital_doctor/vendor/ratchet/rfc6455/tests/ab/run_ab_tests.sh b/digital_doctor/vendor/ratchet/rfc6455/tests/ab/run_ab_tests.sh deleted file mode 100644 index 3df4a7d..0000000 --- a/digital_doctor/vendor/ratchet/rfc6455/tests/ab/run_ab_tests.sh +++ /dev/null @@ -1,48 +0,0 @@ -set -x -cd tests/ab - -if [ "$ABTEST" = "client" ]; then - docker run --rm \ - -d \ - -v ${PWD}:/config \ - -v ${PWD}/reports:/reports \ - -p 9002:9002 \ - --name fuzzingserver \ - crossbario/autobahn-testsuite wstest -m fuzzingserver -s /config/fuzzingserver$SKIP_DEFLATE.json - sleep 5 - if [ "$TRAVIS" != "true" ]; then - echo "Running tests vs Autobahn test client" - ###docker run -it --rm --name abpytest crossbario/autobahn-testsuite wstest --mode testeeclient -w ws://host.docker.internal:9002 - fi - php -d memory_limit=256M clientRunner.php - - docker ps -a - - docker logs fuzzingserver - - docker stop fuzzingserver - - sleep 2 -fi - -if [ "$ABTEST" = "server" ]; then - php -d memory_limit=256M startServer.php & - sleep 3 - - if [ "$OSTYPE" = "linux-gnu" ]; then - IPADDR=`hostname -I | cut -f 1 -d ' '` - else - IPADDR=`ifconfig | grep "inet " | grep -Fv 127.0.0.1 | awk '{print $2}' | head -1 | tr -d 'adr:'` - fi - - docker run --rm \ - -i \ - -v ${PWD}:/config \ - -v ${PWD}/reports:/reports \ - --name fuzzingclient \ - crossbario/autobahn-testsuite /bin/sh -c "sh /config/docker_bootstrap.sh $IPADDR; wstest -m fuzzingclient -s /config/fuzzingclient$SKIP_DEFLATE.json" - sleep 1 - - # send the shutdown command to the PHP echo server - wget -O - -q http://127.0.0.1:9001/shutdown -fi diff --git a/digital_doctor/vendor/ratchet/rfc6455/tests/ab/startServer.php b/digital_doctor/vendor/ratchet/rfc6455/tests/ab/startServer.php deleted file mode 100644 index 7c169c6..0000000 --- a/digital_doctor/vendor/ratchet/rfc6455/tests/ab/startServer.php +++ /dev/null @@ -1,86 +0,0 @@ -on('connection', function (React\Socket\ConnectionInterface $connection) use ($negotiator, $closeFrameChecker, $uException, $socket) { - $headerComplete = false; - $buffer = ''; - $parser = null; - $connection->on('data', function ($data) use ($connection, &$parser, &$headerComplete, &$buffer, $negotiator, $closeFrameChecker, $uException, $socket) { - if ($headerComplete) { - $parser->onData($data); - return; - } - - $buffer .= $data; - $parts = explode("\r\n\r\n", $buffer); - if (count($parts) < 2) { - return; - } - $headerComplete = true; - $psrRequest = Message::parseRequest($parts[0] . "\r\n\r\n"); - $negotiatorResponse = $negotiator->handshake($psrRequest); - - $negotiatorResponse = $negotiatorResponse->withAddedHeader("Content-Length", "0"); - - if ($negotiatorResponse->getStatusCode() !== 101 && $psrRequest->getUri()->getPath() === '/shutdown') { - $connection->end(Message::toString(new Response(200, [], 'Shutting down echo server.' . PHP_EOL))); - $socket->close(); - return; - }; - - $connection->write(Message::toString($negotiatorResponse)); - - if ($negotiatorResponse->getStatusCode() !== 101) { - $connection->end(); - return; - } - - // there is no need to look through the client requests - // we support any valid permessage deflate - $deflateOptions = PermessageDeflateOptions::fromRequestOrResponse($psrRequest)[0]; - - $parser = new \Ratchet\RFC6455\Messaging\MessageBuffer($closeFrameChecker, - function (MessageInterface $message, MessageBuffer $messageBuffer) { - $messageBuffer->sendMessage($message->getPayload(), true, $message->isBinary()); - }, function (FrameInterface $frame) use ($connection, &$parser) { - switch ($frame->getOpCode()) { - case Frame::OP_CLOSE: - $connection->end($frame->getContents()); - break; - case Frame::OP_PING: - $connection->write($parser->newFrame($frame->getPayload(), true, Frame::OP_PONG)->getContents()); - break; - } - }, true, function () use ($uException) { - return $uException; - }, - null, - null, - [$connection, 'write'], - $deflateOptions); - - array_shift($parts); - $parser->onData(implode("\r\n\r\n", $parts)); - }); -}); - -$loop->run(); diff --git a/digital_doctor/vendor/ratchet/rfc6455/tests/bootstrap.php b/digital_doctor/vendor/ratchet/rfc6455/tests/bootstrap.php deleted file mode 100644 index 511b041..0000000 --- a/digital_doctor/vendor/ratchet/rfc6455/tests/bootstrap.php +++ /dev/null @@ -1,19 +0,0 @@ -addPsr4('Ratchet\\RFC6455\\Test\\', __DIR__); - break; - } -} diff --git a/digital_doctor/vendor/ratchet/rfc6455/tests/unit/Handshake/PermessageDeflateOptionsTest.php b/digital_doctor/vendor/ratchet/rfc6455/tests/unit/Handshake/PermessageDeflateOptionsTest.php deleted file mode 100644 index 11d3739..0000000 --- a/digital_doctor/vendor/ratchet/rfc6455/tests/unit/Handshake/PermessageDeflateOptionsTest.php +++ /dev/null @@ -1,30 +0,0 @@ -assertEquals($supported, PermessageDeflateOptions::permessageDeflateSupported($version)); - } -} \ No newline at end of file diff --git a/digital_doctor/vendor/ratchet/rfc6455/tests/unit/Handshake/RequestVerifierTest.php b/digital_doctor/vendor/ratchet/rfc6455/tests/unit/Handshake/RequestVerifierTest.php deleted file mode 100644 index 5ba26b6..0000000 --- a/digital_doctor/vendor/ratchet/rfc6455/tests/unit/Handshake/RequestVerifierTest.php +++ /dev/null @@ -1,180 +0,0 @@ -_v = new RequestVerifier(); - } - - public static function methodProvider() { - return array( - array(true, 'GET'), - array(true, 'get'), - array(true, 'Get'), - array(false, 'POST'), - array(false, 'DELETE'), - array(false, 'PUT'), - array(false, 'PATCH') - ); - } - /** - * @dataProvider methodProvider - */ - public function testMethodMustBeGet($result, $in) { - $this->assertEquals($result, $this->_v->verifyMethod($in)); - } - - public static function httpVersionProvider() { - return array( - array(true, 1.1), - array(true, '1.1'), - array(true, 1.2), - array(true, '1.2'), - array(true, 2), - array(true, '2'), - array(true, '2.0'), - array(false, '1.0'), - array(false, 1), - array(false, '0.9'), - array(false, ''), - array(false, 'hello') - ); - } - - /** - * @dataProvider httpVersionProvider - */ - public function testHttpVersionIsAtLeast1Point1($expected, $in) { - $this->assertEquals($expected, $this->_v->verifyHTTPVersion($in)); - } - - public static function uRIProvider() { - return array( - array(true, '/chat'), - array(true, '/hello/world?key=val'), - array(false, '/chat#bad'), - array(false, 'nope'), - array(false, '/ ಠ_ಠ '), - array(false, '/✖') - ); - } - - /** - * @dataProvider URIProvider - */ - public function testRequestUri($expected, $in) { - $this->assertEquals($expected, $this->_v->verifyRequestURI($in)); - } - - public static function hostProvider() { - return array( - array(true, ['server.example.com']), - array(false, []) - ); - } - - /** - * @dataProvider HostProvider - */ - public function testVerifyHostIsSet($expected, $in) { - $this->assertEquals($expected, $this->_v->verifyHost($in)); - } - - public static function upgradeProvider() { - return array( - array(true, ['websocket']), - array(true, ['Websocket']), - array(true, ['webSocket']), - array(false, []), - array(false, ['']) - ); - } - - /** - * @dataProvider upgradeProvider - */ - public function testVerifyUpgradeIsWebSocket($expected, $val) { - $this->assertEquals($expected, $this->_v->verifyUpgradeRequest($val)); - } - - public static function connectionProvider() { - return array( - array(true, ['Upgrade']), - array(true, ['upgrade']), - array(true, ['keep-alive', 'Upgrade']), - array(true, ['Upgrade', 'keep-alive']), - array(true, ['keep-alive', 'Upgrade', 'something']), - // as seen in Firefox 47.0.1 - see https://github.com/ratchetphp/RFC6455/issues/14 - array(true, ['keep-alive, Upgrade']), - array(true, ['Upgrade, keep-alive']), - array(true, ['keep-alive, Upgrade, something']), - array(true, ['keep-alive, Upgrade', 'something']), - array(false, ['']), - array(false, []) - ); - } - - /** - * @dataProvider connectionProvider - */ - public function testConnectionHeaderVerification($expected, $val) { - $this->assertEquals($expected, $this->_v->verifyConnection($val)); - } - - public static function keyProvider() { - return array( - array(true, ['hkfa1L7uwN6DCo4IS3iWAw==']), - array(true, ['765vVoQpKSGJwPzJIMM2GA==']), - array(true, ['AQIDBAUGBwgJCgsMDQ4PEC==']), - array(true, ['axa2B/Yz2CdpfQAY2Q5P7w==']), - array(false, [0]), - array(false, ['Hello World']), - array(false, ['1234567890123456']), - array(false, ['123456789012345678901234']), - array(true, [base64_encode('UTF8allthngs+✓')]), - array(true, ['dGhlIHNhbXBsZSBub25jZQ==']), - array(false, []), - array(false, ['dGhlIHNhbXBsZSBub25jZQ==', 'Some other value']), - array(false, ['Some other value', 'dGhlIHNhbXBsZSBub25jZQ==']) - ); - } - - /** - * @dataProvider keyProvider - */ - public function testKeyIsBase64Encoded16BitNonce($expected, $val) { - $this->assertEquals($expected, $this->_v->verifyKey($val)); - } - - public static function versionProvider() { - return array( - array(true, [13]), - array(true, ['13']), - array(false, [12]), - array(false, [14]), - array(false, ['14']), - array(false, ['hi']), - array(false, ['']), - array(false, []) - ); - } - - /** - * @dataProvider versionProvider - */ - public function testVersionEquals13($expected, $in) { - $this->assertEquals($expected, $this->_v->verifyVersion($in)); - } -} \ No newline at end of file diff --git a/digital_doctor/vendor/ratchet/rfc6455/tests/unit/Handshake/ResponseVerifierTest.php b/digital_doctor/vendor/ratchet/rfc6455/tests/unit/Handshake/ResponseVerifierTest.php deleted file mode 100644 index 9a1459b..0000000 --- a/digital_doctor/vendor/ratchet/rfc6455/tests/unit/Handshake/ResponseVerifierTest.php +++ /dev/null @@ -1,39 +0,0 @@ -_v = new ResponseVerifier; - } - - public static function subProtocolsProvider() { - return [ - [true, ['a'], ['a']] - , [true, ['c', 'd', 'a'], ['a']] - , [true, ['c, a', 'd'], ['a']] - , [true, [], []] - , [true, ['a', 'b'], []] - , [false, ['c', 'd', 'a'], ['b', 'a']] - , [false, ['a', 'b', 'c'], ['d']] - ]; - } - - /** - * @dataProvider subProtocolsProvider - */ - public function testVerifySubProtocol($expected, $request, $response) { - $this->assertEquals($expected, $this->_v->verifySubProtocol($request, $response)); - } -} diff --git a/digital_doctor/vendor/ratchet/rfc6455/tests/unit/Handshake/ServerNegotiatorTest.php b/digital_doctor/vendor/ratchet/rfc6455/tests/unit/Handshake/ServerNegotiatorTest.php deleted file mode 100644 index 720bdf9..0000000 --- a/digital_doctor/vendor/ratchet/rfc6455/tests/unit/Handshake/ServerNegotiatorTest.php +++ /dev/null @@ -1,219 +0,0 @@ -handshake($request); - - $this->assertEquals('1.1', $response->getProtocolVersion()); - $this->assertEquals(426, $response->getStatusCode()); - $this->assertEquals('Upgrade header MUST be provided', $response->getReasonPhrase()); - $this->assertEquals('Upgrade', $response->getHeaderLine('Connection')); - $this->assertEquals('websocket', $response->getHeaderLine('Upgrade')); - $this->assertEquals('13', $response->getHeaderLine('Sec-WebSocket-Version')); - } - - public function testNoConnectionUpgradeRequested() { - $negotiator = new ServerNegotiator(new RequestVerifier()); - - $requestText = 'GET / HTTP/1.1 -Host: 127.0.0.1:6789 -Connection: keep-alive -Pragma: no-cache -Cache-Control: no-cache -Upgrade: websocket -Upgrade-Insecure-Requests: 1 -User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36 -Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 -Accept-Encoding: gzip, deflate, sdch, br -Accept-Language: en-US,en;q=0.8 - -'; - - $request = Message::parseRequest($requestText); - - $response = $negotiator->handshake($request); - - $this->assertEquals('1.1', $response->getProtocolVersion()); - $this->assertEquals(400, $response->getStatusCode()); - $this->assertEquals('Connection Upgrade MUST be requested', $response->getReasonPhrase()); - } - - public function testInvalidSecWebsocketKey() { - $negotiator = new ServerNegotiator(new RequestVerifier()); - - $requestText = 'GET / HTTP/1.1 -Host: 127.0.0.1:6789 -Connection: Upgrade -Pragma: no-cache -Cache-Control: no-cache -Upgrade: websocket -Sec-WebSocket-Key: 12345 -Upgrade-Insecure-Requests: 1 -User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36 -Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 -Accept-Encoding: gzip, deflate, sdch, br -Accept-Language: en-US,en;q=0.8 - -'; - - $request = Message::parseRequest($requestText); - - $response = $negotiator->handshake($request); - - $this->assertEquals('1.1', $response->getProtocolVersion()); - $this->assertEquals(400, $response->getStatusCode()); - $this->assertEquals('Invalid Sec-WebSocket-Key', $response->getReasonPhrase()); - } - - public function testInvalidSecWebsocketVersion() { - $negotiator = new ServerNegotiator(new RequestVerifier()); - - $requestText = 'GET / HTTP/1.1 -Host: 127.0.0.1:6789 -Connection: Upgrade -Pragma: no-cache -Cache-Control: no-cache -Upgrade: websocket -Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== -Upgrade-Insecure-Requests: 1 -User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36 -Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 -Accept-Encoding: gzip, deflate, sdch, br -Accept-Language: en-US,en;q=0.8 - -'; - - $request = Message::parseRequest($requestText); - - $response = $negotiator->handshake($request); - - $this->assertEquals('1.1', $response->getProtocolVersion()); - $this->assertEquals(426, $response->getStatusCode()); - $this->assertEquals('Upgrade Required', $response->getReasonPhrase()); - $this->assertEquals('Upgrade', $response->getHeaderLine('Connection')); - $this->assertEquals('websocket', $response->getHeaderLine('Upgrade')); - $this->assertEquals('13', $response->getHeaderLine('Sec-WebSocket-Version')); - } - - public function testBadSubprotocolResponse() { - $negotiator = new ServerNegotiator(new RequestVerifier()); - $negotiator->setStrictSubProtocolCheck(true); - $negotiator->setSupportedSubProtocols([]); - - $requestText = 'GET / HTTP/1.1 -Host: 127.0.0.1:6789 -Connection: Upgrade -Pragma: no-cache -Cache-Control: no-cache -Upgrade: websocket -Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== -Sec-WebSocket-Version: 13 -Sec-WebSocket-Protocol: someprotocol -Upgrade-Insecure-Requests: 1 -User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36 -Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 -Accept-Encoding: gzip, deflate, sdch, br -Accept-Language: en-US,en;q=0.8 - -'; - - $request = Message::parseRequest($requestText); - - $response = $negotiator->handshake($request); - - $this->assertEquals('1.1', $response->getProtocolVersion()); - $this->assertEquals(426, $response->getStatusCode()); - $this->assertEquals('No Sec-WebSocket-Protocols requested supported', $response->getReasonPhrase()); - $this->assertEquals('Upgrade', $response->getHeaderLine('Connection')); - $this->assertEquals('websocket', $response->getHeaderLine('Upgrade')); - $this->assertEquals('13', $response->getHeaderLine('Sec-WebSocket-Version')); - } - - public function testNonStrictSubprotocolDoesNotIncludeHeaderWhenNoneAgreedOn() { - $negotiator = new ServerNegotiator(new RequestVerifier()); - $negotiator->setStrictSubProtocolCheck(false); - $negotiator->setSupportedSubProtocols(['someproto']); - - $requestText = 'GET / HTTP/1.1 -Host: 127.0.0.1:6789 -Connection: Upgrade -Pragma: no-cache -Cache-Control: no-cache -Upgrade: websocket -Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== -Sec-WebSocket-Version: 13 -Sec-WebSocket-Protocol: someotherproto -Upgrade-Insecure-Requests: 1 -User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36 -Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 -Accept-Encoding: gzip, deflate, sdch, br -Accept-Language: en-US,en;q=0.8 - -'; - - $request = Message::parseRequest($requestText); - - $response = $negotiator->handshake($request); - - $this->assertEquals('1.1', $response->getProtocolVersion()); - $this->assertEquals(101, $response->getStatusCode()); - $this->assertEquals('Upgrade', $response->getHeaderLine('Connection')); - $this->assertEquals('websocket', $response->getHeaderLine('Upgrade')); - $this->assertFalse($response->hasHeader('Sec-WebSocket-Protocol')); - } - - public function testSuggestsAppropriateSubprotocol() - { - $negotiator = new ServerNegotiator(new RequestVerifier()); - $negotiator->setStrictSubProtocolCheck(true); - $negotiator->setSupportedSubProtocols(['someproto']); - - $requestText = 'GET / HTTP/1.1 -Host: localhost:8080 -Connection: Upgrade -Upgrade: websocket -Sec-WebSocket-Version: 13 -User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 -Accept-Encoding: gzip, deflate, br -Accept-Language: en-US,en;q=0.9 -Sec-WebSocket-Key: HGt8eQax7nAOlXUw0/asPQ== -Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits - -'; - - $request = Message::parseRequest($requestText); - - $response = $negotiator->handshake($request); - - $this->assertEquals('1.1', $response->getProtocolVersion()); - $this->assertEquals(426, $response->getStatusCode()); - $this->assertEquals('Upgrade', $response->getHeaderLine('Connection')); - $this->assertEquals('websocket', $response->getHeaderLine('Upgrade')); - $this->assertEquals('someproto', $response->getHeaderLine('Sec-WebSocket-Protocol')); - } -} diff --git a/digital_doctor/vendor/ratchet/rfc6455/tests/unit/Messaging/FrameTest.php b/digital_doctor/vendor/ratchet/rfc6455/tests/unit/Messaging/FrameTest.php deleted file mode 100644 index 54a4599..0000000 --- a/digital_doctor/vendor/ratchet/rfc6455/tests/unit/Messaging/FrameTest.php +++ /dev/null @@ -1,504 +0,0 @@ -_frame = new Frame; - } - - /** - * Encode the fake binary string to send over the wire - * @param string of 1's and 0's - * @return string - */ - public static function encode($in) { - if (strlen($in) > 8) { - $out = ''; - while (strlen($in) >= 8) { - $out .= static::encode(substr($in, 0, 8)); - $in = substr($in, 8); - } - return $out; - } - return chr(bindec($in)); - } - - /** - * This is a data provider - * param string The UTF8 message - * param string The WebSocket framed message, then base64_encoded - */ - public static function UnframeMessageProvider() { - return array( - array('Hello World!', 'gYydAIfa1WXrtvIg0LXvbOP7'), - array('!@#$%^&*()-=_+[]{}\|/.,<>`~', 'gZv+h96r38f9j9vZ+IHWrvOWoayF9oX6gtfRqfKXwOeg'), - array('ಠ_ಠ', 'gYfnSpu5B/g75gf4Ow=='), - array( - "The quick brown fox jumps over the lazy dog. All work and no play makes Chris a dull boy. I'm trying to get past 128 characters for a unit test here...", - 'gf4Amahb14P8M7Kj2S6+4MN7tfHHLLmjzjSvo8IuuvPbe7j1zSn398A+9+/JIa6jzDSwrYh7lu/Ee6Ds2jD34sY/9+3He6fvySL37skwsvCIGL/xwSj34og/ou/Ee7Xs0XX3o+F8uqPcKa7qxjz398d7sObce6fi2y/3sppj9+DAOqXiyy+y8dt7sezae7aj3TW+94gvsvDce7/m2j75rYY=' - ) - ); - } - - public static function underflowProvider() { - return array( - array('isFinal', ''), - array('getRsv1', ''), - array('getRsv2', ''), - array('getRsv3', ''), - array('getOpcode', ''), - array('isMasked', '10000001'), - array('getPayloadLength', '10000001'), - array('getPayloadLength', '1000000111111110'), - array('getMaskingKey', '1000000110000111'), - array('getPayload', '100000011000000100011100101010101001100111110100') - ); - } - - /** - * @dataProvider underflowProvider - * - * @covers Ratchet\RFC6455\Messaging\Frame::isFinal - * @covers Ratchet\RFC6455\Messaging\Frame::getRsv1 - * @covers Ratchet\RFC6455\Messaging\Frame::getRsv2 - * @covers Ratchet\RFC6455\Messaging\Frame::getRsv3 - * @covers Ratchet\RFC6455\Messaging\Frame::getOpcode - * @covers Ratchet\RFC6455\Messaging\Frame::isMasked - * @covers Ratchet\RFC6455\Messaging\Frame::getPayloadLength - * @covers Ratchet\RFC6455\Messaging\Frame::getMaskingKey - * @covers Ratchet\RFC6455\Messaging\Frame::getPayload - */ - public function testUnderflowExceptionFromAllTheMethodsMimickingBuffering($method, $bin) { - $this->setExpectedException('\UnderflowException'); - if (!empty($bin)) { - $this->_frame->addBuffer(static::encode($bin)); - } - call_user_func(array($this->_frame, $method)); - } - - /** - * A data provider for testing the first byte of a WebSocket frame - * param bool Given, is the byte indicate this is the final frame - * param int Given, what is the expected opcode - * param string of 0|1 Each character represents a bit in the byte - */ - public static function firstByteProvider() { - return array( - array(false, false, false, true, 8, '00011000'), - array(true, false, true, false, 10, '10101010'), - array(false, false, false, false, 15, '00001111'), - array(true, false, false, false, 1, '10000001'), - array(true, true, true, true, 15, '11111111'), - array(true, true, false, false, 7, '11000111') - ); - } - - /** - * @dataProvider firstByteProvider - * covers Ratchet\RFC6455\Messaging\Frame::isFinal - */ - public function testFinCodeFromBits($fin, $rsv1, $rsv2, $rsv3, $opcode, $bin) { - $this->_frame->addBuffer(static::encode($bin)); - $this->assertEquals($fin, $this->_frame->isFinal()); - } - - /** - * @dataProvider firstByteProvider - * covers Ratchet\RFC6455\Messaging\Frame::getRsv1 - * covers Ratchet\RFC6455\Messaging\Frame::getRsv2 - * covers Ratchet\RFC6455\Messaging\Frame::getRsv3 - */ - public function testGetRsvFromBits($fin, $rsv1, $rsv2, $rsv3, $opcode, $bin) { - $this->_frame->addBuffer(static::encode($bin)); - $this->assertEquals($rsv1, $this->_frame->getRsv1()); - $this->assertEquals($rsv2, $this->_frame->getRsv2()); - $this->assertEquals($rsv3, $this->_frame->getRsv3()); - } - - /** - * @dataProvider firstByteProvider - * covers Ratchet\RFC6455\Messaging\Frame::getOpcode - */ - public function testOpcodeFromBits($fin, $rsv1, $rsv2, $rsv3, $opcode, $bin) { - $this->_frame->addBuffer(static::encode($bin)); - $this->assertEquals($opcode, $this->_frame->getOpcode()); - } - - /** - * @dataProvider UnframeMessageProvider - * covers Ratchet\RFC6455\Messaging\Frame::isFinal - */ - public function testFinCodeFromFullMessage($msg, $encoded) { - $this->_frame->addBuffer(base64_decode($encoded)); - $this->assertTrue($this->_frame->isFinal()); - } - - /** - * @dataProvider UnframeMessageProvider - * covers Ratchet\RFC6455\Messaging\Frame::getOpcode - */ - public function testOpcodeFromFullMessage($msg, $encoded) { - $this->_frame->addBuffer(base64_decode($encoded)); - $this->assertEquals(1, $this->_frame->getOpcode()); - } - - public static function payloadLengthDescriptionProvider() { - return array( - array(7, '01110101'), - array(7, '01111101'), - array(23, '01111110'), - array(71, '01111111'), - array(7, '00000000'), // Should this throw an exception? Can a payload be empty? - array(7, '00000001') - ); - } - - /** - * @dataProvider payloadLengthDescriptionProvider - * covers Ratchet\RFC6455\Messaging\Frame::addBuffer - * covers Ratchet\RFC6455\Messaging\Frame::getFirstPayloadVal - */ - public function testFirstPayloadDesignationValue($bits, $bin) { - $this->_frame->addBuffer(static::encode($this->_firstByteFinText)); - $this->_frame->addBuffer(static::encode($bin)); - $ref = new \ReflectionClass($this->_frame); - $cb = $ref->getMethod('getFirstPayloadVal'); - $cb->setAccessible(true); - $this->assertEquals(bindec($bin), $cb->invoke($this->_frame)); - } - - /** - * covers Ratchet\RFC6455\Messaging\Frame::getFirstPayloadVal - */ - public function testFirstPayloadValUnderflow() { - $ref = new \ReflectionClass($this->_frame); - $cb = $ref->getMethod('getFirstPayloadVal'); - $cb->setAccessible(true); - $this->setExpectedException('UnderflowException'); - $cb->invoke($this->_frame); - } - - /** - * @dataProvider payloadLengthDescriptionProvider - * covers Ratchet\RFC6455\Messaging\Frame::getNumPayloadBits - */ - public function testDetermineHowManyBitsAreUsedToDescribePayload($expected_bits, $bin) { - $this->_frame->addBuffer(static::encode($this->_firstByteFinText)); - $this->_frame->addBuffer(static::encode($bin)); - $ref = new \ReflectionClass($this->_frame); - $cb = $ref->getMethod('getNumPayloadBits'); - $cb->setAccessible(true); - $this->assertEquals($expected_bits, $cb->invoke($this->_frame)); - } - - /** - * covers Ratchet\RFC6455\Messaging\Frame::getNumPayloadBits - */ - public function testgetNumPayloadBitsUnderflow() { - $ref = new \ReflectionClass($this->_frame); - $cb = $ref->getMethod('getNumPayloadBits'); - $cb->setAccessible(true); - $this->setExpectedException('UnderflowException'); - $cb->invoke($this->_frame); - } - - public function secondByteProvider() { - return array( - array(true, 1, '10000001'), - array(false, 1, '00000001'), - array(true, 125, $this->_secondByteMaskedSPL) - ); - } - /** - * @dataProvider secondByteProvider - * covers Ratchet\RFC6455\Messaging\Frame::isMasked - */ - public function testIsMaskedReturnsExpectedValue($masked, $payload_length, $bin) { - $this->_frame->addBuffer(static::encode($this->_firstByteFinText)); - $this->_frame->addBuffer(static::encode($bin)); - $this->assertEquals($masked, $this->_frame->isMasked()); - } - - /** - * @dataProvider UnframeMessageProvider - * covers Ratchet\RFC6455\Messaging\Frame::isMasked - */ - public function testIsMaskedFromFullMessage($msg, $encoded) { - $this->_frame->addBuffer(base64_decode($encoded)); - $this->assertTrue($this->_frame->isMasked()); - } - - /** - * @dataProvider secondByteProvider - * covers Ratchet\RFC6455\Messaging\Frame::getPayloadLength - */ - public function testGetPayloadLengthWhenOnlyFirstFrameIsUsed($masked, $payload_length, $bin) { - $this->_frame->addBuffer(static::encode($this->_firstByteFinText)); - $this->_frame->addBuffer(static::encode($bin)); - $this->assertEquals($payload_length, $this->_frame->getPayloadLength()); - } - - /** - * @dataProvider UnframeMessageProvider - * covers Ratchet\RFC6455\Messaging\Frame::getPayloadLength - * @todo Not yet testing when second additional payload length descriptor - */ - public function testGetPayloadLengthFromFullMessage($msg, $encoded) { - $this->_frame->addBuffer(base64_decode($encoded)); - $this->assertEquals(strlen($msg), $this->_frame->getPayloadLength()); - } - - public function maskingKeyProvider() { - $frame = new Frame; - return array( - array($frame->generateMaskingKey()), - array($frame->generateMaskingKey()), - array($frame->generateMaskingKey()) - ); - } - - /** - * @dataProvider maskingKeyProvider - * covers Ratchet\RFC6455\Messaging\Frame::getMaskingKey - * @todo I I wrote the dataProvider incorrectly, skipping for now - */ - public function testGetMaskingKey($mask) { - $this->_frame->addBuffer(static::encode($this->_firstByteFinText)); - $this->_frame->addBuffer(static::encode($this->_secondByteMaskedSPL)); - $this->_frame->addBuffer($mask); - $this->assertEquals($mask, $this->_frame->getMaskingKey()); - } - - /** - * covers Ratchet\RFC6455\Messaging\Frame::getMaskingKey - */ - public function testGetMaskingKeyOnUnmaskedPayload() { - $frame = new Frame('Hello World!'); - $this->assertEquals('', $frame->getMaskingKey()); - } - - /** - * @dataProvider UnframeMessageProvider - * covers Ratchet\RFC6455\Messaging\Frame::getPayload - * @todo Move this test to bottom as it requires all methods of the class - */ - public function testUnframeFullMessage($unframed, $base_framed) { - $this->_frame->addBuffer(base64_decode($base_framed)); - $this->assertEquals($unframed, $this->_frame->getPayload()); - } - - public static function messageFragmentProvider() { - return array( - array(false, '', '', '', '', '') - ); - } - - /** - * @dataProvider UnframeMessageProvider - * covers Ratchet\RFC6455\Messaging\Frame::getPayload - */ - public function testCheckPiecingTogetherMessage($msg, $encoded) { - $framed = base64_decode($encoded); - for ($i = 0, $len = strlen($framed);$i < $len; $i++) { - $this->_frame->addBuffer(substr($framed, $i, 1)); - } - $this->assertEquals($msg, $this->_frame->getPayload()); - } - - /** - * covers Ratchet\RFC6455\Messaging\Frame::__construct - * covers Ratchet\RFC6455\Messaging\Frame::getPayloadLength - * covers Ratchet\RFC6455\Messaging\Frame::getPayload - */ - public function testLongCreate() { - $len = 65525; - $pl = $this->generateRandomString($len); - $frame = new Frame($pl, true, Frame::OP_PING); - $this->assertTrue($frame->isFinal()); - $this->assertEquals(Frame::OP_PING, $frame->getOpcode()); - $this->assertFalse($frame->isMasked()); - $this->assertEquals($len, $frame->getPayloadLength()); - $this->assertEquals($pl, $frame->getPayload()); - } - - /** - * covers Ratchet\RFC6455\Messaging\Frame::__construct - * covers Ratchet\RFC6455\Messaging\Frame::getPayloadLength - */ - public function testReallyLongCreate() { - $len = 65575; - $frame = new Frame($this->generateRandomString($len)); - $this->assertEquals($len, $frame->getPayloadLength()); - } - /** - * covers Ratchet\RFC6455\Messaging\Frame::__construct - * covers Ratchet\RFC6455\Messaging\Frame::extractOverflow - */ - public function testExtractOverflow() { - $string1 = $this->generateRandomString(); - $frame1 = new Frame($string1); - $string2 = $this->generateRandomString(); - $frame2 = new Frame($string2); - $cat = new Frame; - $cat->addBuffer($frame1->getContents() . $frame2->getContents()); - $this->assertEquals($frame1->getContents(), $cat->getContents()); - $this->assertEquals($string1, $cat->getPayload()); - $uncat = new Frame; - $uncat->addBuffer($cat->extractOverflow()); - $this->assertEquals($string1, $cat->getPayload()); - $this->assertEquals($string2, $uncat->getPayload()); - } - - /** - * covers Ratchet\RFC6455\Messaging\Frame::extractOverflow - */ - public function testEmptyExtractOverflow() { - $string = $this->generateRandomString(); - $frame = new Frame($string); - $this->assertEquals($string, $frame->getPayload()); - $this->assertEquals('', $frame->extractOverflow()); - $this->assertEquals($string, $frame->getPayload()); - } - - /** - * covers Ratchet\RFC6455\Messaging\Frame::getContents - */ - public function testGetContents() { - $msg = 'The quick brown fox jumps over the lazy dog.'; - $frame1 = new Frame($msg); - $frame2 = new Frame($msg); - $frame2->maskPayload(); - $this->assertNotEquals($frame1->getContents(), $frame2->getContents()); - $this->assertEquals(strlen($frame1->getContents()) + 4, strlen($frame2->getContents())); - } - - /** - * covers Ratchet\RFC6455\Messaging\Frame::maskPayload - */ - public function testMasking() { - $msg = 'The quick brown fox jumps over the lazy dog.'; - $frame = new Frame($msg); - $frame->maskPayload(); - $this->assertTrue($frame->isMasked()); - $this->assertEquals($msg, $frame->getPayload()); - } - - /** - * covers Ratchet\RFC6455\Messaging\Frame::unMaskPayload - */ - public function testUnMaskPayload() { - $string = $this->generateRandomString(); - $frame = new Frame($string); - $frame->maskPayload()->unMaskPayload(); - $this->assertFalse($frame->isMasked()); - $this->assertEquals($string, $frame->getPayload()); - } - - /** - * covers Ratchet\RFC6455\Messaging\Frame::generateMaskingKey - */ - public function testGenerateMaskingKey() { - $dupe = false; - $done = array(); - for ($i = 0; $i < 10; $i++) { - $new = $this->_frame->generateMaskingKey(); - if (in_array($new, $done)) { - $dupe = true; - } - $done[] = $new; - } - $this->assertEquals(4, strlen($new)); - $this->assertFalse($dupe); - } - - /** - * covers Ratchet\RFC6455\Messaging\Frame::maskPayload - */ - public function testGivenMaskIsValid() { - $this->setExpectedException('InvalidArgumentException'); - $this->_frame->maskPayload('hello world'); - } - - /** - * covers Ratchet\RFC6455\Messaging\Frame::maskPayload - */ - public function testGivenMaskIsValidAscii() { - if (!extension_loaded('mbstring')) { - $this->markTestSkipped("mbstring required for this test"); - return; - } - $this->setExpectedException('OutOfBoundsException'); - $this->_frame->maskPayload('x✖'); - } - - protected function generateRandomString($length = 10, $addSpaces = true, $addNumbers = true) { - $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"$%&/()=[]{}'; // ยง - $useChars = array(); - for($i = 0; $i < $length; $i++) { - $useChars[] = $characters[mt_rand(0, strlen($characters) - 1)]; - } - if($addSpaces === true) { - array_push($useChars, ' ', ' ', ' ', ' ', ' ', ' '); - } - if($addNumbers === true) { - array_push($useChars, rand(0, 9), rand(0, 9), rand(0, 9)); - } - shuffle($useChars); - $randomString = trim(implode('', $useChars)); - $randomString = substr($randomString, 0, $length); - return $randomString; - } - - /** - * There was a frame boundary issue when the first 3 bytes of a frame with a payload greater than - * 126 was added to the frame buffer and then Frame::getPayloadLength was called. It would cause the frame - * to set the payload length to 126 and then not recalculate it once the full length information was available. - * - * This is fixed by setting the defPayLen back to -1 before the underflow exception is thrown. - * - * covers Ratchet\RFC6455\Messaging\Frame::getPayloadLength - * covers Ratchet\RFC6455\Messaging\Frame::extractOverflow - */ - public function testFrameDeliveredOneByteAtATime() { - $startHeader = "\x01\x7e\x01\x00"; // header for a text frame of 256 - non-final - $framePayload = str_repeat("*", 256); - $rawOverflow = "xyz"; - $rawFrame = $startHeader . $framePayload . $rawOverflow; - $frame = new Frame(); - $payloadLen = 256; - for ($i = 0; $i < strlen($rawFrame); $i++) { - $frame->addBuffer($rawFrame[$i]); - try { - // payloadLen will - $payloadLen = $frame->getPayloadLength(); - } catch (\UnderflowException $e) { - if ($i > 2) { // we should get an underflow on 0,1,2 - $this->fail("Underflow exception when the frame length should be available"); - } - } - if ($payloadLen !== 256) { - $this->fail("Payload length of " . $payloadLen . " should have been 256."); - } - } - // make sure the overflow is good - $this->assertEquals($rawOverflow, $frame->extractOverflow()); - } -} diff --git a/digital_doctor/vendor/ratchet/rfc6455/tests/unit/Messaging/MessageBufferTest.php b/digital_doctor/vendor/ratchet/rfc6455/tests/unit/Messaging/MessageBufferTest.php deleted file mode 100644 index 89dcca0..0000000 --- a/digital_doctor/vendor/ratchet/rfc6455/tests/unit/Messaging/MessageBufferTest.php +++ /dev/null @@ -1,376 +0,0 @@ -getContents(); - - $data = str_repeat($frameRaw, 1000); - - $messageCount = 0; - - $messageBuffer = new MessageBuffer( - new CloseFrameChecker(), - function (Message $message) use (&$messageCount) { - $messageCount++; - $this->assertEquals('a', $message->getPayload()); - }, - null, - false - ); - - $messageBuffer->onData($data); - - $this->assertEquals(1000, $messageCount); - } - - public function testProcessingMessagesAsynchronouslyWhileBlockingInMessageHandler() { - $loop = Factory::create(); - - $frameA = new Frame('a', true, Frame::OP_TEXT); - $frameB = new Frame('b', true, Frame::OP_TEXT); - - $bReceived = false; - - $messageBuffer = new MessageBuffer( - new CloseFrameChecker(), - function (Message $message) use (&$messageCount, &$bReceived, $loop) { - $payload = $message->getPayload(); - $bReceived = $payload === 'b'; - - if (!$bReceived) { - $loop->run(); - } - }, - null, - false - ); - - $loop->addPeriodicTimer(0.1, function () use ($messageBuffer, $frameB, $loop) { - $loop->stop(); - $messageBuffer->onData($frameB->getContents()); - }); - - $messageBuffer->onData($frameA->getContents()); - - $this->assertTrue($bReceived); - } - - public function testInvalidFrameLength() { - $frame = new Frame(str_repeat('a', 200), true, Frame::OP_TEXT); - - $frameRaw = $frame->getContents(); - - $frameRaw[1] = "\x7f"; // 127 in the first spot - - $frameRaw[2] = "\xff"; // this will unpack to -1 - $frameRaw[3] = "\xff"; - $frameRaw[4] = "\xff"; - $frameRaw[5] = "\xff"; - $frameRaw[6] = "\xff"; - $frameRaw[7] = "\xff"; - $frameRaw[8] = "\xff"; - $frameRaw[9] = "\xff"; - - /** @var Frame $controlFrame */ - $controlFrame = null; - $messageCount = 0; - - $messageBuffer = new MessageBuffer( - new CloseFrameChecker(), - function (Message $message) use (&$messageCount) { - $messageCount++; - }, - function (Frame $frame) use (&$controlFrame) { - $this->assertNull($controlFrame); - $controlFrame = $frame; - }, - false, - null, - 0, - 10 - ); - - $messageBuffer->onData($frameRaw); - - $this->assertEquals(0, $messageCount); - $this->assertTrue($controlFrame instanceof Frame); - $this->assertEquals(Frame::OP_CLOSE, $controlFrame->getOpcode()); - $this->assertEquals([Frame::CLOSE_PROTOCOL], array_merge(unpack('n*', substr($controlFrame->getPayload(), 0, 2)))); - - } - - public function testFrameLengthTooBig() { - $frame = new Frame(str_repeat('a', 200), true, Frame::OP_TEXT); - - $frameRaw = $frame->getContents(); - - $frameRaw[1] = "\x7f"; // 127 in the first spot - - $frameRaw[2] = "\x7f"; // this will unpack to -1 - $frameRaw[3] = "\xff"; - $frameRaw[4] = "\xff"; - $frameRaw[5] = "\xff"; - $frameRaw[6] = "\xff"; - $frameRaw[7] = "\xff"; - $frameRaw[8] = "\xff"; - $frameRaw[9] = "\xff"; - - /** @var Frame $controlFrame */ - $controlFrame = null; - $messageCount = 0; - - $messageBuffer = new MessageBuffer( - new CloseFrameChecker(), - function (Message $message) use (&$messageCount) { - $messageCount++; - }, - function (Frame $frame) use (&$controlFrame) { - $this->assertNull($controlFrame); - $controlFrame = $frame; - }, - false, - null, - 0, - 10 - ); - - $messageBuffer->onData($frameRaw); - - $this->assertEquals(0, $messageCount); - $this->assertTrue($controlFrame instanceof Frame); - $this->assertEquals(Frame::OP_CLOSE, $controlFrame->getOpcode()); - $this->assertEquals([Frame::CLOSE_TOO_BIG], array_merge(unpack('n*', substr($controlFrame->getPayload(), 0, 2)))); - } - - public function testFrameLengthBiggerThanMaxMessagePayload() { - $frame = new Frame(str_repeat('a', 200), true, Frame::OP_TEXT); - - $frameRaw = $frame->getContents(); - - /** @var Frame $controlFrame */ - $controlFrame = null; - $messageCount = 0; - - $messageBuffer = new MessageBuffer( - new CloseFrameChecker(), - function (Message $message) use (&$messageCount) { - $messageCount++; - }, - function (Frame $frame) use (&$controlFrame) { - $this->assertNull($controlFrame); - $controlFrame = $frame; - }, - false, - null, - 100, - 0 - ); - - $messageBuffer->onData($frameRaw); - - $this->assertEquals(0, $messageCount); - $this->assertTrue($controlFrame instanceof Frame); - $this->assertEquals(Frame::OP_CLOSE, $controlFrame->getOpcode()); - $this->assertEquals([Frame::CLOSE_TOO_BIG], array_merge(unpack('n*', substr($controlFrame->getPayload(), 0, 2)))); - } - - public function testSecondFrameLengthPushesPastMaxMessagePayload() { - $frame = new Frame(str_repeat('a', 200), false, Frame::OP_TEXT); - $firstFrameRaw = $frame->getContents(); - $frame = new Frame(str_repeat('b', 200), true, Frame::OP_TEXT); - $secondFrameRaw = $frame->getContents(); - - /** @var Frame $controlFrame */ - $controlFrame = null; - $messageCount = 0; - - $messageBuffer = new MessageBuffer( - new CloseFrameChecker(), - function (Message $message) use (&$messageCount) { - $messageCount++; - }, - function (Frame $frame) use (&$controlFrame) { - $this->assertNull($controlFrame); - $controlFrame = $frame; - }, - false, - null, - 300, - 0 - ); - - $messageBuffer->onData($firstFrameRaw); - // only put part of the second frame in to watch it fail fast - $messageBuffer->onData(substr($secondFrameRaw, 0, 150)); - - $this->assertEquals(0, $messageCount); - $this->assertTrue($controlFrame instanceof Frame); - $this->assertEquals(Frame::OP_CLOSE, $controlFrame->getOpcode()); - $this->assertEquals([Frame::CLOSE_TOO_BIG], array_merge(unpack('n*', substr($controlFrame->getPayload(), 0, 2)))); - } - - /** - * Some test cases from memory limit inspired by https://github.com/BrandEmbassy/php-memory - * - * Here is the license for that project: - * MIT License - * - * Copyright (c) 2018 Brand Embassy - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - - /** - * @dataProvider phpConfigurationProvider - * - * @param string $phpConfigurationValue - * @param int $expectedLimit - */ - public function testMemoryLimits($phpConfigurationValue, $expectedLimit) { - $method = new \ReflectionMethod('Ratchet\RFC6455\Messaging\MessageBuffer', 'getMemoryLimit'); - $method->setAccessible(true); - $actualLimit = $method->invoke(null, $phpConfigurationValue); - - $this->assertSame($expectedLimit, $actualLimit); - } - - public function phpConfigurationProvider() { - return [ - 'without unit type, just bytes' => ['500', 500], - '1 GB with big "G"' => ['1G', 1 * 1024 * 1024 * 1024], - '128 MB with big "M"' => ['128M', 128 * 1024 * 1024], - '128 MB with small "m"' => ['128m', 128 * 1024 * 1024], - '24 kB with small "k"' => ['24k', 24 * 1024], - '2 GB with small "g"' => ['2g', 2 * 1024 * 1024 * 1024], - 'unlimited memory' => ['-1', 0], - 'invalid float value' => ['2.5M', 2 * 1024 * 1024], - 'empty value' => ['', 0], - 'invalid ini setting' => ['whatever it takes', 0] - ]; - } - - /** - * @expectedException \InvalidArgumentException - */ - public function testInvalidMaxFramePayloadSizes() { - $messageBuffer = new MessageBuffer( - new CloseFrameChecker(), - function (Message $message) {}, - function (Frame $frame) {}, - false, - null, - 0, - 0x8000000000000000 - ); - } - - /** - * @expectedException \InvalidArgumentException - */ - public function testInvalidMaxMessagePayloadSizes() { - $messageBuffer = new MessageBuffer( - new CloseFrameChecker(), - function (Message $message) {}, - function (Frame $frame) {}, - false, - null, - 0x8000000000000000, - 0 - ); - } - - /** - * @dataProvider phpConfigurationProvider - * - * @param string $phpConfigurationValue - * @param int $expectedLimit - * - * @runInSeparateProcess - * @requires PHP 7.0 - */ - public function testIniSizes($phpConfigurationValue, $expectedLimit) { - $value = @ini_set('memory_limit', $phpConfigurationValue); - if ($value === false) { - $this->markTestSkipped("Does not support setting the memory_limit lower than current memory_usage"); - } - - $messageBuffer = new MessageBuffer( - new CloseFrameChecker(), - function (Message $message) {}, - function (Frame $frame) {}, - false, - null - ); - - if ($expectedLimit === -1) { - $expectedLimit = 0; - } - - $prop = new \ReflectionProperty($messageBuffer, 'maxMessagePayloadSize'); - $prop->setAccessible(true); - $this->assertEquals($expectedLimit / 4, $prop->getValue($messageBuffer)); - - $prop = new \ReflectionProperty($messageBuffer, 'maxFramePayloadSize'); - $prop->setAccessible(true); - $this->assertEquals($expectedLimit / 4, $prop->getValue($messageBuffer)); - } - - /** - * @runInSeparateProcess - * @requires PHP 7.0 - */ - public function testInvalidIniSize() { - $value = @ini_set('memory_limit', 'lots of memory'); - if ($value === false) { - $this->markTestSkipped("Does not support setting the memory_limit lower than current memory_usage"); - } - - $messageBuffer = new MessageBuffer( - new CloseFrameChecker(), - function (Message $message) {}, - function (Frame $frame) {}, - false, - null - ); - - $prop = new \ReflectionProperty($messageBuffer, 'maxMessagePayloadSize'); - $prop->setAccessible(true); - $this->assertEquals(0, $prop->getValue($messageBuffer)); - - $prop = new \ReflectionProperty($messageBuffer, 'maxFramePayloadSize'); - $prop->setAccessible(true); - $this->assertEquals(0, $prop->getValue($messageBuffer)); - } -} \ No newline at end of file diff --git a/digital_doctor/vendor/ratchet/rfc6455/tests/unit/Messaging/MessageTest.php b/digital_doctor/vendor/ratchet/rfc6455/tests/unit/Messaging/MessageTest.php deleted file mode 100644 index c307da8..0000000 --- a/digital_doctor/vendor/ratchet/rfc6455/tests/unit/Messaging/MessageTest.php +++ /dev/null @@ -1,61 +0,0 @@ -message = new Message; - } - - public function testNoFrames() { - $this->assertFalse($this->message->isCoalesced()); - } - - public function testNoFramesOpCode() { - $this->setExpectedException('UnderflowException'); - $this->message->getOpCode(); - } - - public function testFragmentationPayload() { - $a = 'Hello '; - $b = 'World!'; - $f1 = new Frame($a, false); - $f2 = new Frame($b, true, Frame::OP_CONTINUE); - $this->message->addFrame($f1)->addFrame($f2); - $this->assertEquals(strlen($a . $b), $this->message->getPayloadLength()); - $this->assertEquals($a . $b, $this->message->getPayload()); - } - - public function testUnbufferedFragment() { - $this->message->addFrame(new Frame('The quick brow', false)); - $this->setExpectedException('UnderflowException'); - $this->message->getPayload(); - } - - public function testGetOpCode() { - $this->message - ->addFrame(new Frame('The quick brow', false, Frame::OP_TEXT)) - ->addFrame(new Frame('n fox jumps ov', false, Frame::OP_CONTINUE)) - ->addFrame(new Frame('er the lazy dog', true, Frame::OP_CONTINUE)) - ; - $this->assertEquals(Frame::OP_TEXT, $this->message->getOpCode()); - } - - public function testGetUnBufferedPayloadLength() { - $this->message - ->addFrame(new Frame('The quick brow', false, Frame::OP_TEXT)) - ->addFrame(new Frame('n fox jumps ov', false, Frame::OP_CONTINUE)) - ; - $this->assertEquals(28, $this->message->getPayloadLength()); - } -} \ No newline at end of file diff --git a/digital_doctor/vendor/react/cache/CHANGELOG.md b/digital_doctor/vendor/react/cache/CHANGELOG.md deleted file mode 100644 index ab59f18..0000000 --- a/digital_doctor/vendor/react/cache/CHANGELOG.md +++ /dev/null @@ -1,96 +0,0 @@ -# Changelog - -## 1.2.0 (2022-11-30) - -* Feature: Support PHP 8.1 and PHP 8.2. - (#47 by @SimonFrings and #52 by @WyriHaximus) - -* Minor documentation improvements. - (#48 by @SimonFrings and #51 by @nhedger) - -* Update test suite and use GitHub actions for continuous integration (CI). - (#45 and #49 by @SimonFrings and #54 by @clue) - -## 1.1.0 (2020-09-18) - -* Feature: Forward compatibility with react/promise 3. - (#39 by @WyriHaximus) - -* Add `.gitattributes` to exclude dev files from exports. - (#40 by @reedy) - -* Improve test suite, update to support PHP 8 and PHPUnit 9.3. - (#41 and #43 by @SimonFrings and #42 by @WyriHaximus) - -## 1.0.0 (2019-07-11) - -* First stable LTS release, now following [SemVer](https://semver.org/). - We'd like to emphasize that this component is production ready and battle-tested. - We plan to support all long-term support (LTS) releases for at least 24 months, - so you have a rock-solid foundation to build on top of. - -> Contains no other changes, so it's actually fully compatible with the v0.6.0 release. - -## 0.6.0 (2019-07-04) - -* Feature / BC break: Add support for `getMultiple()`, `setMultiple()`, `deleteMultiple()`, `clear()` and `has()` - supporting multiple cache items (inspired by PSR-16). - (#32 by @krlv and #37 by @clue) - -* Documentation for TTL precision with millisecond accuracy or below and - use high-resolution timer for cache TTL on PHP 7.3+. - (#35 and #38 by @clue) - -* Improve API documentation and allow legacy HHVM to fail in Travis CI config. - (#34 and #36 by @clue) - -* Prefix all global functions calls with \ to skip the look up and resolve process and go straight to the global function. - (#31 by @WyriHaximus) - -## 0.5.0 (2018-06-25) - -* Improve documentation by describing what is expected of a class implementing `CacheInterface`. - (#21, #22, #23, #27 by @WyriHaximus) - -* Implemented (optional) Least Recently Used (LRU) cache algorithm for `ArrayCache`. - (#26 by @clue) - -* Added support for cache expiration (TTL). - (#29 by @clue and @WyriHaximus) - -* Renamed `remove` to `delete` making it more in line with `PSR-16`. - (#30 by @clue) - -## 0.4.2 (2017-12-20) - -* Improve documentation with usage and installation instructions - (#10 by @clue) - -* Improve test suite by adding PHPUnit to `require-dev` and - add forward compatibility with PHPUnit 5 and PHPUnit 6 and - sanitize Composer autoload paths - (#14 by @shaunbramley and #12 and #18 by @clue) - -## 0.4.1 (2016-02-25) - -* Repository maintenance, split off from main repo, improve test suite and documentation -* First class support for PHP7 and HHVM (#9 by @clue) -* Adjust compatibility to 5.3 (#7 by @clue) - -## 0.4.0 (2014-02-02) - -* BC break: Bump minimum PHP version to PHP 5.4, remove 5.3 specific hacks -* BC break: Update to React/Promise 2.0 -* Dependency: Autoloading and filesystem structure now PSR-4 instead of PSR-0 - -## 0.3.2 (2013-05-10) - -* Version bump - -## 0.3.0 (2013-04-14) - -* Version bump - -## 0.2.6 (2012-12-26) - -* Feature: New cache component, used by DNS diff --git a/digital_doctor/vendor/react/cache/LICENSE b/digital_doctor/vendor/react/cache/LICENSE deleted file mode 100644 index d6f8901..0000000 --- a/digital_doctor/vendor/react/cache/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2012 Christian Lück, Cees-Jan Kiewiet, Jan Sorgalla, Chris Boden, Igor Wiedler - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/digital_doctor/vendor/react/cache/README.md b/digital_doctor/vendor/react/cache/README.md deleted file mode 100644 index 7a86be9..0000000 --- a/digital_doctor/vendor/react/cache/README.md +++ /dev/null @@ -1,367 +0,0 @@ -# Cache - -[![CI status](https://github.com/reactphp/cache/actions/workflows/ci.yml/badge.svg)](https://github.com/reactphp/cache/actions) -[![installs on Packagist](https://img.shields.io/packagist/dt/react/cache?color=blue&label=installs%20on%20Packagist)](https://packagist.org/packages/react/cache) - -Async, [Promise](https://github.com/reactphp/promise)-based cache interface -for [ReactPHP](https://reactphp.org/). - -The cache component provides a -[Promise](https://github.com/reactphp/promise)-based -[`CacheInterface`](#cacheinterface) and an in-memory [`ArrayCache`](#arraycache) -implementation of that. -This allows consumers to type hint against the interface and third parties to -provide alternate implementations. -This project is heavily inspired by -[PSR-16: Common Interface for Caching Libraries](https://www.php-fig.org/psr/psr-16/), -but uses an interface more suited for async, non-blocking applications. - -**Table of Contents** - -* [Usage](#usage) - * [CacheInterface](#cacheinterface) - * [get()](#get) - * [set()](#set) - * [delete()](#delete) - * [getMultiple()](#getmultiple) - * [setMultiple()](#setmultiple) - * [deleteMultiple()](#deletemultiple) - * [clear()](#clear) - * [has()](#has) - * [ArrayCache](#arraycache) -* [Common usage](#common-usage) - * [Fallback get](#fallback-get) - * [Fallback-get-and-set](#fallback-get-and-set) -* [Install](#install) -* [Tests](#tests) -* [License](#license) - -## Usage - -### CacheInterface - -The `CacheInterface` describes the main interface of this component. -This allows consumers to type hint against the interface and third parties to -provide alternate implementations. - -#### get() - -The `get(string $key, mixed $default = null): PromiseInterface` method can be used to -retrieve an item from the cache. - -This method will resolve with the cached value on success or with the -given `$default` value when no item can be found or when an error occurs. -Similarly, an expired cache item (once the time-to-live is expired) is -considered a cache miss. - -```php -$cache - ->get('foo') - ->then('var_dump'); -``` - -This example fetches the value of the key `foo` and passes it to the -`var_dump` function. You can use any of the composition provided by -[promises](https://github.com/reactphp/promise). - -#### set() - -The `set(string $key, mixed $value, ?float $ttl = null): PromiseInterface` method can be used to -store an item in the cache. - -This method will resolve with `true` on success or `false` when an error -occurs. If the cache implementation has to go over the network to store -it, it may take a while. - -The optional `$ttl` parameter sets the maximum time-to-live in seconds -for this cache item. If this parameter is omitted (or `null`), the item -will stay in the cache for as long as the underlying implementation -supports. Trying to access an expired cache item results in a cache miss, -see also [`get()`](#get). - -```php -$cache->set('foo', 'bar', 60); -``` - -This example eventually sets the value of the key `foo` to `bar`. If it -already exists, it is overridden. - -This interface does not enforce any particular TTL resolution, so special -care may have to be taken if you rely on very high precision with -millisecond accuracy or below. Cache implementations SHOULD work on a -best effort basis and SHOULD provide at least second accuracy unless -otherwise noted. Many existing cache implementations are known to provide -microsecond or millisecond accuracy, but it's generally not recommended -to rely on this high precision. - -This interface suggests that cache implementations SHOULD use a monotonic -time source if available. Given that a monotonic time source is only -available as of PHP 7.3 by default, cache implementations MAY fall back -to using wall-clock time. -While this does not affect many common use cases, this is an important -distinction for programs that rely on a high time precision or on systems -that are subject to discontinuous time adjustments (time jumps). -This means that if you store a cache item with a TTL of 30s and then -adjust your system time forward by 20s, the cache item SHOULD still -expire in 30s. - -#### delete() - -The `delete(string $key): PromiseInterface` method can be used to -delete an item from the cache. - -This method will resolve with `true` on success or `false` when an error -occurs. When no item for `$key` is found in the cache, it also resolves -to `true`. If the cache implementation has to go over the network to -delete it, it may take a while. - -```php -$cache->delete('foo'); -``` - -This example eventually deletes the key `foo` from the cache. As with -`set()`, this may not happen instantly and a promise is returned to -provide guarantees whether or not the item has been removed from cache. - -#### getMultiple() - -The `getMultiple(string[] $keys, mixed $default = null): PromiseInterface` method can be used to -retrieve multiple cache items by their unique keys. - -This method will resolve with an array of cached values on success or with the -given `$default` value when an item can not be found or when an error occurs. -Similarly, an expired cache item (once the time-to-live is expired) is -considered a cache miss. - -```php -$cache->getMultiple(array('name', 'age'))->then(function (array $values) { - $name = $values['name'] ?? 'User'; - $age = $values['age'] ?? 'n/a'; - - echo $name . ' is ' . $age . PHP_EOL; -}); -``` - -This example fetches the cache items for the `name` and `age` keys and -prints some example output. You can use any of the composition provided -by [promises](https://github.com/reactphp/promise). - -#### setMultiple() - -The `setMultiple(array $values, ?float $ttl = null): PromiseInterface` method can be used to -persist a set of key => value pairs in the cache, with an optional TTL. - -This method will resolve with `true` on success or `false` when an error -occurs. If the cache implementation has to go over the network to store -it, it may take a while. - -The optional `$ttl` parameter sets the maximum time-to-live in seconds -for these cache items. If this parameter is omitted (or `null`), these items -will stay in the cache for as long as the underlying implementation -supports. Trying to access an expired cache items results in a cache miss, -see also [`getMultiple()`](#getmultiple). - -```php -$cache->setMultiple(array('foo' => 1, 'bar' => 2), 60); -``` - -This example eventually sets the list of values - the key `foo` to `1` value -and the key `bar` to `2`. If some of the keys already exist, they are overridden. - -#### deleteMultiple() - -The `setMultiple(string[] $keys): PromiseInterface` method can be used to -delete multiple cache items in a single operation. - -This method will resolve with `true` on success or `false` when an error -occurs. When no items for `$keys` are found in the cache, it also resolves -to `true`. If the cache implementation has to go over the network to -delete it, it may take a while. - -```php -$cache->deleteMultiple(array('foo', 'bar, 'baz')); -``` - -This example eventually deletes keys `foo`, `bar` and `baz` from the cache. -As with `setMultiple()`, this may not happen instantly and a promise is returned to -provide guarantees whether or not the item has been removed from cache. - -#### clear() - -The `clear(): PromiseInterface` method can be used to -wipe clean the entire cache. - -This method will resolve with `true` on success or `false` when an error -occurs. If the cache implementation has to go over the network to -delete it, it may take a while. - -```php -$cache->clear(); -``` - -This example eventually deletes all keys from the cache. As with `deleteMultiple()`, -this may not happen instantly and a promise is returned to provide guarantees -whether or not all the items have been removed from cache. - -#### has() - -The `has(string $key): PromiseInterface` method can be used to -determine whether an item is present in the cache. - -This method will resolve with `true` on success or `false` when no item can be found -or when an error occurs. Similarly, an expired cache item (once the time-to-live -is expired) is considered a cache miss. - -```php -$cache - ->has('foo') - ->then('var_dump'); -``` - -This example checks if the value of the key `foo` is set in the cache and passes -the result to the `var_dump` function. You can use any of the composition provided by -[promises](https://github.com/reactphp/promise). - -NOTE: It is recommended that has() is only to be used for cache warming type purposes -and not to be used within your live applications operations for get/set, as this method -is subject to a race condition where your has() will return true and immediately after, -another script can remove it making the state of your app out of date. - -### ArrayCache - -The `ArrayCache` provides an in-memory implementation of the [`CacheInterface`](#cacheinterface). - -```php -$cache = new ArrayCache(); - -$cache->set('foo', 'bar'); -``` - -Its constructor accepts an optional `?int $limit` parameter to limit the -maximum number of entries to store in the LRU cache. If you add more -entries to this instance, it will automatically take care of removing -the one that was least recently used (LRU). - -For example, this snippet will overwrite the first value and only store -the last two entries: - -```php -$cache = new ArrayCache(2); - -$cache->set('foo', '1'); -$cache->set('bar', '2'); -$cache->set('baz', '3'); -``` - -This cache implementation is known to rely on wall-clock time to schedule -future cache expiration times when using any version before PHP 7.3, -because a monotonic time source is only available as of PHP 7.3 (`hrtime()`). -While this does not affect many common use cases, this is an important -distinction for programs that rely on a high time precision or on systems -that are subject to discontinuous time adjustments (time jumps). -This means that if you store a cache item with a TTL of 30s on PHP < 7.3 -and then adjust your system time forward by 20s, the cache item may -expire in 10s. See also [`set()`](#set) for more details. - -## Common usage - -### Fallback get - -A common use case of caches is to attempt fetching a cached value and as a -fallback retrieve it from the original data source if not found. Here is an -example of that: - -```php -$cache - ->get('foo') - ->then(function ($result) { - if ($result === null) { - return getFooFromDb(); - } - - return $result; - }) - ->then('var_dump'); -``` - -First an attempt is made to retrieve the value of `foo`. A callback function is -registered that will call `getFooFromDb` when the resulting value is null. -`getFooFromDb` is a function (can be any PHP callable) that will be called if the -key does not exist in the cache. - -`getFooFromDb` can handle the missing key by returning a promise for the -actual value from the database (or any other data source). As a result, this -chain will correctly fall back, and provide the value in both cases. - -### Fallback get and set - -To expand on the fallback get example, often you want to set the value on the -cache after fetching it from the data source. - -```php -$cache - ->get('foo') - ->then(function ($result) { - if ($result === null) { - return $this->getAndCacheFooFromDb(); - } - - return $result; - }) - ->then('var_dump'); - -public function getAndCacheFooFromDb() -{ - return $this->db - ->get('foo') - ->then(array($this, 'cacheFooFromDb')); -} - -public function cacheFooFromDb($foo) -{ - $this->cache->set('foo', $foo); - - return $foo; -} -``` - -By using chaining you can easily conditionally cache the value if it is -fetched from the database. - -## Install - -The recommended way to install this library is [through Composer](https://getcomposer.org). -[New to Composer?](https://getcomposer.org/doc/00-intro.md) - -This project follows [SemVer](https://semver.org/). -This will install the latest supported version: - -```bash -composer require react/cache:^1.2 -``` - -See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades. - -This project aims to run on any platform and thus does not require any PHP -extensions and supports running on legacy PHP 5.3 through current PHP 8+ and -HHVM. -It's *highly recommended to use PHP 7+* for this project. - -## Tests - -To run the test suite, you first need to clone this repo and then install all -dependencies [through Composer](https://getcomposer.org): - -```bash -composer install -``` - -To run the test suite, go to the project root and run: - -```bash -vendor/bin/phpunit -``` - -## License - -MIT, see [LICENSE file](LICENSE). diff --git a/digital_doctor/vendor/react/cache/composer.json b/digital_doctor/vendor/react/cache/composer.json deleted file mode 100644 index 153439a..0000000 --- a/digital_doctor/vendor/react/cache/composer.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "name": "react/cache", - "description": "Async, Promise-based cache interface for ReactPHP", - "keywords": ["cache", "caching", "promise", "ReactPHP"], - "license": "MIT", - "authors": [ - { - "name": "Christian Lück", - "homepage": "https://clue.engineering/", - "email": "christian@clue.engineering" - }, - { - "name": "Cees-Jan Kiewiet", - "homepage": "https://wyrihaximus.net/", - "email": "reactphp@ceesjankiewiet.nl" - }, - { - "name": "Jan Sorgalla", - "homepage": "https://sorgalla.com/", - "email": "jsorgalla@gmail.com" - }, - { - "name": "Chris Boden", - "homepage": "https://cboden.dev/", - "email": "cboden@gmail.com" - } - ], - "require": { - "php": ">=5.3.0", - "react/promise": "^3.0 || ^2.0 || ^1.1" - }, - "require-dev": { - "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35" - }, - "autoload": { - "psr-4": { - "React\\Cache\\": "src/" - } - }, - "autoload-dev": { - "psr-4": { - "React\\Tests\\Cache\\": "tests/" - } - } -} diff --git a/digital_doctor/vendor/react/cache/src/ArrayCache.php b/digital_doctor/vendor/react/cache/src/ArrayCache.php deleted file mode 100644 index 81f25ef..0000000 --- a/digital_doctor/vendor/react/cache/src/ArrayCache.php +++ /dev/null @@ -1,181 +0,0 @@ -set('foo', 'bar'); - * ``` - * - * Its constructor accepts an optional `?int $limit` parameter to limit the - * maximum number of entries to store in the LRU cache. If you add more - * entries to this instance, it will automatically take care of removing - * the one that was least recently used (LRU). - * - * For example, this snippet will overwrite the first value and only store - * the last two entries: - * - * ```php - * $cache = new ArrayCache(2); - * - * $cache->set('foo', '1'); - * $cache->set('bar', '2'); - * $cache->set('baz', '3'); - * ``` - * - * This cache implementation is known to rely on wall-clock time to schedule - * future cache expiration times when using any version before PHP 7.3, - * because a monotonic time source is only available as of PHP 7.3 (`hrtime()`). - * While this does not affect many common use cases, this is an important - * distinction for programs that rely on a high time precision or on systems - * that are subject to discontinuous time adjustments (time jumps). - * This means that if you store a cache item with a TTL of 30s on PHP < 7.3 - * and then adjust your system time forward by 20s, the cache item may - * expire in 10s. See also [`set()`](#set) for more details. - * - * @param int|null $limit maximum number of entries to store in the LRU cache - */ - public function __construct($limit = null) - { - $this->limit = $limit; - - // prefer high-resolution timer, available as of PHP 7.3+ - $this->supportsHighResolution = \function_exists('hrtime'); - } - - public function get($key, $default = null) - { - // delete key if it is already expired => below will detect this as a cache miss - if (isset($this->expires[$key]) && $this->now() - $this->expires[$key] > 0) { - unset($this->data[$key], $this->expires[$key]); - } - - if (!\array_key_exists($key, $this->data)) { - return Promise\resolve($default); - } - - // remove and append to end of array to keep track of LRU info - $value = $this->data[$key]; - unset($this->data[$key]); - $this->data[$key] = $value; - - return Promise\resolve($value); - } - - public function set($key, $value, $ttl = null) - { - // unset before setting to ensure this entry will be added to end of array (LRU info) - unset($this->data[$key]); - $this->data[$key] = $value; - - // sort expiration times if TTL is given (first will expire first) - unset($this->expires[$key]); - if ($ttl !== null) { - $this->expires[$key] = $this->now() + $ttl; - \asort($this->expires); - } - - // ensure size limit is not exceeded or remove first entry from array - if ($this->limit !== null && \count($this->data) > $this->limit) { - // first try to check if there's any expired entry - // expiration times are sorted, so we can simply look at the first one - \reset($this->expires); - $key = \key($this->expires); - - // check to see if the first in the list of expiring keys is already expired - // if the first key is not expired, we have to overwrite by using LRU info - if ($key === null || $this->now() - $this->expires[$key] < 0) { - \reset($this->data); - $key = \key($this->data); - } - unset($this->data[$key], $this->expires[$key]); - } - - return Promise\resolve(true); - } - - public function delete($key) - { - unset($this->data[$key], $this->expires[$key]); - - return Promise\resolve(true); - } - - public function getMultiple(array $keys, $default = null) - { - $values = array(); - - foreach ($keys as $key) { - $values[$key] = $this->get($key, $default); - } - - return Promise\all($values); - } - - public function setMultiple(array $values, $ttl = null) - { - foreach ($values as $key => $value) { - $this->set($key, $value, $ttl); - } - - return Promise\resolve(true); - } - - public function deleteMultiple(array $keys) - { - foreach ($keys as $key) { - unset($this->data[$key], $this->expires[$key]); - } - - return Promise\resolve(true); - } - - public function clear() - { - $this->data = array(); - $this->expires = array(); - - return Promise\resolve(true); - } - - public function has($key) - { - // delete key if it is already expired - if (isset($this->expires[$key]) && $this->now() - $this->expires[$key] > 0) { - unset($this->data[$key], $this->expires[$key]); - } - - if (!\array_key_exists($key, $this->data)) { - return Promise\resolve(false); - } - - // remove and append to end of array to keep track of LRU info - $value = $this->data[$key]; - unset($this->data[$key]); - $this->data[$key] = $value; - - return Promise\resolve(true); - } - - /** - * @return float - */ - private function now() - { - return $this->supportsHighResolution ? \hrtime(true) * 1e-9 : \microtime(true); - } -} diff --git a/digital_doctor/vendor/react/cache/src/CacheInterface.php b/digital_doctor/vendor/react/cache/src/CacheInterface.php deleted file mode 100644 index 8e51c19..0000000 --- a/digital_doctor/vendor/react/cache/src/CacheInterface.php +++ /dev/null @@ -1,194 +0,0 @@ -get('foo') - * ->then('var_dump'); - * ``` - * - * This example fetches the value of the key `foo` and passes it to the - * `var_dump` function. You can use any of the composition provided by - * [promises](https://github.com/reactphp/promise). - * - * @param string $key - * @param mixed $default Default value to return for cache miss or null if not given. - * @return PromiseInterface - */ - public function get($key, $default = null); - - /** - * Stores an item in the cache. - * - * This method will resolve with `true` on success or `false` when an error - * occurs. If the cache implementation has to go over the network to store - * it, it may take a while. - * - * The optional `$ttl` parameter sets the maximum time-to-live in seconds - * for this cache item. If this parameter is omitted (or `null`), the item - * will stay in the cache for as long as the underlying implementation - * supports. Trying to access an expired cache item results in a cache miss, - * see also [`get()`](#get). - * - * ```php - * $cache->set('foo', 'bar', 60); - * ``` - * - * This example eventually sets the value of the key `foo` to `bar`. If it - * already exists, it is overridden. - * - * This interface does not enforce any particular TTL resolution, so special - * care may have to be taken if you rely on very high precision with - * millisecond accuracy or below. Cache implementations SHOULD work on a - * best effort basis and SHOULD provide at least second accuracy unless - * otherwise noted. Many existing cache implementations are known to provide - * microsecond or millisecond accuracy, but it's generally not recommended - * to rely on this high precision. - * - * This interface suggests that cache implementations SHOULD use a monotonic - * time source if available. Given that a monotonic time source is only - * available as of PHP 7.3 by default, cache implementations MAY fall back - * to using wall-clock time. - * While this does not affect many common use cases, this is an important - * distinction for programs that rely on a high time precision or on systems - * that are subject to discontinuous time adjustments (time jumps). - * This means that if you store a cache item with a TTL of 30s and then - * adjust your system time forward by 20s, the cache item SHOULD still - * expire in 30s. - * - * @param string $key - * @param mixed $value - * @param ?float $ttl - * @return PromiseInterface Returns a promise which resolves to `true` on success or `false` on error - */ - public function set($key, $value, $ttl = null); - - /** - * Deletes an item from the cache. - * - * This method will resolve with `true` on success or `false` when an error - * occurs. When no item for `$key` is found in the cache, it also resolves - * to `true`. If the cache implementation has to go over the network to - * delete it, it may take a while. - * - * ```php - * $cache->delete('foo'); - * ``` - * - * This example eventually deletes the key `foo` from the cache. As with - * `set()`, this may not happen instantly and a promise is returned to - * provide guarantees whether or not the item has been removed from cache. - * - * @param string $key - * @return PromiseInterface Returns a promise which resolves to `true` on success or `false` on error - */ - public function delete($key); - - /** - * Retrieves multiple cache items by their unique keys. - * - * This method will resolve with an array of cached values on success or with the - * given `$default` value when an item can not be found or when an error occurs. - * Similarly, an expired cache item (once the time-to-live is expired) is - * considered a cache miss. - * - * ```php - * $cache->getMultiple(array('name', 'age'))->then(function (array $values) { - * $name = $values['name'] ?? 'User'; - * $age = $values['age'] ?? 'n/a'; - * - * echo $name . ' is ' . $age . PHP_EOL; - * }); - * ``` - * - * This example fetches the cache items for the `name` and `age` keys and - * prints some example output. You can use any of the composition provided - * by [promises](https://github.com/reactphp/promise). - * - * @param string[] $keys A list of keys that can obtained in a single operation. - * @param mixed $default Default value to return for keys that do not exist. - * @return PromiseInterface Returns a promise which resolves to an `array` of cached values - */ - public function getMultiple(array $keys, $default = null); - - /** - * Persists a set of key => value pairs in the cache, with an optional TTL. - * - * This method will resolve with `true` on success or `false` when an error - * occurs. If the cache implementation has to go over the network to store - * it, it may take a while. - * - * The optional `$ttl` parameter sets the maximum time-to-live in seconds - * for these cache items. If this parameter is omitted (or `null`), these items - * will stay in the cache for as long as the underlying implementation - * supports. Trying to access an expired cache items results in a cache miss, - * see also [`get()`](#get). - * - * ```php - * $cache->setMultiple(array('foo' => 1, 'bar' => 2), 60); - * ``` - * - * This example eventually sets the list of values - the key `foo` to 1 value - * and the key `bar` to 2. If some of the keys already exist, they are overridden. - * - * @param array $values A list of key => value pairs for a multiple-set operation. - * @param ?float $ttl Optional. The TTL value of this item. - * @return PromiseInterface Returns a promise which resolves to `true` on success or `false` on error - */ - public function setMultiple(array $values, $ttl = null); - - /** - * Deletes multiple cache items in a single operation. - * - * @param string[] $keys A list of string-based keys to be deleted. - * @return PromiseInterface Returns a promise which resolves to `true` on success or `false` on error - */ - public function deleteMultiple(array $keys); - - /** - * Wipes clean the entire cache. - * - * @return PromiseInterface Returns a promise which resolves to `true` on success or `false` on error - */ - public function clear(); - - /** - * Determines whether an item is present in the cache. - * - * This method will resolve with `true` on success or `false` when no item can be found - * or when an error occurs. Similarly, an expired cache item (once the time-to-live - * is expired) is considered a cache miss. - * - * ```php - * $cache - * ->has('foo') - * ->then('var_dump'); - * ``` - * - * This example checks if the value of the key `foo` is set in the cache and passes - * the result to the `var_dump` function. You can use any of the composition provided by - * [promises](https://github.com/reactphp/promise). - * - * NOTE: It is recommended that has() is only to be used for cache warming type purposes - * and not to be used within your live applications operations for get/set, as this method - * is subject to a race condition where your has() will return true and immediately after, - * another script can remove it making the state of your app out of date. - * - * @param string $key The cache item key. - * @return PromiseInterface Returns a promise which resolves to `true` on success or `false` on error - */ - public function has($key); -} diff --git a/digital_doctor/vendor/react/dns/CHANGELOG.md b/digital_doctor/vendor/react/dns/CHANGELOG.md deleted file mode 100644 index bc1055f..0000000 --- a/digital_doctor/vendor/react/dns/CHANGELOG.md +++ /dev/null @@ -1,452 +0,0 @@ -# Changelog - -## 1.13.0 (2024-06-13) - -* Feature: Improve PHP 8.4+ support by avoiding implicitly nullable type declarations. - (#224 by @WyriHaximus) - -## 1.12.0 (2023-11-29) - -* Feature: Full PHP 8.3 compatibility. - (#217 by @sergiy-petrov) - -* Update test environment and avoid unhandled promise rejections. - (#215, #216 and #218 by @clue) - -## 1.11.0 (2023-06-02) - -* Feature: Include timeout logic to avoid dependency on reactphp/promise-timer. - (#213 by @clue) - -* Improve test suite and project setup and report failed assertions. - (#210 by @clue, #212 by @WyriHaximus and #209 and #211 by @SimonFrings) - -## 1.10.0 (2022-09-08) - -* Feature: Full support for PHP 8.2 release. - (#201 by @clue and #207 by @WyriHaximus) - -* Feature: Optimize forward compatibility with Promise v3, avoid hitting autoloader. - (#202 by @clue) - -* Feature / Fix: Improve error reporting when custom error handler is used. - (#197 by @clue) - -* Fix: Fix invalid references in exception stack trace. - (#191 by @clue) - -* Minor documentation improvements. - (#195 by @SimonFrings and #203 by @nhedger) - -* Improve test suite, update to use default loop and new reactphp/async package. - (#204, #205 and #206 by @clue and #196 by @SimonFrings) - -## 1.9.0 (2021-12-20) - -* Feature: Full support for PHP 8.1 release and prepare PHP 8.2 compatibility - by refactoring `Parser` to avoid assigning dynamic properties. - (#188 and #186 by @clue and #184 by @SimonFrings) - -* Feature: Avoid dependency on `ext-filter`. - (#185 by @clue) - -* Feature / Fix: Skip invalid nameserver entries from `resolv.conf` and ignore IPv6 zone IDs. - (#187 by @clue) - -* Feature / Fix: Reduce socket read chunk size for queries over TCP/IP. - (#189 by @clue) - -## 1.8.0 (2021-07-11) - -A major new feature release, see [**release announcement**](https://clue.engineering/2021/announcing-reactphp-default-loop). - -* Feature: Simplify usage by supporting new [default loop](https://reactphp.org/event-loop/#loop). - (#182 by @clue) - - ```php - // old (still supported) - $factory = new React\Dns\Resolver\Factory(); - $resolver = $factory->create($config, $loop); - - // new (using default loop) - $factory = new React\Dns\Resolver\Factory(); - $resolver = $factory->create($config); - ``` - -## 1.7.0 (2021-06-25) - -* Feature: Update DNS `Factory` to accept complete `Config` object. - Add new `FallbackExecutor` and use fallback DNS servers when `Config` lists multiple servers. - (#179 and #180 by @clue) - - ```php - // old (still supported) - $config = React\Dns\Config\Config::loadSystemConfigBlocking(); - $server = $config->nameservers ? reset($config->nameservers) : '8.8.8.8'; - $resolver = $factory->create($server, $loop); - - // new - $config = React\Dns\Config\Config::loadSystemConfigBlocking(); - if (!$config->nameservers) { - $config->nameservers[] = '8.8.8.8'; - } - $resolver = $factory->create($config, $loop); - ``` - -## 1.6.0 (2021-06-21) - -* Feature: Add support for legacy `SPF` record type. - (#178 by @akondas and @clue) - -* Fix: Fix integer overflow for TCP/IP chunk size on 32 bit platforms. - (#177 by @clue) - -## 1.5.0 (2021-03-05) - -* Feature: Improve error reporting when query fails, include domain and query type and DNS server address where applicable. - (#174 by @clue) - -* Feature: Improve error handling when sending data to DNS server fails (macOS). - (#171 and #172 by @clue) - -* Fix: Improve DNS response parser to limit recursion for compressed labels. - (#169 by @clue) - -* Improve test suite, use GitHub actions for continuous integration (CI). - (#170 by @SimonFrings) - -## 1.4.0 (2020-09-18) - -* Feature: Support upcoming PHP 8. - (#168 by @clue) - -* Improve test suite and update to PHPUnit 9.3. - (#164 by @clue, #165 and #166 by @SimonFrings and #167 by @WyriHaximus) - -## 1.3.0 (2020-07-10) - -* Feature: Forward compatibility with react/promise v3. - (#153 by @WyriHaximus) - -* Feature: Support parsing `OPT` records (EDNS0). - (#157 by @clue) - -* Fix: Avoid PHP warnings due to lack of args in exception trace on PHP 7.4. - (#160 by @clue) - -* Improve test suite and add `.gitattributes` to exclude dev files from exports. - Run tests on PHPUnit 9 and PHP 7.4 and clean up test suite. - (#154 by @reedy, #156 by @clue and #163 by @SimonFrings) - -## 1.2.0 (2019-08-15) - -* Feature: Add `TcpTransportExecutor` to send DNS queries over TCP/IP connection, - add `SelectiveTransportExecutor` to retry with TCP if UDP is truncated and - automatically select transport protocol when no explicit `udp://` or `tcp://` scheme is given in `Factory`. - (#145, #146, #147 and #148 by @clue) - -* Feature: Support escaping literal dots and special characters in domain names. - (#144 by @clue) - -## 1.1.0 (2019-07-18) - -* Feature: Support parsing `CAA` and `SSHFP` records. - (#141 and #142 by @clue) - -* Feature: Add `ResolverInterface` as common interface for `Resolver` class. - (#139 by @clue) - -* Fix: Add missing private property definitions and - remove unneeded dependency on `react/stream`. - (#140 and #143 by @clue) - -## 1.0.0 (2019-07-11) - -* First stable LTS release, now following [SemVer](https://semver.org/). - We'd like to emphasize that this component is production ready and battle-tested. - We plan to support all long-term support (LTS) releases for at least 24 months, - so you have a rock-solid foundation to build on top of. - -This update involves a number of BC breaks due to dropped support for -deprecated functionality and some internal API cleanup. We've tried hard to -avoid BC breaks where possible and minimize impact otherwise. We expect that -most consumers of this package will actually not be affected by any BC -breaks, see below for more details: - -* BC break: Delete all deprecated APIs, use `Query` objects for `Message` questions - instead of nested arrays and increase code coverage to 100%. - (#130 by @clue) - -* BC break: Move `$nameserver` from `ExecutorInterface` to `UdpTransportExecutor`, - remove advanced/internal `UdpTransportExecutor` args for `Parser`/`BinaryDumper` and - add API documentation for `ExecutorInterface`. - (#135, #137 and #138 by @clue) - -* BC break: Replace `HeaderBag` attributes with simple `Message` properties. - (#132 by @clue) - -* BC break: Mark all `Record` attributes as required, add documentation vs `Query`. - (#136 by @clue) - -* BC break: Mark all classes as final to discourage inheritance - (#134 by @WyriHaximus) - -## 0.4.19 (2019-07-10) - -* Feature: Avoid garbage references when DNS resolution rejects on legacy PHP <= 5.6. - (#133 by @clue) - -## 0.4.18 (2019-09-07) - -* Feature / Fix: Implement `CachingExecutor` using cache TTL, deprecate old `CachedExecutor`, - respect TTL from response records when caching and do not cache truncated responses. - (#129 by @clue) - -* Feature: Limit cache size to 256 last responses by default. - (#127 by @clue) - -* Feature: Cooperatively resolve hosts to avoid running same query concurrently. - (#125 by @clue) - -## 0.4.17 (2019-04-01) - -* Feature: Support parsing `authority` and `additional` records from DNS response. - (#123 by @clue) - -* Feature: Support dumping records as part of outgoing binary DNS message. - (#124 by @clue) - -* Feature: Forward compatibility with upcoming Cache v0.6 and Cache v1.0 - (#121 by @clue) - -* Improve test suite to add forward compatibility with PHPUnit 7, - test against PHP 7.3 and use legacy PHPUnit 5 on legacy HHVM. - (#122 by @clue) - -## 0.4.16 (2018-11-11) - -* Feature: Improve promise cancellation for DNS lookup retries and clean up any garbage references. - (#118 by @clue) - -* Fix: Reject parsing malformed DNS response messages such as incomplete DNS response messages, - malformed record data or malformed compressed domain name labels. - (#115 and #117 by @clue) - -* Fix: Fix interpretation of TTL as UINT32 with most significant bit unset. - (#116 by @clue) - -* Fix: Fix caching advanced MX/SRV/TXT/SOA structures. - (#112 by @clue) - -## 0.4.15 (2018-07-02) - -* Feature: Add `resolveAll()` method to support custom query types in `Resolver`. - (#110 by @clue and @WyriHaximus) - - ```php - $resolver->resolveAll('reactphp.org', Message::TYPE_AAAA)->then(function ($ips) { - echo 'IPv6 addresses for reactphp.org ' . implode(', ', $ips) . PHP_EOL; - }); - ``` - -* Feature: Support parsing `NS`, `TXT`, `MX`, `SOA` and `SRV` records. - (#104, #105, #106, #107 and #108 by @clue) - -* Feature: Add support for `Message::TYPE_ANY` and parse unknown types as binary data. - (#104 by @clue) - -* Feature: Improve error messages for failed queries and improve documentation. - (#109 by @clue) - -* Feature: Add reverse DNS lookup example. - (#111 by @clue) - -## 0.4.14 (2018-06-26) - -* Feature: Add `UdpTransportExecutor`, validate incoming DNS response messages - to avoid cache poisoning attacks and deprecate legacy `Executor`. - (#101 and #103 by @clue) - -* Feature: Forward compatibility with Cache 0.5 - (#102 by @clue) - -* Deprecate legacy `Query::$currentTime` and binary parser data attributes to clean up and simplify API. - (#99 by @clue) - -## 0.4.13 (2018-02-27) - -* Add `Config::loadSystemConfigBlocking()` to load default system config - and support parsing DNS config on all supported platforms - (`/etc/resolv.conf` on Unix/Linux/Mac and WMIC on Windows) - (#92, #93, #94 and #95 by @clue) - - ```php - $config = Config::loadSystemConfigBlocking(); - $server = $config->nameservers ? reset($config->nameservers) : '8.8.8.8'; - ``` - -* Remove unneeded cyclic dependency on react/socket - (#96 by @clue) - -## 0.4.12 (2018-01-14) - -* Improve test suite by adding forward compatibility with PHPUnit 6, - test against PHP 7.2, fix forward compatibility with upcoming EventLoop releases, - add test group to skip integration tests relying on internet connection - and add minor documentation improvements. - (#85 and #87 by @carusogabriel, #88 and #89 by @clue and #83 by @jsor) - -## 0.4.11 (2017-08-25) - -* Feature: Support resolving from default hosts file - (#75, #76 and #77 by @clue) - - This means that resolving hosts such as `localhost` will now work as - expected across all platforms with no changes required: - - ```php - $resolver->resolve('localhost')->then(function ($ip) { - echo 'IP: ' . $ip; - }); - ``` - - The new `HostsExecutor` exists for advanced usage and is otherwise used - internally for this feature. - -## 0.4.10 (2017-08-10) - -* Feature: Forward compatibility with EventLoop v1.0 and v0.5 and - lock minimum dependencies and work around circular dependency for tests - (#70 and #71 by @clue) - -* Fix: Work around DNS timeout issues for Windows users - (#74 by @clue) - -* Documentation and examples for advanced usage - (#66 by @WyriHaximus) - -* Remove broken TCP code, do not retry with invalid TCP query - (#73 by @clue) - -* Improve test suite by fixing HHVM build for now again and ignore future HHVM build errors and - lock Travis distro so new defaults will not break the build and - fix failing tests for PHP 7.1 - (#68 by @WyriHaximus and #69 and #72 by @clue) - -## 0.4.9 (2017-05-01) - -* Feature: Forward compatibility with upcoming Socket v1.0 and v0.8 - (#61 by @clue) - -## 0.4.8 (2017-04-16) - -* Feature: Add support for the AAAA record type to the protocol parser - (#58 by @othillo) - -* Feature: Add support for the PTR record type to the protocol parser - (#59 by @othillo) - -## 0.4.7 (2017-03-31) - -* Feature: Forward compatibility with upcoming Socket v0.6 and v0.7 component - (#57 by @clue) - -## 0.4.6 (2017-03-11) - -* Fix: Fix DNS timeout issues for Windows users and add forward compatibility - with Stream v0.5 and upcoming v0.6 - (#53 by @clue) - -* Improve test suite by adding PHPUnit to `require-dev` - (#54 by @clue) - -## 0.4.5 (2017-03-02) - -* Fix: Ensure we ignore the case of the answer - (#51 by @WyriHaximus) - -* Feature: Add `TimeoutExecutor` and simplify internal APIs to allow internal - code re-use for upcoming versions. - (#48 and #49 by @clue) - -## 0.4.4 (2017-02-13) - -* Fix: Fix handling connection and stream errors - (#45 by @clue) - -* Feature: Add examples and forward compatibility with upcoming Socket v0.5 component - (#46 and #47 by @clue) - -## 0.4.3 (2016-07-31) - -* Feature: Allow for cache adapter injection (#38 by @WyriHaximus) - - ```php - $factory = new React\Dns\Resolver\Factory(); - - $cache = new MyCustomCacheInstance(); - $resolver = $factory->createCached('8.8.8.8', $loop, $cache); - ``` - -* Feature: Support Promise cancellation (#35 by @clue) - - ```php - $promise = $resolver->resolve('reactphp.org'); - - $promise->cancel(); - ``` - -## 0.4.2 (2016-02-24) - -* Repository maintenance, split off from main repo, improve test suite and documentation -* First class support for PHP7 and HHVM (#34 by @clue) -* Adjust compatibility to 5.3 (#30 by @clue) - -## 0.4.1 (2014-04-13) - -* Bug fix: Fixed PSR-4 autoload path (@marcj/WyriHaximus) - -## 0.4.0 (2014-02-02) - -* BC break: Bump minimum PHP version to PHP 5.4, remove 5.3 specific hacks -* BC break: Update to React/Promise 2.0 -* Bug fix: Properly resolve CNAME aliases -* Dependency: Autoloading and filesystem structure now PSR-4 instead of PSR-0 -* Bump React dependencies to v0.4 - -## 0.3.2 (2013-05-10) - -* Feature: Support default port for IPv6 addresses (@clue) - -## 0.3.0 (2013-04-14) - -* Bump React dependencies to v0.3 - -## 0.2.6 (2012-12-26) - -* Feature: New cache component, used by DNS - -## 0.2.5 (2012-11-26) - -* Version bump - -## 0.2.4 (2012-11-18) - -* Feature: Change to promise-based API (@jsor) - -## 0.2.3 (2012-11-14) - -* Version bump - -## 0.2.2 (2012-10-28) - -* Feature: DNS executor timeout handling (@arnaud-lb) -* Feature: DNS retry executor (@arnaud-lb) - -## 0.2.1 (2012-10-14) - -* Minor adjustments to DNS parser - -## 0.2.0 (2012-09-10) - -* Feature: DNS resolver diff --git a/digital_doctor/vendor/react/dns/LICENSE b/digital_doctor/vendor/react/dns/LICENSE deleted file mode 100644 index d6f8901..0000000 --- a/digital_doctor/vendor/react/dns/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2012 Christian Lück, Cees-Jan Kiewiet, Jan Sorgalla, Chris Boden, Igor Wiedler - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/digital_doctor/vendor/react/dns/README.md b/digital_doctor/vendor/react/dns/README.md deleted file mode 100644 index 9f83a94..0000000 --- a/digital_doctor/vendor/react/dns/README.md +++ /dev/null @@ -1,453 +0,0 @@ -# DNS - -[![CI status](https://github.com/reactphp/dns/actions/workflows/ci.yml/badge.svg)](https://github.com/reactphp/dns/actions) -[![installs on Packagist](https://img.shields.io/packagist/dt/react/dns?color=blue&label=installs%20on%20Packagist)](https://packagist.org/packages/react/dns) - -Async DNS resolver for [ReactPHP](https://reactphp.org/). - -The main point of the DNS component is to provide async DNS resolution. -However, it is really a toolkit for working with DNS messages, and could -easily be used to create a DNS server. - -**Table of contents** - -* [Basic usage](#basic-usage) -* [Caching](#caching) - * [Custom cache adapter](#custom-cache-adapter) -* [ResolverInterface](#resolverinterface) - * [resolve()](#resolve) - * [resolveAll()](#resolveall) -* [Advanced usage](#advanced-usage) - * [UdpTransportExecutor](#udptransportexecutor) - * [TcpTransportExecutor](#tcptransportexecutor) - * [SelectiveTransportExecutor](#selectivetransportexecutor) - * [HostsFileExecutor](#hostsfileexecutor) -* [Install](#install) -* [Tests](#tests) -* [License](#license) -* [References](#references) - -## Basic usage - -The most basic usage is to just create a resolver through the resolver -factory. All you need to give it is a nameserver, then you can start resolving -names, baby! - -```php -$config = React\Dns\Config\Config::loadSystemConfigBlocking(); -if (!$config->nameservers) { - $config->nameservers[] = '8.8.8.8'; -} - -$factory = new React\Dns\Resolver\Factory(); -$dns = $factory->create($config); - -$dns->resolve('igor.io')->then(function ($ip) { - echo "Host: $ip\n"; -}); -``` - -See also the [first example](examples). - -The `Config` class can be used to load the system default config. This is an -operation that may access the filesystem and block. Ideally, this method should -thus be executed only once before the loop starts and not repeatedly while it is -running. -Note that this class may return an *empty* configuration if the system config -can not be loaded. As such, you'll likely want to apply a default nameserver -as above if none can be found. - -> Note that the factory loads the hosts file from the filesystem once when - creating the resolver instance. - Ideally, this method should thus be executed only once before the loop starts - and not repeatedly while it is running. - -But there's more. - -## Caching - -You can cache results by configuring the resolver to use a `CachedExecutor`: - -```php -$config = React\Dns\Config\Config::loadSystemConfigBlocking(); -if (!$config->nameservers) { - $config->nameservers[] = '8.8.8.8'; -} - -$factory = new React\Dns\Resolver\Factory(); -$dns = $factory->createCached($config); - -$dns->resolve('igor.io')->then(function ($ip) { - echo "Host: $ip\n"; -}); - -... - -$dns->resolve('igor.io')->then(function ($ip) { - echo "Host: $ip\n"; -}); -``` - -If the first call returns before the second, only one query will be executed. -The second result will be served from an in memory cache. -This is particularly useful for long running scripts where the same hostnames -have to be looked up multiple times. - -See also the [third example](examples). - -### Custom cache adapter - -By default, the above will use an in memory cache. - -You can also specify a custom cache implementing [`CacheInterface`](https://github.com/reactphp/cache) to handle the record cache instead: - -```php -$cache = new React\Cache\ArrayCache(); -$factory = new React\Dns\Resolver\Factory(); -$dns = $factory->createCached('8.8.8.8', null, $cache); -``` - -See also the wiki for possible [cache implementations](https://github.com/reactphp/react/wiki/Users#cache-implementations). - -## ResolverInterface - - - -### resolve() - -The `resolve(string $domain): PromiseInterface` method can be used to -resolve the given $domain name to a single IPv4 address (type `A` query). - -```php -$resolver->resolve('reactphp.org')->then(function ($ip) { - echo 'IP for reactphp.org is ' . $ip . PHP_EOL; -}); -``` - -This is one of the main methods in this package. It sends a DNS query -for the given $domain name to your DNS server and returns a single IP -address on success. - -If the DNS server sends a DNS response message that contains more than -one IP address for this query, it will randomly pick one of the IP -addresses from the response. If you want the full list of IP addresses -or want to send a different type of query, you should use the -[`resolveAll()`](#resolveall) method instead. - -If the DNS server sends a DNS response message that indicates an error -code, this method will reject with a `RecordNotFoundException`. Its -message and code can be used to check for the response code. - -If the DNS communication fails and the server does not respond with a -valid response message, this message will reject with an `Exception`. - -Pending DNS queries can be cancelled by cancelling its pending promise like so: - -```php -$promise = $resolver->resolve('reactphp.org'); - -$promise->cancel(); -``` - -### resolveAll() - -The `resolveAll(string $host, int $type): PromiseInterface` method can be used to -resolve all record values for the given $domain name and query $type. - -```php -$resolver->resolveAll('reactphp.org', Message::TYPE_A)->then(function ($ips) { - echo 'IPv4 addresses for reactphp.org ' . implode(', ', $ips) . PHP_EOL; -}); - -$resolver->resolveAll('reactphp.org', Message::TYPE_AAAA)->then(function ($ips) { - echo 'IPv6 addresses for reactphp.org ' . implode(', ', $ips) . PHP_EOL; -}); -``` - -This is one of the main methods in this package. It sends a DNS query -for the given $domain name to your DNS server and returns a list with all -record values on success. - -If the DNS server sends a DNS response message that contains one or more -records for this query, it will return a list with all record values -from the response. You can use the `Message::TYPE_*` constants to control -which type of query will be sent. Note that this method always returns a -list of record values, but each record value type depends on the query -type. For example, it returns the IPv4 addresses for type `A` queries, -the IPv6 addresses for type `AAAA` queries, the hostname for type `NS`, -`CNAME` and `PTR` queries and structured data for other queries. See also -the `Record` documentation for more details. - -If the DNS server sends a DNS response message that indicates an error -code, this method will reject with a `RecordNotFoundException`. Its -message and code can be used to check for the response code. - -If the DNS communication fails and the server does not respond with a -valid response message, this message will reject with an `Exception`. - -Pending DNS queries can be cancelled by cancelling its pending promise like so: - -```php -$promise = $resolver->resolveAll('reactphp.org', Message::TYPE_AAAA); - -$promise->cancel(); -``` - -## Advanced Usage - -### UdpTransportExecutor - -The `UdpTransportExecutor` can be used to -send DNS queries over a UDP transport. - -This is the main class that sends a DNS query to your DNS server and is used -internally by the `Resolver` for the actual message transport. - -For more advanced usages one can utilize this class directly. -The following example looks up the `IPv6` address for `igor.io`. - -```php -$executor = new UdpTransportExecutor('8.8.8.8:53'); - -$executor->query( - new Query($name, Message::TYPE_AAAA, Message::CLASS_IN) -)->then(function (Message $message) { - foreach ($message->answers as $answer) { - echo 'IPv6: ' . $answer->data . PHP_EOL; - } -}, 'printf'); -``` - -See also the [fourth example](examples). - -Note that this executor does not implement a timeout, so you will very likely -want to use this in combination with a `TimeoutExecutor` like this: - -```php -$executor = new TimeoutExecutor( - new UdpTransportExecutor($nameserver), - 3.0 -); -``` - -Also note that this executor uses an unreliable UDP transport and that it -does not implement any retry logic, so you will likely want to use this in -combination with a `RetryExecutor` like this: - -```php -$executor = new RetryExecutor( - new TimeoutExecutor( - new UdpTransportExecutor($nameserver), - 3.0 - ) -); -``` - -Note that this executor is entirely async and as such allows you to execute -any number of queries concurrently. You should probably limit the number of -concurrent queries in your application or you're very likely going to face -rate limitations and bans on the resolver end. For many common applications, -you may want to avoid sending the same query multiple times when the first -one is still pending, so you will likely want to use this in combination with -a `CoopExecutor` like this: - -```php -$executor = new CoopExecutor( - new RetryExecutor( - new TimeoutExecutor( - new UdpTransportExecutor($nameserver), - 3.0 - ) - ) -); -``` - -> Internally, this class uses PHP's UDP sockets and does not take advantage - of [react/datagram](https://github.com/reactphp/datagram) purely for - organizational reasons to avoid a cyclic dependency between the two - packages. Higher-level components should take advantage of the Datagram - component instead of reimplementing this socket logic from scratch. - -### TcpTransportExecutor - -The `TcpTransportExecutor` class can be used to -send DNS queries over a TCP/IP stream transport. - -This is one of the main classes that send a DNS query to your DNS server. - -For more advanced usages one can utilize this class directly. -The following example looks up the `IPv6` address for `reactphp.org`. - -```php -$executor = new TcpTransportExecutor('8.8.8.8:53'); - -$executor->query( - new Query($name, Message::TYPE_AAAA, Message::CLASS_IN) -)->then(function (Message $message) { - foreach ($message->answers as $answer) { - echo 'IPv6: ' . $answer->data . PHP_EOL; - } -}, 'printf'); -``` - -See also [example #92](examples). - -Note that this executor does not implement a timeout, so you will very likely -want to use this in combination with a `TimeoutExecutor` like this: - -```php -$executor = new TimeoutExecutor( - new TcpTransportExecutor($nameserver), - 3.0 -); -``` - -Unlike the `UdpTransportExecutor`, this class uses a reliable TCP/IP -transport, so you do not necessarily have to implement any retry logic. - -Note that this executor is entirely async and as such allows you to execute -queries concurrently. The first query will establish a TCP/IP socket -connection to the DNS server which will be kept open for a short period. -Additional queries will automatically reuse this existing socket connection -to the DNS server, will pipeline multiple requests over this single -connection and will keep an idle connection open for a short period. The -initial TCP/IP connection overhead may incur a slight delay if you only send -occasional queries – when sending a larger number of concurrent queries over -an existing connection, it becomes increasingly more efficient and avoids -creating many concurrent sockets like the UDP-based executor. You may still -want to limit the number of (concurrent) queries in your application or you -may be facing rate limitations and bans on the resolver end. For many common -applications, you may want to avoid sending the same query multiple times -when the first one is still pending, so you will likely want to use this in -combination with a `CoopExecutor` like this: - -```php -$executor = new CoopExecutor( - new TimeoutExecutor( - new TcpTransportExecutor($nameserver), - 3.0 - ) -); -``` - -> Internally, this class uses PHP's TCP/IP sockets and does not take advantage - of [react/socket](https://github.com/reactphp/socket) purely for - organizational reasons to avoid a cyclic dependency between the two - packages. Higher-level components should take advantage of the Socket - component instead of reimplementing this socket logic from scratch. - -### SelectiveTransportExecutor - -The `SelectiveTransportExecutor` class can be used to -Send DNS queries over a UDP or TCP/IP stream transport. - -This class will automatically choose the correct transport protocol to send -a DNS query to your DNS server. It will always try to send it over the more -efficient UDP transport first. If this query yields a size related issue -(truncated messages), it will retry over a streaming TCP/IP transport. - -For more advanced usages one can utilize this class directly. -The following example looks up the `IPv6` address for `reactphp.org`. - -```php -$executor = new SelectiveTransportExecutor($udpExecutor, $tcpExecutor); - -$executor->query( - new Query($name, Message::TYPE_AAAA, Message::CLASS_IN) -)->then(function (Message $message) { - foreach ($message->answers as $answer) { - echo 'IPv6: ' . $answer->data . PHP_EOL; - } -}, 'printf'); -``` - -Note that this executor only implements the logic to select the correct -transport for the given DNS query. Implementing the correct transport logic, -implementing timeouts and any retry logic is left up to the given executors, -see also [`UdpTransportExecutor`](#udptransportexecutor) and -[`TcpTransportExecutor`](#tcptransportexecutor) for more details. - -Note that this executor is entirely async and as such allows you to execute -any number of queries concurrently. You should probably limit the number of -concurrent queries in your application or you're very likely going to face -rate limitations and bans on the resolver end. For many common applications, -you may want to avoid sending the same query multiple times when the first -one is still pending, so you will likely want to use this in combination with -a `CoopExecutor` like this: - -```php -$executor = new CoopExecutor( - new SelectiveTransportExecutor( - $datagramExecutor, - $streamExecutor - ) -); -``` - -### HostsFileExecutor - -Note that the above `UdpTransportExecutor` class always performs an actual DNS query. -If you also want to take entries from your hosts file into account, you may -use this code: - -```php -$hosts = \React\Dns\Config\HostsFile::loadFromPathBlocking(); - -$executor = new UdpTransportExecutor('8.8.8.8:53'); -$executor = new HostsFileExecutor($hosts, $executor); - -$executor->query( - new Query('localhost', Message::TYPE_A, Message::CLASS_IN) -); -``` - -## Install - -The recommended way to install this library is [through Composer](https://getcomposer.org/). -[New to Composer?](https://getcomposer.org/doc/00-intro.md) - -This project follows [SemVer](https://semver.org/). -This will install the latest supported version: - -```bash -composer require react/dns:^1.13 -``` - -See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades. - -This project aims to run on any platform and thus does not require any PHP -extensions and supports running on legacy PHP 5.3 through current PHP 8+ and -HHVM. -It's *highly recommended to use the latest supported PHP version* for this project. - -## Tests - -To run the test suite, you first need to clone this repo and then install all -dependencies [through Composer](https://getcomposer.org/): - -```bash -composer install -``` - -To run the test suite, go to the project root and run: - -```bash -vendor/bin/phpunit -``` - -The test suite also contains a number of functional integration tests that rely -on a stable internet connection. -If you do not want to run these, they can simply be skipped like this: - -```bash -vendor/bin/phpunit --exclude-group internet -``` - -## License - -MIT, see [LICENSE file](LICENSE). - -## References - -* [RFC 1034](https://tools.ietf.org/html/rfc1034) Domain Names - Concepts and Facilities -* [RFC 1035](https://tools.ietf.org/html/rfc1035) Domain Names - Implementation and Specification diff --git a/digital_doctor/vendor/react/dns/composer.json b/digital_doctor/vendor/react/dns/composer.json deleted file mode 100644 index 4fe5c0d..0000000 --- a/digital_doctor/vendor/react/dns/composer.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "name": "react/dns", - "description": "Async DNS resolver for ReactPHP", - "keywords": ["dns", "dns-resolver", "ReactPHP", "async"], - "license": "MIT", - "authors": [ - { - "name": "Christian Lück", - "homepage": "https://clue.engineering/", - "email": "christian@clue.engineering" - }, - { - "name": "Cees-Jan Kiewiet", - "homepage": "https://wyrihaximus.net/", - "email": "reactphp@ceesjankiewiet.nl" - }, - { - "name": "Jan Sorgalla", - "homepage": "https://sorgalla.com/", - "email": "jsorgalla@gmail.com" - }, - { - "name": "Chris Boden", - "homepage": "https://cboden.dev/", - "email": "cboden@gmail.com" - } - ], - "require": { - "php": ">=5.3.0", - "react/cache": "^1.0 || ^0.6 || ^0.5", - "react/event-loop": "^1.2", - "react/promise": "^3.2 || ^2.7 || ^1.2.1" - }, - "require-dev": { - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", - "react/async": "^4.3 || ^3 || ^2", - "react/promise-timer": "^1.11" - }, - "autoload": { - "psr-4": { - "React\\Dns\\": "src/" - } - }, - "autoload-dev": { - "psr-4": { - "React\\Tests\\Dns\\": "tests/" - } - } -} diff --git a/digital_doctor/vendor/react/dns/src/BadServerException.php b/digital_doctor/vendor/react/dns/src/BadServerException.php deleted file mode 100644 index 3d95213..0000000 --- a/digital_doctor/vendor/react/dns/src/BadServerException.php +++ /dev/null @@ -1,7 +0,0 @@ - `fe80:1`) - if (strpos($ip, ':') !== false && ($pos = strpos($ip, '%')) !== false) { - $ip = substr($ip, 0, $pos); - } - - if (@inet_pton($ip) !== false) { - $config->nameservers[] = $ip; - } - } - - return $config; - } - - /** - * Loads the DNS configurations from Windows's WMIC (from the given command or default command) - * - * Note that this method blocks while loading the given command and should - * thus be used with care! While this should be relatively fast for normal - * WMIC commands, it remains unknown if this may block under certain - * circumstances. In particular, this method should only be executed before - * the loop starts, not while it is running. - * - * Note that this method will only try to execute the given command try to - * parse its output, irrespective of whether this command exists. In - * particular, this command is only available on Windows. Currently, this - * will only parse valid nameserver entries from the command output and will - * ignore all other output without complaining. - * - * Note that the previous section implies that this may return an empty - * `Config` object if no valid nameserver entries can be found. - * - * @param ?string $command (advanced) should not be given (NULL) unless you know what you're doing - * @return self - * @link https://ss64.com/nt/wmic.html - */ - public static function loadWmicBlocking($command = null) - { - $contents = shell_exec($command === null ? 'wmic NICCONFIG get "DNSServerSearchOrder" /format:CSV' : $command); - preg_match_all('/(?<=[{;,"])([\da-f.:]{4,})(?=[};,"])/i', $contents, $matches); - - $config = new self(); - $config->nameservers = $matches[1]; - - return $config; - } - - public $nameservers = array(); -} diff --git a/digital_doctor/vendor/react/dns/src/Config/HostsFile.php b/digital_doctor/vendor/react/dns/src/Config/HostsFile.php deleted file mode 100644 index 1060231..0000000 --- a/digital_doctor/vendor/react/dns/src/Config/HostsFile.php +++ /dev/null @@ -1,153 +0,0 @@ -contents = $contents; - } - - /** - * Returns all IPs for the given hostname - * - * @param string $name - * @return string[] - */ - public function getIpsForHost($name) - { - $name = strtolower($name); - - $ips = array(); - foreach (preg_split('/\r?\n/', $this->contents) as $line) { - $parts = preg_split('/\s+/', $line); - $ip = array_shift($parts); - if ($parts && array_search($name, $parts) !== false) { - // remove IPv6 zone ID (`fe80::1%lo0` => `fe80:1`) - if (strpos($ip, ':') !== false && ($pos = strpos($ip, '%')) !== false) { - $ip = substr($ip, 0, $pos); - } - - if (@inet_pton($ip) !== false) { - $ips[] = $ip; - } - } - } - - return $ips; - } - - /** - * Returns all hostnames for the given IPv4 or IPv6 address - * - * @param string $ip - * @return string[] - */ - public function getHostsForIp($ip) - { - // check binary representation of IP to avoid string case and short notation - $ip = @inet_pton($ip); - if ($ip === false) { - return array(); - } - - $names = array(); - foreach (preg_split('/\r?\n/', $this->contents) as $line) { - $parts = preg_split('/\s+/', $line, -1, PREG_SPLIT_NO_EMPTY); - $addr = (string) array_shift($parts); - - // remove IPv6 zone ID (`fe80::1%lo0` => `fe80:1`) - if (strpos($addr, ':') !== false && ($pos = strpos($addr, '%')) !== false) { - $addr = substr($addr, 0, $pos); - } - - if (@inet_pton($addr) === $ip) { - foreach ($parts as $part) { - $names[] = $part; - } - } - } - - return $names; - } -} diff --git a/digital_doctor/vendor/react/dns/src/Model/Message.php b/digital_doctor/vendor/react/dns/src/Model/Message.php deleted file mode 100644 index bac2b10..0000000 --- a/digital_doctor/vendor/react/dns/src/Model/Message.php +++ /dev/null @@ -1,230 +0,0 @@ -id = self::generateId(); - $request->rd = true; - $request->questions[] = $query; - - return $request; - } - - /** - * Creates a new response message for the given query with the given answer records - * - * @param Query $query - * @param Record[] $answers - * @return self - */ - public static function createResponseWithAnswersForQuery(Query $query, array $answers) - { - $response = new Message(); - $response->id = self::generateId(); - $response->qr = true; - $response->rd = true; - - $response->questions[] = $query; - - foreach ($answers as $record) { - $response->answers[] = $record; - } - - return $response; - } - - /** - * generates a random 16 bit message ID - * - * This uses a CSPRNG so that an outside attacker that is sending spoofed - * DNS response messages can not guess the message ID to avoid possible - * cache poisoning attacks. - * - * The `random_int()` function is only available on PHP 7+ or when - * https://github.com/paragonie/random_compat is installed. As such, using - * the latest supported PHP version is highly recommended. This currently - * falls back to a less secure random number generator on older PHP versions - * in the hope that this system is properly protected against outside - * attackers, for example by using one of the common local DNS proxy stubs. - * - * @return int - * @see self::getId() - * @codeCoverageIgnore - */ - private static function generateId() - { - if (function_exists('random_int')) { - return random_int(0, 0xffff); - } - return mt_rand(0, 0xffff); - } - - /** - * The 16 bit message ID - * - * The response message ID has to match the request message ID. This allows - * the receiver to verify this is the correct response message. An outside - * attacker may try to inject fake responses by "guessing" the message ID, - * so this should use a proper CSPRNG to avoid possible cache poisoning. - * - * @var int 16 bit message ID - * @see self::generateId() - */ - public $id = 0; - - /** - * @var bool Query/Response flag, query=false or response=true - */ - public $qr = false; - - /** - * @var int specifies the kind of query (4 bit), see self::OPCODE_* constants - * @see self::OPCODE_QUERY - */ - public $opcode = self::OPCODE_QUERY; - - /** - * - * @var bool Authoritative Answer - */ - public $aa = false; - - /** - * @var bool TrunCation - */ - public $tc = false; - - /** - * @var bool Recursion Desired - */ - public $rd = false; - - /** - * @var bool Recursion Available - */ - public $ra = false; - - /** - * @var int response code (4 bit), see self::RCODE_* constants - * @see self::RCODE_OK - */ - public $rcode = Message::RCODE_OK; - - /** - * An array of Query objects - * - * ```php - * $questions = array( - * new Query( - * 'reactphp.org', - * Message::TYPE_A, - * Message::CLASS_IN - * ) - * ); - * ``` - * - * @var Query[] - */ - public $questions = array(); - - /** - * @var Record[] - */ - public $answers = array(); - - /** - * @var Record[] - */ - public $authority = array(); - - /** - * @var Record[] - */ - public $additional = array(); -} diff --git a/digital_doctor/vendor/react/dns/src/Model/Record.php b/digital_doctor/vendor/react/dns/src/Model/Record.php deleted file mode 100644 index c20403f..0000000 --- a/digital_doctor/vendor/react/dns/src/Model/Record.php +++ /dev/null @@ -1,153 +0,0 @@ -name = $name; - $this->type = $type; - $this->class = $class; - $this->ttl = $ttl; - $this->data = $data; - } -} diff --git a/digital_doctor/vendor/react/dns/src/Protocol/BinaryDumper.php b/digital_doctor/vendor/react/dns/src/Protocol/BinaryDumper.php deleted file mode 100644 index 6f4030f..0000000 --- a/digital_doctor/vendor/react/dns/src/Protocol/BinaryDumper.php +++ /dev/null @@ -1,199 +0,0 @@ -headerToBinary($message); - $data .= $this->questionToBinary($message->questions); - $data .= $this->recordsToBinary($message->answers); - $data .= $this->recordsToBinary($message->authority); - $data .= $this->recordsToBinary($message->additional); - - return $data; - } - - /** - * @param Message $message - * @return string - */ - private function headerToBinary(Message $message) - { - $data = ''; - - $data .= pack('n', $message->id); - - $flags = 0x00; - $flags = ($flags << 1) | ($message->qr ? 1 : 0); - $flags = ($flags << 4) | $message->opcode; - $flags = ($flags << 1) | ($message->aa ? 1 : 0); - $flags = ($flags << 1) | ($message->tc ? 1 : 0); - $flags = ($flags << 1) | ($message->rd ? 1 : 0); - $flags = ($flags << 1) | ($message->ra ? 1 : 0); - $flags = ($flags << 3) | 0; // skip unused zero bit - $flags = ($flags << 4) | $message->rcode; - - $data .= pack('n', $flags); - - $data .= pack('n', count($message->questions)); - $data .= pack('n', count($message->answers)); - $data .= pack('n', count($message->authority)); - $data .= pack('n', count($message->additional)); - - return $data; - } - - /** - * @param Query[] $questions - * @return string - */ - private function questionToBinary(array $questions) - { - $data = ''; - - foreach ($questions as $question) { - $data .= $this->domainNameToBinary($question->name); - $data .= pack('n*', $question->type, $question->class); - } - - return $data; - } - - /** - * @param Record[] $records - * @return string - */ - private function recordsToBinary(array $records) - { - $data = ''; - - foreach ($records as $record) { - /* @var $record Record */ - switch ($record->type) { - case Message::TYPE_A: - case Message::TYPE_AAAA: - $binary = \inet_pton($record->data); - break; - case Message::TYPE_CNAME: - case Message::TYPE_NS: - case Message::TYPE_PTR: - $binary = $this->domainNameToBinary($record->data); - break; - case Message::TYPE_TXT: - case Message::TYPE_SPF: - $binary = $this->textsToBinary($record->data); - break; - case Message::TYPE_MX: - $binary = \pack( - 'n', - $record->data['priority'] - ); - $binary .= $this->domainNameToBinary($record->data['target']); - break; - case Message::TYPE_SRV: - $binary = \pack( - 'n*', - $record->data['priority'], - $record->data['weight'], - $record->data['port'] - ); - $binary .= $this->domainNameToBinary($record->data['target']); - break; - case Message::TYPE_SOA: - $binary = $this->domainNameToBinary($record->data['mname']); - $binary .= $this->domainNameToBinary($record->data['rname']); - $binary .= \pack( - 'N*', - $record->data['serial'], - $record->data['refresh'], - $record->data['retry'], - $record->data['expire'], - $record->data['minimum'] - ); - break; - case Message::TYPE_CAA: - $binary = \pack( - 'C*', - $record->data['flag'], - \strlen($record->data['tag']) - ); - $binary .= $record->data['tag']; - $binary .= $record->data['value']; - break; - case Message::TYPE_SSHFP: - $binary = \pack( - 'CCH*', - $record->data['algorithm'], - $record->data['type'], - $record->data['fingerprint'] - ); - break; - case Message::TYPE_OPT: - $binary = ''; - foreach ($record->data as $opt => $value) { - if ($opt === Message::OPT_TCP_KEEPALIVE && $value !== null) { - $value = \pack('n', round($value * 10)); - } - $binary .= \pack('n*', $opt, \strlen((string) $value)) . $value; - } - break; - default: - // RDATA is already stored as binary value for unknown record types - $binary = $record->data; - } - - $data .= $this->domainNameToBinary($record->name); - $data .= \pack('nnNn', $record->type, $record->class, $record->ttl, \strlen($binary)); - $data .= $binary; - } - - return $data; - } - - /** - * @param string[] $texts - * @return string - */ - private function textsToBinary(array $texts) - { - $data = ''; - foreach ($texts as $text) { - $data .= \chr(\strlen($text)) . $text; - } - return $data; - } - - /** - * @param string $host - * @return string - */ - private function domainNameToBinary($host) - { - if ($host === '') { - return "\0"; - } - - // break up domain name at each dot that is not preceeded by a backslash (escaped notation) - return $this->textsToBinary( - \array_map( - 'stripcslashes', - \preg_split( - '/(?parse($data, 0); - if ($message === null) { - throw new InvalidArgumentException('Unable to parse binary message'); - } - - return $message; - } - - /** - * @param string $data - * @param int $consumed - * @return ?Message - */ - private function parse($data, $consumed) - { - if (!isset($data[12 - 1])) { - return null; - } - - list($id, $fields, $qdCount, $anCount, $nsCount, $arCount) = array_values(unpack('n*', substr($data, 0, 12))); - - $message = new Message(); - $message->id = $id; - $message->rcode = $fields & 0xf; - $message->ra = (($fields >> 7) & 1) === 1; - $message->rd = (($fields >> 8) & 1) === 1; - $message->tc = (($fields >> 9) & 1) === 1; - $message->aa = (($fields >> 10) & 1) === 1; - $message->opcode = ($fields >> 11) & 0xf; - $message->qr = (($fields >> 15) & 1) === 1; - $consumed += 12; - - // parse all questions - for ($i = $qdCount; $i > 0; --$i) { - list($question, $consumed) = $this->parseQuestion($data, $consumed); - if ($question === null) { - return null; - } else { - $message->questions[] = $question; - } - } - - // parse all answer records - for ($i = $anCount; $i > 0; --$i) { - list($record, $consumed) = $this->parseRecord($data, $consumed); - if ($record === null) { - return null; - } else { - $message->answers[] = $record; - } - } - - // parse all authority records - for ($i = $nsCount; $i > 0; --$i) { - list($record, $consumed) = $this->parseRecord($data, $consumed); - if ($record === null) { - return null; - } else { - $message->authority[] = $record; - } - } - - // parse all additional records - for ($i = $arCount; $i > 0; --$i) { - list($record, $consumed) = $this->parseRecord($data, $consumed); - if ($record === null) { - return null; - } else { - $message->additional[] = $record; - } - } - - return $message; - } - - /** - * @param string $data - * @param int $consumed - * @return array - */ - private function parseQuestion($data, $consumed) - { - list($labels, $consumed) = $this->readLabels($data, $consumed); - - if ($labels === null || !isset($data[$consumed + 4 - 1])) { - return array(null, null); - } - - list($type, $class) = array_values(unpack('n*', substr($data, $consumed, 4))); - $consumed += 4; - - return array( - new Query( - implode('.', $labels), - $type, - $class - ), - $consumed - ); - } - - /** - * @param string $data - * @param int $consumed - * @return array An array with a parsed Record on success or array with null if data is invalid/incomplete - */ - private function parseRecord($data, $consumed) - { - list($name, $consumed) = $this->readDomain($data, $consumed); - - if ($name === null || !isset($data[$consumed + 10 - 1])) { - return array(null, null); - } - - list($type, $class) = array_values(unpack('n*', substr($data, $consumed, 4))); - $consumed += 4; - - list($ttl) = array_values(unpack('N', substr($data, $consumed, 4))); - $consumed += 4; - - // TTL is a UINT32 that must not have most significant bit set for BC reasons - if ($ttl < 0 || $ttl >= 1 << 31) { - $ttl = 0; - } - - list($rdLength) = array_values(unpack('n', substr($data, $consumed, 2))); - $consumed += 2; - - if (!isset($data[$consumed + $rdLength - 1])) { - return array(null, null); - } - - $rdata = null; - $expected = $consumed + $rdLength; - - if (Message::TYPE_A === $type) { - if ($rdLength === 4) { - $rdata = inet_ntop(substr($data, $consumed, $rdLength)); - $consumed += $rdLength; - } - } elseif (Message::TYPE_AAAA === $type) { - if ($rdLength === 16) { - $rdata = inet_ntop(substr($data, $consumed, $rdLength)); - $consumed += $rdLength; - } - } elseif (Message::TYPE_CNAME === $type || Message::TYPE_PTR === $type || Message::TYPE_NS === $type) { - list($rdata, $consumed) = $this->readDomain($data, $consumed); - } elseif (Message::TYPE_TXT === $type || Message::TYPE_SPF === $type) { - $rdata = array(); - while ($consumed < $expected) { - $len = ord($data[$consumed]); - $rdata[] = (string)substr($data, $consumed + 1, $len); - $consumed += $len + 1; - } - } elseif (Message::TYPE_MX === $type) { - if ($rdLength > 2) { - list($priority) = array_values(unpack('n', substr($data, $consumed, 2))); - list($target, $consumed) = $this->readDomain($data, $consumed + 2); - - $rdata = array( - 'priority' => $priority, - 'target' => $target - ); - } - } elseif (Message::TYPE_SRV === $type) { - if ($rdLength > 6) { - list($priority, $weight, $port) = array_values(unpack('n*', substr($data, $consumed, 6))); - list($target, $consumed) = $this->readDomain($data, $consumed + 6); - - $rdata = array( - 'priority' => $priority, - 'weight' => $weight, - 'port' => $port, - 'target' => $target - ); - } - } elseif (Message::TYPE_SSHFP === $type) { - if ($rdLength > 2) { - list($algorithm, $hash) = \array_values(\unpack('C*', \substr($data, $consumed, 2))); - $fingerprint = \bin2hex(\substr($data, $consumed + 2, $rdLength - 2)); - $consumed += $rdLength; - - $rdata = array( - 'algorithm' => $algorithm, - 'type' => $hash, - 'fingerprint' => $fingerprint - ); - } - } elseif (Message::TYPE_SOA === $type) { - list($mname, $consumed) = $this->readDomain($data, $consumed); - list($rname, $consumed) = $this->readDomain($data, $consumed); - - if ($mname !== null && $rname !== null && isset($data[$consumed + 20 - 1])) { - list($serial, $refresh, $retry, $expire, $minimum) = array_values(unpack('N*', substr($data, $consumed, 20))); - $consumed += 20; - - $rdata = array( - 'mname' => $mname, - 'rname' => $rname, - 'serial' => $serial, - 'refresh' => $refresh, - 'retry' => $retry, - 'expire' => $expire, - 'minimum' => $minimum - ); - } - } elseif (Message::TYPE_OPT === $type) { - $rdata = array(); - while (isset($data[$consumed + 4 - 1])) { - list($code, $length) = array_values(unpack('n*', substr($data, $consumed, 4))); - $value = (string) substr($data, $consumed + 4, $length); - if ($code === Message::OPT_TCP_KEEPALIVE && $value === '') { - $value = null; - } elseif ($code === Message::OPT_TCP_KEEPALIVE && $length === 2) { - list($value) = array_values(unpack('n', $value)); - $value = round($value * 0.1, 1); - } elseif ($code === Message::OPT_TCP_KEEPALIVE) { - break; - } - $rdata[$code] = $value; - $consumed += 4 + $length; - } - } elseif (Message::TYPE_CAA === $type) { - if ($rdLength > 3) { - list($flag, $tagLength) = array_values(unpack('C*', substr($data, $consumed, 2))); - - if ($tagLength > 0 && $rdLength - 2 - $tagLength > 0) { - $tag = substr($data, $consumed + 2, $tagLength); - $value = substr($data, $consumed + 2 + $tagLength, $rdLength - 2 - $tagLength); - $consumed += $rdLength; - - $rdata = array( - 'flag' => $flag, - 'tag' => $tag, - 'value' => $value - ); - } - } - } else { - // unknown types simply parse rdata as an opaque binary string - $rdata = substr($data, $consumed, $rdLength); - $consumed += $rdLength; - } - - // ensure parsing record data consumes expact number of bytes indicated in record length - if ($consumed !== $expected || $rdata === null) { - return array(null, null); - } - - return array( - new Record($name, $type, $class, $ttl, $rdata), - $consumed - ); - } - - private function readDomain($data, $consumed) - { - list ($labels, $consumed) = $this->readLabels($data, $consumed); - - if ($labels === null) { - return array(null, null); - } - - // use escaped notation for each label part, then join using dots - return array( - \implode( - '.', - \array_map( - function ($label) { - return \addcslashes($label, "\0..\40.\177"); - }, - $labels - ) - ), - $consumed - ); - } - - /** - * @param string $data - * @param int $consumed - * @param int $compressionDepth maximum depth for compressed labels to avoid unreasonable recursion - * @return array - */ - private function readLabels($data, $consumed, $compressionDepth = 127) - { - $labels = array(); - - while (true) { - if (!isset($data[$consumed])) { - return array(null, null); - } - - $length = \ord($data[$consumed]); - - // end of labels reached - if ($length === 0) { - $consumed += 1; - break; - } - - // first two bits set? this is a compressed label (14 bit pointer offset) - if (($length & 0xc0) === 0xc0 && isset($data[$consumed + 1]) && $compressionDepth) { - $offset = ($length & ~0xc0) << 8 | \ord($data[$consumed + 1]); - if ($offset >= $consumed) { - return array(null, null); - } - - $consumed += 2; - list($newLabels) = $this->readLabels($data, $offset, $compressionDepth - 1); - - if ($newLabels === null) { - return array(null, null); - } - - $labels = array_merge($labels, $newLabels); - break; - } - - // length MUST be 0-63 (6 bits only) and data has to be large enough - if ($length & 0xc0 || !isset($data[$consumed + $length - 1])) { - return array(null, null); - } - - $labels[] = substr($data, $consumed + 1, $length); - $consumed += $length + 1; - } - - return array($labels, $consumed); - } -} diff --git a/digital_doctor/vendor/react/dns/src/Query/CachingExecutor.php b/digital_doctor/vendor/react/dns/src/Query/CachingExecutor.php deleted file mode 100644 index e530b24..0000000 --- a/digital_doctor/vendor/react/dns/src/Query/CachingExecutor.php +++ /dev/null @@ -1,88 +0,0 @@ -executor = $executor; - $this->cache = $cache; - } - - public function query(Query $query) - { - $id = $query->name . ':' . $query->type . ':' . $query->class; - $cache = $this->cache; - $that = $this; - $executor = $this->executor; - - $pending = $cache->get($id); - return new Promise(function ($resolve, $reject) use ($query, $id, $cache, $executor, &$pending, $that) { - $pending->then( - function ($message) use ($query, $id, $cache, $executor, &$pending, $that) { - // return cached response message on cache hit - if ($message !== null) { - return $message; - } - - // perform DNS lookup if not already cached - return $pending = $executor->query($query)->then( - function (Message $message) use ($cache, $id, $that) { - // DNS response message received => store in cache when not truncated and return - if (!$message->tc) { - $cache->set($id, $message, $that->ttl($message)); - } - - return $message; - } - ); - } - )->then($resolve, function ($e) use ($reject, &$pending) { - $reject($e); - $pending = null; - }); - }, function ($_, $reject) use (&$pending, $query) { - $reject(new \RuntimeException('DNS query for ' . $query->describe() . ' has been cancelled')); - $pending->cancel(); - $pending = null; - }); - } - - /** - * @param Message $message - * @return int - * @internal - */ - public function ttl(Message $message) - { - // select TTL from answers (should all be the same), use smallest value if available - // @link https://tools.ietf.org/html/rfc2181#section-5.2 - $ttl = null; - foreach ($message->answers as $answer) { - if ($ttl === null || $answer->ttl < $ttl) { - $ttl = $answer->ttl; - } - } - - if ($ttl === null) { - $ttl = self::TTL; - } - - return $ttl; - } -} diff --git a/digital_doctor/vendor/react/dns/src/Query/CancellationException.php b/digital_doctor/vendor/react/dns/src/Query/CancellationException.php deleted file mode 100644 index 5432b36..0000000 --- a/digital_doctor/vendor/react/dns/src/Query/CancellationException.php +++ /dev/null @@ -1,7 +0,0 @@ -executor = $base; - } - - public function query(Query $query) - { - $key = $this->serializeQueryToIdentity($query); - if (isset($this->pending[$key])) { - // same query is already pending, so use shared reference to pending query - $promise = $this->pending[$key]; - ++$this->counts[$key]; - } else { - // no such query pending, so start new query and keep reference until it's fulfilled or rejected - $promise = $this->executor->query($query); - $this->pending[$key] = $promise; - $this->counts[$key] = 1; - - $pending =& $this->pending; - $counts =& $this->counts; - $promise->then(function () use ($key, &$pending, &$counts) { - unset($pending[$key], $counts[$key]); - }, function () use ($key, &$pending, &$counts) { - unset($pending[$key], $counts[$key]); - }); - } - - // Return a child promise awaiting the pending query. - // Cancelling this child promise should only cancel the pending query - // when no other child promise is awaiting the same query. - $pending =& $this->pending; - $counts =& $this->counts; - return new Promise(function ($resolve, $reject) use ($promise) { - $promise->then($resolve, $reject); - }, function () use (&$promise, $key, $query, &$pending, &$counts) { - if (--$counts[$key] < 1) { - unset($pending[$key], $counts[$key]); - $promise->cancel(); - $promise = null; - } - throw new \RuntimeException('DNS query for ' . $query->describe() . ' has been cancelled'); - }); - } - - private function serializeQueryToIdentity(Query $query) - { - return sprintf('%s:%s:%s', $query->name, $query->type, $query->class); - } -} diff --git a/digital_doctor/vendor/react/dns/src/Query/ExecutorInterface.php b/digital_doctor/vendor/react/dns/src/Query/ExecutorInterface.php deleted file mode 100644 index 0bc3945..0000000 --- a/digital_doctor/vendor/react/dns/src/Query/ExecutorInterface.php +++ /dev/null @@ -1,43 +0,0 @@ -query($query)->then( - * function (React\Dns\Model\Message $response) { - * // response message successfully received - * var_dump($response->rcode, $response->answers); - * }, - * function (Exception $error) { - * // failed to query due to $error - * } - * ); - * ``` - * - * The returned Promise MUST be implemented in such a way that it can be - * cancelled when it is still pending. Cancelling a pending promise MUST - * reject its value with an Exception. It SHOULD clean up any underlying - * resources and references as applicable. - * - * ```php - * $promise = $executor->query($query); - * - * $promise->cancel(); - * ``` - * - * @param Query $query - * @return \React\Promise\PromiseInterface<\React\Dns\Model\Message> - * resolves with response message on success or rejects with an Exception on error - */ - public function query(Query $query); -} diff --git a/digital_doctor/vendor/react/dns/src/Query/FallbackExecutor.php b/digital_doctor/vendor/react/dns/src/Query/FallbackExecutor.php deleted file mode 100644 index 83bd360..0000000 --- a/digital_doctor/vendor/react/dns/src/Query/FallbackExecutor.php +++ /dev/null @@ -1,49 +0,0 @@ -executor = $executor; - $this->fallback = $fallback; - } - - public function query(Query $query) - { - $cancelled = false; - $fallback = $this->fallback; - $promise = $this->executor->query($query); - - return new Promise(function ($resolve, $reject) use (&$promise, $fallback, $query, &$cancelled) { - $promise->then($resolve, function (\Exception $e1) use ($fallback, $query, $resolve, $reject, &$cancelled, &$promise) { - // reject if primary resolution rejected due to cancellation - if ($cancelled) { - $reject($e1); - return; - } - - // start fallback query if primary query rejected - $promise = $fallback->query($query)->then($resolve, function (\Exception $e2) use ($e1, $reject) { - $append = $e2->getMessage(); - if (($pos = strpos($append, ':')) !== false) { - $append = substr($append, $pos + 2); - } - - // reject with combined error message if both queries fail - $reject(new \RuntimeException($e1->getMessage() . '. ' . $append)); - }); - }); - }, function () use (&$promise, &$cancelled) { - // cancel pending query (primary or fallback) - $cancelled = true; - $promise->cancel(); - }); - } -} diff --git a/digital_doctor/vendor/react/dns/src/Query/HostsFileExecutor.php b/digital_doctor/vendor/react/dns/src/Query/HostsFileExecutor.php deleted file mode 100644 index d6e2d93..0000000 --- a/digital_doctor/vendor/react/dns/src/Query/HostsFileExecutor.php +++ /dev/null @@ -1,89 +0,0 @@ -hosts = $hosts; - $this->fallback = $fallback; - } - - public function query(Query $query) - { - if ($query->class === Message::CLASS_IN && ($query->type === Message::TYPE_A || $query->type === Message::TYPE_AAAA)) { - // forward lookup for type A or AAAA - $records = array(); - $expectsColon = $query->type === Message::TYPE_AAAA; - foreach ($this->hosts->getIpsForHost($query->name) as $ip) { - // ensure this is an IPv4/IPV6 address according to query type - if ((strpos($ip, ':') !== false) === $expectsColon) { - $records[] = new Record($query->name, $query->type, $query->class, 0, $ip); - } - } - - if ($records) { - return Promise\resolve( - Message::createResponseWithAnswersForQuery($query, $records) - ); - } - } elseif ($query->class === Message::CLASS_IN && $query->type === Message::TYPE_PTR) { - // reverse lookup: extract IPv4 or IPv6 from special `.arpa` domain - $ip = $this->getIpFromHost($query->name); - - if ($ip !== null) { - $records = array(); - foreach ($this->hosts->getHostsForIp($ip) as $host) { - $records[] = new Record($query->name, $query->type, $query->class, 0, $host); - } - - if ($records) { - return Promise\resolve( - Message::createResponseWithAnswersForQuery($query, $records) - ); - } - } - } - - return $this->fallback->query($query); - } - - private function getIpFromHost($host) - { - if (substr($host, -13) === '.in-addr.arpa') { - // IPv4: read as IP and reverse bytes - $ip = @inet_pton(substr($host, 0, -13)); - if ($ip === false || isset($ip[4])) { - return null; - } - - return inet_ntop(strrev($ip)); - } elseif (substr($host, -9) === '.ip6.arpa') { - // IPv6: replace dots, reverse nibbles and interpret as hexadecimal string - $ip = @inet_ntop(pack('H*', strrev(str_replace('.', '', substr($host, 0, -9))))); - if ($ip === false) { - return null; - } - - return $ip; - } else { - return null; - } - } -} diff --git a/digital_doctor/vendor/react/dns/src/Query/Query.php b/digital_doctor/vendor/react/dns/src/Query/Query.php deleted file mode 100644 index a3dcfb5..0000000 --- a/digital_doctor/vendor/react/dns/src/Query/Query.php +++ /dev/null @@ -1,69 +0,0 @@ -name = $name; - $this->type = $type; - $this->class = $class; - } - - /** - * Describes the hostname and query type/class for this query - * - * The output format is supposed to be human readable and is subject to change. - * The format is inspired by RFC 3597 when handling unkown types/classes. - * - * @return string "example.com (A)" or "example.com (CLASS0 TYPE1234)" - * @link https://tools.ietf.org/html/rfc3597 - */ - public function describe() - { - $class = $this->class !== Message::CLASS_IN ? 'CLASS' . $this->class . ' ' : ''; - - $type = 'TYPE' . $this->type; - $ref = new \ReflectionClass('React\Dns\Model\Message'); - foreach ($ref->getConstants() as $name => $value) { - if ($value === $this->type && \strpos($name, 'TYPE_') === 0) { - $type = \substr($name, 5); - break; - } - } - - return $this->name . ' (' . $class . $type . ')'; - } -} diff --git a/digital_doctor/vendor/react/dns/src/Query/RetryExecutor.php b/digital_doctor/vendor/react/dns/src/Query/RetryExecutor.php deleted file mode 100644 index 880609b..0000000 --- a/digital_doctor/vendor/react/dns/src/Query/RetryExecutor.php +++ /dev/null @@ -1,85 +0,0 @@ -executor = $executor; - $this->retries = $retries; - } - - public function query(Query $query) - { - return $this->tryQuery($query, $this->retries); - } - - public function tryQuery(Query $query, $retries) - { - $deferred = new Deferred(function () use (&$promise) { - if ($promise instanceof PromiseInterface && \method_exists($promise, 'cancel')) { - $promise->cancel(); - } - }); - - $success = function ($value) use ($deferred, &$errorback) { - $errorback = null; - $deferred->resolve($value); - }; - - $executor = $this->executor; - $errorback = function ($e) use ($deferred, &$promise, $query, $success, &$errorback, &$retries, $executor) { - if (!$e instanceof TimeoutException) { - $errorback = null; - $deferred->reject($e); - } elseif ($retries <= 0) { - $errorback = null; - $deferred->reject($e = new \RuntimeException( - 'DNS query for ' . $query->describe() . ' failed: too many retries', - 0, - $e - )); - - // avoid garbage references by replacing all closures in call stack. - // what a lovely piece of code! - $r = new \ReflectionProperty('Exception', 'trace'); - $r->setAccessible(true); - $trace = $r->getValue($e); - - // Exception trace arguments are not available on some PHP 7.4 installs - // @codeCoverageIgnoreStart - foreach ($trace as $ti => $one) { - if (isset($one['args'])) { - foreach ($one['args'] as $ai => $arg) { - if ($arg instanceof \Closure) { - $trace[$ti]['args'][$ai] = 'Object(' . \get_class($arg) . ')'; - } - } - } - } - // @codeCoverageIgnoreEnd - $r->setValue($e, $trace); - } else { - --$retries; - $promise = $executor->query($query)->then( - $success, - $errorback - ); - } - }; - - $promise = $this->executor->query($query)->then( - $success, - $errorback - ); - - return $deferred->promise(); - } -} diff --git a/digital_doctor/vendor/react/dns/src/Query/SelectiveTransportExecutor.php b/digital_doctor/vendor/react/dns/src/Query/SelectiveTransportExecutor.php deleted file mode 100644 index 0f0ca5d..0000000 --- a/digital_doctor/vendor/react/dns/src/Query/SelectiveTransportExecutor.php +++ /dev/null @@ -1,85 +0,0 @@ -query( - * new Query($name, Message::TYPE_AAAA, Message::CLASS_IN) - * )->then(function (Message $message) { - * foreach ($message->answers as $answer) { - * echo 'IPv6: ' . $answer->data . PHP_EOL; - * } - * }, 'printf'); - * ``` - * - * Note that this executor only implements the logic to select the correct - * transport for the given DNS query. Implementing the correct transport logic, - * implementing timeouts and any retry logic is left up to the given executors, - * see also [`UdpTransportExecutor`](#udptransportexecutor) and - * [`TcpTransportExecutor`](#tcptransportexecutor) for more details. - * - * Note that this executor is entirely async and as such allows you to execute - * any number of queries concurrently. You should probably limit the number of - * concurrent queries in your application or you're very likely going to face - * rate limitations and bans on the resolver end. For many common applications, - * you may want to avoid sending the same query multiple times when the first - * one is still pending, so you will likely want to use this in combination with - * a `CoopExecutor` like this: - * - * ```php - * $executor = new CoopExecutor( - * new SelectiveTransportExecutor( - * $datagramExecutor, - * $streamExecutor - * ) - * ); - * ``` - */ -class SelectiveTransportExecutor implements ExecutorInterface -{ - private $datagramExecutor; - private $streamExecutor; - - public function __construct(ExecutorInterface $datagramExecutor, ExecutorInterface $streamExecutor) - { - $this->datagramExecutor = $datagramExecutor; - $this->streamExecutor = $streamExecutor; - } - - public function query(Query $query) - { - $stream = $this->streamExecutor; - $pending = $this->datagramExecutor->query($query); - - return new Promise(function ($resolve, $reject) use (&$pending, $stream, $query) { - $pending->then( - $resolve, - function ($e) use (&$pending, $stream, $query, $resolve, $reject) { - if ($e->getCode() === (\defined('SOCKET_EMSGSIZE') ? \SOCKET_EMSGSIZE : 90)) { - $pending = $stream->query($query)->then($resolve, $reject); - } else { - $reject($e); - } - } - ); - }, function () use (&$pending) { - $pending->cancel(); - $pending = null; - }); - } -} diff --git a/digital_doctor/vendor/react/dns/src/Query/TcpTransportExecutor.php b/digital_doctor/vendor/react/dns/src/Query/TcpTransportExecutor.php deleted file mode 100644 index 669fd01..0000000 --- a/digital_doctor/vendor/react/dns/src/Query/TcpTransportExecutor.php +++ /dev/null @@ -1,382 +0,0 @@ -query( - * new Query($name, Message::TYPE_AAAA, Message::CLASS_IN) - * )->then(function (Message $message) { - * foreach ($message->answers as $answer) { - * echo 'IPv6: ' . $answer->data . PHP_EOL; - * } - * }, 'printf'); - * ``` - * - * See also [example #92](examples). - * - * Note that this executor does not implement a timeout, so you will very likely - * want to use this in combination with a `TimeoutExecutor` like this: - * - * ```php - * $executor = new TimeoutExecutor( - * new TcpTransportExecutor($nameserver), - * 3.0 - * ); - * ``` - * - * Unlike the `UdpTransportExecutor`, this class uses a reliable TCP/IP - * transport, so you do not necessarily have to implement any retry logic. - * - * Note that this executor is entirely async and as such allows you to execute - * queries concurrently. The first query will establish a TCP/IP socket - * connection to the DNS server which will be kept open for a short period. - * Additional queries will automatically reuse this existing socket connection - * to the DNS server, will pipeline multiple requests over this single - * connection and will keep an idle connection open for a short period. The - * initial TCP/IP connection overhead may incur a slight delay if you only send - * occasional queries – when sending a larger number of concurrent queries over - * an existing connection, it becomes increasingly more efficient and avoids - * creating many concurrent sockets like the UDP-based executor. You may still - * want to limit the number of (concurrent) queries in your application or you - * may be facing rate limitations and bans on the resolver end. For many common - * applications, you may want to avoid sending the same query multiple times - * when the first one is still pending, so you will likely want to use this in - * combination with a `CoopExecutor` like this: - * - * ```php - * $executor = new CoopExecutor( - * new TimeoutExecutor( - * new TcpTransportExecutor($nameserver), - * 3.0 - * ) - * ); - * ``` - * - * > Internally, this class uses PHP's TCP/IP sockets and does not take advantage - * of [react/socket](https://github.com/reactphp/socket) purely for - * organizational reasons to avoid a cyclic dependency between the two - * packages. Higher-level components should take advantage of the Socket - * component instead of reimplementing this socket logic from scratch. - */ -class TcpTransportExecutor implements ExecutorInterface -{ - private $nameserver; - private $loop; - private $parser; - private $dumper; - - /** - * @var ?resource - */ - private $socket; - - /** - * @var Deferred[] - */ - private $pending = array(); - - /** - * @var string[] - */ - private $names = array(); - - /** - * Maximum idle time when socket is current unused (i.e. no pending queries outstanding) - * - * If a new query is to be sent during the idle period, we can reuse the - * existing socket without having to wait for a new socket connection. - * This uses a rather small, hard-coded value to not keep any unneeded - * sockets open and to not keep the loop busy longer than needed. - * - * A future implementation may take advantage of `edns-tcp-keepalive` to keep - * the socket open for longer periods. This will likely require explicit - * configuration because this may consume additional resources and also keep - * the loop busy for longer than expected in some applications. - * - * @var float - * @link https://tools.ietf.org/html/rfc7766#section-6.2.1 - * @link https://tools.ietf.org/html/rfc7828 - */ - private $idlePeriod = 0.001; - - /** - * @var ?\React\EventLoop\TimerInterface - */ - private $idleTimer; - - private $writeBuffer = ''; - private $writePending = false; - - private $readBuffer = ''; - private $readPending = false; - - /** @var string */ - private $readChunk = 0xffff; - - /** - * @param string $nameserver - * @param ?LoopInterface $loop - */ - public function __construct($nameserver, $loop = null) - { - if (\strpos($nameserver, '[') === false && \substr_count($nameserver, ':') >= 2 && \strpos($nameserver, '://') === false) { - // several colons, but not enclosed in square brackets => enclose IPv6 address in square brackets - $nameserver = '[' . $nameserver . ']'; - } - - $parts = \parse_url((\strpos($nameserver, '://') === false ? 'tcp://' : '') . $nameserver); - if (!isset($parts['scheme'], $parts['host']) || $parts['scheme'] !== 'tcp' || @\inet_pton(\trim($parts['host'], '[]')) === false) { - throw new \InvalidArgumentException('Invalid nameserver address given'); - } - - if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 - throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface'); - } - - $this->nameserver = 'tcp://' . $parts['host'] . ':' . (isset($parts['port']) ? $parts['port'] : 53); - $this->loop = $loop ?: Loop::get(); - $this->parser = new Parser(); - $this->dumper = new BinaryDumper(); - } - - public function query(Query $query) - { - $request = Message::createRequestForQuery($query); - - // keep shuffing message ID to avoid using the same message ID for two pending queries at the same time - while (isset($this->pending[$request->id])) { - $request->id = \mt_rand(0, 0xffff); // @codeCoverageIgnore - } - - $queryData = $this->dumper->toBinary($request); - $length = \strlen($queryData); - if ($length > 0xffff) { - return \React\Promise\reject(new \RuntimeException( - 'DNS query for ' . $query->describe() . ' failed: Query too large for TCP transport' - )); - } - - $queryData = \pack('n', $length) . $queryData; - - if ($this->socket === null) { - // create async TCP/IP connection (may take a while) - $socket = @\stream_socket_client($this->nameserver, $errno, $errstr, 0, \STREAM_CLIENT_CONNECT | \STREAM_CLIENT_ASYNC_CONNECT); - if ($socket === false) { - return \React\Promise\reject(new \RuntimeException( - 'DNS query for ' . $query->describe() . ' failed: Unable to connect to DNS server ' . $this->nameserver . ' (' . $errstr . ')', - $errno - )); - } - - // set socket to non-blocking and wait for it to become writable (connection success/rejected) - \stream_set_blocking($socket, false); - if (\function_exists('stream_set_chunk_size')) { - \stream_set_chunk_size($socket, $this->readChunk); // @codeCoverageIgnore - } - $this->socket = $socket; - } - - if ($this->idleTimer !== null) { - $this->loop->cancelTimer($this->idleTimer); - $this->idleTimer = null; - } - - // wait for socket to become writable to actually write out data - $this->writeBuffer .= $queryData; - if (!$this->writePending) { - $this->writePending = true; - $this->loop->addWriteStream($this->socket, array($this, 'handleWritable')); - } - - $names =& $this->names; - $that = $this; - $deferred = new Deferred(function () use ($that, &$names, $request) { - // remove from list of pending names, but remember pending query - $name = $names[$request->id]; - unset($names[$request->id]); - $that->checkIdle(); - - throw new CancellationException('DNS query for ' . $name . ' has been cancelled'); - }); - - $this->pending[$request->id] = $deferred; - $this->names[$request->id] = $query->describe(); - - return $deferred->promise(); - } - - /** - * @internal - */ - public function handleWritable() - { - if ($this->readPending === false) { - $name = @\stream_socket_get_name($this->socket, true); - if ($name === false) { - // Connection failed? Check socket error if available for underlying errno/errstr. - // @codeCoverageIgnoreStart - if (\function_exists('socket_import_stream')) { - $socket = \socket_import_stream($this->socket); - $errno = \socket_get_option($socket, \SOL_SOCKET, \SO_ERROR); - $errstr = \socket_strerror($errno); - } else { - $errno = \defined('SOCKET_ECONNREFUSED') ? \SOCKET_ECONNREFUSED : 111; - $errstr = 'Connection refused'; - } - // @codeCoverageIgnoreEnd - - $this->closeError('Unable to connect to DNS server ' . $this->nameserver . ' (' . $errstr . ')', $errno); - return; - } - - $this->readPending = true; - $this->loop->addReadStream($this->socket, array($this, 'handleRead')); - } - - $errno = 0; - $errstr = ''; - \set_error_handler(function ($_, $error) use (&$errno, &$errstr) { - // Match errstr from PHP's warning message. - // fwrite(): Send of 327712 bytes failed with errno=32 Broken pipe - \preg_match('/errno=(\d+) (.+)/', $error, $m); - $errno = isset($m[1]) ? (int) $m[1] : 0; - $errstr = isset($m[2]) ? $m[2] : $error; - }); - - $written = \fwrite($this->socket, $this->writeBuffer); - - \restore_error_handler(); - - if ($written === false || $written === 0) { - $this->closeError( - 'Unable to send query to DNS server ' . $this->nameserver . ' (' . $errstr . ')', - $errno - ); - return; - } - - if (isset($this->writeBuffer[$written])) { - $this->writeBuffer = \substr($this->writeBuffer, $written); - } else { - $this->loop->removeWriteStream($this->socket); - $this->writePending = false; - $this->writeBuffer = ''; - } - } - - /** - * @internal - */ - public function handleRead() - { - // read one chunk of data from the DNS server - // any error is fatal, this is a stream of TCP/IP data - $chunk = @\fread($this->socket, $this->readChunk); - if ($chunk === false || $chunk === '') { - $this->closeError('Connection to DNS server ' . $this->nameserver . ' lost'); - return; - } - - // reassemble complete message by concatenating all chunks. - $this->readBuffer .= $chunk; - - // response message header contains at least 12 bytes - while (isset($this->readBuffer[11])) { - // read response message length from first 2 bytes and ensure we have length + data in buffer - list(, $length) = \unpack('n', $this->readBuffer); - if (!isset($this->readBuffer[$length + 1])) { - return; - } - - $data = \substr($this->readBuffer, 2, $length); - $this->readBuffer = (string)substr($this->readBuffer, $length + 2); - - try { - $response = $this->parser->parseMessage($data); - } catch (\Exception $e) { - // reject all pending queries if we received an invalid message from remote server - $this->closeError('Invalid message received from DNS server ' . $this->nameserver); - return; - } - - // reject all pending queries if we received an unexpected response ID or truncated response - if (!isset($this->pending[$response->id]) || $response->tc) { - $this->closeError('Invalid response message received from DNS server ' . $this->nameserver); - return; - } - - $deferred = $this->pending[$response->id]; - unset($this->pending[$response->id], $this->names[$response->id]); - - $deferred->resolve($response); - - $this->checkIdle(); - } - } - - /** - * @internal - * @param string $reason - * @param int $code - */ - public function closeError($reason, $code = 0) - { - $this->readBuffer = ''; - if ($this->readPending) { - $this->loop->removeReadStream($this->socket); - $this->readPending = false; - } - - $this->writeBuffer = ''; - if ($this->writePending) { - $this->loop->removeWriteStream($this->socket); - $this->writePending = false; - } - - if ($this->idleTimer !== null) { - $this->loop->cancelTimer($this->idleTimer); - $this->idleTimer = null; - } - - @\fclose($this->socket); - $this->socket = null; - - foreach ($this->names as $id => $name) { - $this->pending[$id]->reject(new \RuntimeException( - 'DNS query for ' . $name . ' failed: ' . $reason, - $code - )); - } - $this->pending = $this->names = array(); - } - - /** - * @internal - */ - public function checkIdle() - { - if ($this->idleTimer === null && !$this->names) { - $that = $this; - $this->idleTimer = $this->loop->addTimer($this->idlePeriod, function () use ($that) { - $that->closeError('Idle timeout'); - }); - } - } -} diff --git a/digital_doctor/vendor/react/dns/src/Query/TimeoutException.php b/digital_doctor/vendor/react/dns/src/Query/TimeoutException.php deleted file mode 100644 index 109b0a9..0000000 --- a/digital_doctor/vendor/react/dns/src/Query/TimeoutException.php +++ /dev/null @@ -1,7 +0,0 @@ -executor = $executor; - $this->loop = $loop ?: Loop::get(); - $this->timeout = $timeout; - } - - public function query(Query $query) - { - $promise = $this->executor->query($query); - - $loop = $this->loop; - $time = $this->timeout; - return new Promise(function ($resolve, $reject) use ($loop, $time, $promise, $query) { - $timer = null; - $promise = $promise->then(function ($v) use (&$timer, $loop, $resolve) { - if ($timer) { - $loop->cancelTimer($timer); - } - $timer = false; - $resolve($v); - }, function ($v) use (&$timer, $loop, $reject) { - if ($timer) { - $loop->cancelTimer($timer); - } - $timer = false; - $reject($v); - }); - - // promise already resolved => no need to start timer - if ($timer === false) { - return; - } - - // start timeout timer which will cancel the pending promise - $timer = $loop->addTimer($time, function () use ($time, &$promise, $reject, $query) { - $reject(new TimeoutException( - 'DNS query for ' . $query->describe() . ' timed out' - )); - - // Cancel pending query to clean up any underlying resources and references. - // Avoid garbage references in call stack by passing pending promise by reference. - assert(\method_exists($promise, 'cancel')); - $promise->cancel(); - $promise = null; - }); - }, function () use (&$promise) { - // Cancelling this promise will cancel the pending query, thus triggering the rejection logic above. - // Avoid garbage references in call stack by passing pending promise by reference. - assert(\method_exists($promise, 'cancel')); - $promise->cancel(); - $promise = null; - }); - } -} diff --git a/digital_doctor/vendor/react/dns/src/Query/UdpTransportExecutor.php b/digital_doctor/vendor/react/dns/src/Query/UdpTransportExecutor.php deleted file mode 100644 index a8cbfaf..0000000 --- a/digital_doctor/vendor/react/dns/src/Query/UdpTransportExecutor.php +++ /dev/null @@ -1,221 +0,0 @@ -query( - * new Query($name, Message::TYPE_AAAA, Message::CLASS_IN) - * )->then(function (Message $message) { - * foreach ($message->answers as $answer) { - * echo 'IPv6: ' . $answer->data . PHP_EOL; - * } - * }, 'printf'); - * ``` - * - * See also the [fourth example](examples). - * - * Note that this executor does not implement a timeout, so you will very likely - * want to use this in combination with a `TimeoutExecutor` like this: - * - * ```php - * $executor = new TimeoutExecutor( - * new UdpTransportExecutor($nameserver), - * 3.0 - * ); - * ``` - * - * Also note that this executor uses an unreliable UDP transport and that it - * does not implement any retry logic, so you will likely want to use this in - * combination with a `RetryExecutor` like this: - * - * ```php - * $executor = new RetryExecutor( - * new TimeoutExecutor( - * new UdpTransportExecutor($nameserver), - * 3.0 - * ) - * ); - * ``` - * - * Note that this executor is entirely async and as such allows you to execute - * any number of queries concurrently. You should probably limit the number of - * concurrent queries in your application or you're very likely going to face - * rate limitations and bans on the resolver end. For many common applications, - * you may want to avoid sending the same query multiple times when the first - * one is still pending, so you will likely want to use this in combination with - * a `CoopExecutor` like this: - * - * ```php - * $executor = new CoopExecutor( - * new RetryExecutor( - * new TimeoutExecutor( - * new UdpTransportExecutor($nameserver), - * 3.0 - * ) - * ) - * ); - * ``` - * - * > Internally, this class uses PHP's UDP sockets and does not take advantage - * of [react/datagram](https://github.com/reactphp/datagram) purely for - * organizational reasons to avoid a cyclic dependency between the two - * packages. Higher-level components should take advantage of the Datagram - * component instead of reimplementing this socket logic from scratch. - */ -final class UdpTransportExecutor implements ExecutorInterface -{ - private $nameserver; - private $loop; - private $parser; - private $dumper; - - /** - * maximum UDP packet size to send and receive - * - * @var int - */ - private $maxPacketSize = 512; - - /** - * @param string $nameserver - * @param ?LoopInterface $loop - */ - public function __construct($nameserver, $loop = null) - { - if (\strpos($nameserver, '[') === false && \substr_count($nameserver, ':') >= 2 && \strpos($nameserver, '://') === false) { - // several colons, but not enclosed in square brackets => enclose IPv6 address in square brackets - $nameserver = '[' . $nameserver . ']'; - } - - $parts = \parse_url((\strpos($nameserver, '://') === false ? 'udp://' : '') . $nameserver); - if (!isset($parts['scheme'], $parts['host']) || $parts['scheme'] !== 'udp' || @\inet_pton(\trim($parts['host'], '[]')) === false) { - throw new \InvalidArgumentException('Invalid nameserver address given'); - } - - if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 - throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface'); - } - - $this->nameserver = 'udp://' . $parts['host'] . ':' . (isset($parts['port']) ? $parts['port'] : 53); - $this->loop = $loop ?: Loop::get(); - $this->parser = new Parser(); - $this->dumper = new BinaryDumper(); - } - - public function query(Query $query) - { - $request = Message::createRequestForQuery($query); - - $queryData = $this->dumper->toBinary($request); - if (isset($queryData[$this->maxPacketSize])) { - return \React\Promise\reject(new \RuntimeException( - 'DNS query for ' . $query->describe() . ' failed: Query too large for UDP transport', - \defined('SOCKET_EMSGSIZE') ? \SOCKET_EMSGSIZE : 90 - )); - } - - // UDP connections are instant, so try connection without a loop or timeout - $errno = 0; - $errstr = ''; - $socket = @\stream_socket_client($this->nameserver, $errno, $errstr, 0); - if ($socket === false) { - return \React\Promise\reject(new \RuntimeException( - 'DNS query for ' . $query->describe() . ' failed: Unable to connect to DNS server ' . $this->nameserver . ' (' . $errstr . ')', - $errno - )); - } - - // set socket to non-blocking and immediately try to send (fill write buffer) - \stream_set_blocking($socket, false); - - \set_error_handler(function ($_, $error) use (&$errno, &$errstr) { - // Write may potentially fail, but most common errors are already caught by connection check above. - // Among others, macOS is known to report here when trying to send to broadcast address. - // This can also be reproduced by writing data exceeding `stream_set_chunk_size()` to a server refusing UDP data. - // fwrite(): send of 8192 bytes failed with errno=111 Connection refused - \preg_match('/errno=(\d+) (.+)/', $error, $m); - $errno = isset($m[1]) ? (int) $m[1] : 0; - $errstr = isset($m[2]) ? $m[2] : $error; - }); - - $written = \fwrite($socket, $queryData); - - \restore_error_handler(); - - if ($written !== \strlen($queryData)) { - return \React\Promise\reject(new \RuntimeException( - 'DNS query for ' . $query->describe() . ' failed: Unable to send query to DNS server ' . $this->nameserver . ' (' . $errstr . ')', - $errno - )); - } - - $loop = $this->loop; - $deferred = new Deferred(function () use ($loop, $socket, $query) { - // cancellation should remove socket from loop and close socket - $loop->removeReadStream($socket); - \fclose($socket); - - throw new CancellationException('DNS query for ' . $query->describe() . ' has been cancelled'); - }); - - $max = $this->maxPacketSize; - $parser = $this->parser; - $nameserver = $this->nameserver; - $loop->addReadStream($socket, function ($socket) use ($loop, $deferred, $query, $parser, $request, $max, $nameserver) { - // try to read a single data packet from the DNS server - // ignoring any errors, this is uses UDP packets and not a stream of data - $data = @\fread($socket, $max); - if ($data === false) { - return; - } - - try { - $response = $parser->parseMessage($data); - } catch (\Exception $e) { - // ignore and await next if we received an invalid message from remote server - // this may as well be a fake response from an attacker (possible DOS) - return; - } - - // ignore and await next if we received an unexpected response ID - // this may as well be a fake response from an attacker (possible cache poisoning) - if ($response->id !== $request->id) { - return; - } - - // we only react to the first valid message, so remove socket from loop and close - $loop->removeReadStream($socket); - \fclose($socket); - - if ($response->tc) { - $deferred->reject(new \RuntimeException( - 'DNS query for ' . $query->describe() . ' failed: The DNS server ' . $nameserver . ' returned a truncated result for a UDP query', - \defined('SOCKET_EMSGSIZE') ? \SOCKET_EMSGSIZE : 90 - )); - return; - } - - $deferred->resolve($response); - }); - - return $deferred->promise(); - } -} diff --git a/digital_doctor/vendor/react/dns/src/RecordNotFoundException.php b/digital_doctor/vendor/react/dns/src/RecordNotFoundException.php deleted file mode 100644 index 3b70274..0000000 --- a/digital_doctor/vendor/react/dns/src/RecordNotFoundException.php +++ /dev/null @@ -1,7 +0,0 @@ -decorateHostsFileExecutor($this->createExecutor($config, $loop ?: Loop::get())); - - return new Resolver($executor); - } - - /** - * Creates a cached DNS resolver instance for the given DNS config and cache - * - * As of v1.7.0 it's recommended to pass a `Config` object instead of a - * single nameserver address. If the given config contains more than one DNS - * nameserver, all DNS nameservers will be used in order. The primary DNS - * server will always be used first before falling back to the secondary or - * tertiary DNS server. - * - * @param Config|string $config DNS Config object (recommended) or single nameserver address - * @param ?LoopInterface $loop - * @param ?CacheInterface $cache - * @return \React\Dns\Resolver\ResolverInterface - * @throws \InvalidArgumentException for invalid DNS server address - * @throws \UnderflowException when given DNS Config object has an empty list of nameservers - */ - public function createCached($config, $loop = null, $cache = null) - { - if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 - throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface'); - } - - if ($cache !== null && !$cache instanceof CacheInterface) { // manual type check to support legacy PHP < 7.1 - throw new \InvalidArgumentException('Argument #3 ($cache) expected null|React\Cache\CacheInterface'); - } - - // default to keeping maximum of 256 responses in cache unless explicitly given - if (!($cache instanceof CacheInterface)) { - $cache = new ArrayCache(256); - } - - $executor = $this->createExecutor($config, $loop ?: Loop::get()); - $executor = new CachingExecutor($executor, $cache); - $executor = $this->decorateHostsFileExecutor($executor); - - return new Resolver($executor); - } - - /** - * Tries to load the hosts file and decorates the given executor on success - * - * @param ExecutorInterface $executor - * @return ExecutorInterface - * @codeCoverageIgnore - */ - private function decorateHostsFileExecutor(ExecutorInterface $executor) - { - try { - $executor = new HostsFileExecutor( - HostsFile::loadFromPathBlocking(), - $executor - ); - } catch (\RuntimeException $e) { - // ignore this file if it can not be loaded - } - - // Windows does not store localhost in hosts file by default but handles this internally - // To compensate for this, we explicitly use hard-coded defaults for localhost - if (DIRECTORY_SEPARATOR === '\\') { - $executor = new HostsFileExecutor( - new HostsFile("127.0.0.1 localhost\n::1 localhost"), - $executor - ); - } - - return $executor; - } - - /** - * @param Config|string $nameserver - * @param LoopInterface $loop - * @return CoopExecutor - * @throws \InvalidArgumentException for invalid DNS server address - * @throws \UnderflowException when given DNS Config object has an empty list of nameservers - */ - private function createExecutor($nameserver, LoopInterface $loop) - { - if ($nameserver instanceof Config) { - if (!$nameserver->nameservers) { - throw new \UnderflowException('Empty config with no DNS servers'); - } - - // Hard-coded to check up to 3 DNS servers to match default limits in place in most systems (see MAXNS config). - // Note to future self: Recursion isn't too hard, but how deep do we really want to go? - $primary = reset($nameserver->nameservers); - $secondary = next($nameserver->nameservers); - $tertiary = next($nameserver->nameservers); - - if ($tertiary !== false) { - // 3 DNS servers given => nest first with fallback for second and third - return new CoopExecutor( - new RetryExecutor( - new FallbackExecutor( - $this->createSingleExecutor($primary, $loop), - new FallbackExecutor( - $this->createSingleExecutor($secondary, $loop), - $this->createSingleExecutor($tertiary, $loop) - ) - ) - ) - ); - } elseif ($secondary !== false) { - // 2 DNS servers given => fallback from first to second - return new CoopExecutor( - new RetryExecutor( - new FallbackExecutor( - $this->createSingleExecutor($primary, $loop), - $this->createSingleExecutor($secondary, $loop) - ) - ) - ); - } else { - // 1 DNS server given => use single executor - $nameserver = $primary; - } - } - - return new CoopExecutor(new RetryExecutor($this->createSingleExecutor($nameserver, $loop))); - } - - /** - * @param string $nameserver - * @param LoopInterface $loop - * @return ExecutorInterface - * @throws \InvalidArgumentException for invalid DNS server address - */ - private function createSingleExecutor($nameserver, LoopInterface $loop) - { - $parts = \parse_url($nameserver); - - if (isset($parts['scheme']) && $parts['scheme'] === 'tcp') { - $executor = $this->createTcpExecutor($nameserver, $loop); - } elseif (isset($parts['scheme']) && $parts['scheme'] === 'udp') { - $executor = $this->createUdpExecutor($nameserver, $loop); - } else { - $executor = new SelectiveTransportExecutor( - $this->createUdpExecutor($nameserver, $loop), - $this->createTcpExecutor($nameserver, $loop) - ); - } - - return $executor; - } - - /** - * @param string $nameserver - * @param LoopInterface $loop - * @return TimeoutExecutor - * @throws \InvalidArgumentException for invalid DNS server address - */ - private function createTcpExecutor($nameserver, LoopInterface $loop) - { - return new TimeoutExecutor( - new TcpTransportExecutor($nameserver, $loop), - 5.0, - $loop - ); - } - - /** - * @param string $nameserver - * @param LoopInterface $loop - * @return TimeoutExecutor - * @throws \InvalidArgumentException for invalid DNS server address - */ - private function createUdpExecutor($nameserver, LoopInterface $loop) - { - return new TimeoutExecutor( - new UdpTransportExecutor( - $nameserver, - $loop - ), - 5.0, - $loop - ); - } -} diff --git a/digital_doctor/vendor/react/dns/src/Resolver/Resolver.php b/digital_doctor/vendor/react/dns/src/Resolver/Resolver.php deleted file mode 100644 index 92926f3..0000000 --- a/digital_doctor/vendor/react/dns/src/Resolver/Resolver.php +++ /dev/null @@ -1,147 +0,0 @@ -executor = $executor; - } - - public function resolve($domain) - { - return $this->resolveAll($domain, Message::TYPE_A)->then(function (array $ips) { - return $ips[array_rand($ips)]; - }); - } - - public function resolveAll($domain, $type) - { - $query = new Query($domain, $type, Message::CLASS_IN); - $that = $this; - - return $this->executor->query( - $query - )->then(function (Message $response) use ($query, $that) { - return $that->extractValues($query, $response); - }); - } - - /** - * [Internal] extract all resource record values from response for this query - * - * @param Query $query - * @param Message $response - * @return array - * @throws RecordNotFoundException when response indicates an error or contains no data - * @internal - */ - public function extractValues(Query $query, Message $response) - { - // reject if response code indicates this is an error response message - $code = $response->rcode; - if ($code !== Message::RCODE_OK) { - switch ($code) { - case Message::RCODE_FORMAT_ERROR: - $message = 'Format Error'; - break; - case Message::RCODE_SERVER_FAILURE: - $message = 'Server Failure'; - break; - case Message::RCODE_NAME_ERROR: - $message = 'Non-Existent Domain / NXDOMAIN'; - break; - case Message::RCODE_NOT_IMPLEMENTED: - $message = 'Not Implemented'; - break; - case Message::RCODE_REFUSED: - $message = 'Refused'; - break; - default: - $message = 'Unknown error response code ' . $code; - } - throw new RecordNotFoundException( - 'DNS query for ' . $query->describe() . ' returned an error response (' . $message . ')', - $code - ); - } - - $answers = $response->answers; - $addresses = $this->valuesByNameAndType($answers, $query->name, $query->type); - - // reject if we did not receive a valid answer (domain is valid, but no record for this type could be found) - if (0 === count($addresses)) { - throw new RecordNotFoundException( - 'DNS query for ' . $query->describe() . ' did not return a valid answer (NOERROR / NODATA)' - ); - } - - return array_values($addresses); - } - - /** - * @param \React\Dns\Model\Record[] $answers - * @param string $name - * @param int $type - * @return array - */ - private function valuesByNameAndType(array $answers, $name, $type) - { - // return all record values for this name and type (if any) - $named = $this->filterByName($answers, $name); - $records = $this->filterByType($named, $type); - if ($records) { - return $this->mapRecordData($records); - } - - // no matching records found? check if there are any matching CNAMEs instead - $cnameRecords = $this->filterByType($named, Message::TYPE_CNAME); - if ($cnameRecords) { - $cnames = $this->mapRecordData($cnameRecords); - foreach ($cnames as $cname) { - $records = array_merge( - $records, - $this->valuesByNameAndType($answers, $cname, $type) - ); - } - } - - return $records; - } - - private function filterByName(array $answers, $name) - { - return $this->filterByField($answers, 'name', $name); - } - - private function filterByType(array $answers, $type) - { - return $this->filterByField($answers, 'type', $type); - } - - private function filterByField(array $answers, $field, $value) - { - $value = strtolower($value); - return array_filter($answers, function ($answer) use ($field, $value) { - return $value === strtolower($answer->$field); - }); - } - - private function mapRecordData(array $records) - { - return array_map(function ($record) { - return $record->data; - }, $records); - } -} diff --git a/digital_doctor/vendor/react/dns/src/Resolver/ResolverInterface.php b/digital_doctor/vendor/react/dns/src/Resolver/ResolverInterface.php deleted file mode 100644 index 555a1cb..0000000 --- a/digital_doctor/vendor/react/dns/src/Resolver/ResolverInterface.php +++ /dev/null @@ -1,94 +0,0 @@ -resolve('reactphp.org')->then(function ($ip) { - * echo 'IP for reactphp.org is ' . $ip . PHP_EOL; - * }); - * ``` - * - * This is one of the main methods in this package. It sends a DNS query - * for the given $domain name to your DNS server and returns a single IP - * address on success. - * - * If the DNS server sends a DNS response message that contains more than - * one IP address for this query, it will randomly pick one of the IP - * addresses from the response. If you want the full list of IP addresses - * or want to send a different type of query, you should use the - * [`resolveAll()`](#resolveall) method instead. - * - * If the DNS server sends a DNS response message that indicates an error - * code, this method will reject with a `RecordNotFoundException`. Its - * message and code can be used to check for the response code. - * - * If the DNS communication fails and the server does not respond with a - * valid response message, this message will reject with an `Exception`. - * - * Pending DNS queries can be cancelled by cancelling its pending promise like so: - * - * ```php - * $promise = $resolver->resolve('reactphp.org'); - * - * $promise->cancel(); - * ``` - * - * @param string $domain - * @return \React\Promise\PromiseInterface - * resolves with a single IP address on success or rejects with an Exception on error. - */ - public function resolve($domain); - - /** - * Resolves all record values for the given $domain name and query $type. - * - * ```php - * $resolver->resolveAll('reactphp.org', Message::TYPE_A)->then(function ($ips) { - * echo 'IPv4 addresses for reactphp.org ' . implode(', ', $ips) . PHP_EOL; - * }); - * - * $resolver->resolveAll('reactphp.org', Message::TYPE_AAAA)->then(function ($ips) { - * echo 'IPv6 addresses for reactphp.org ' . implode(', ', $ips) . PHP_EOL; - * }); - * ``` - * - * This is one of the main methods in this package. It sends a DNS query - * for the given $domain name to your DNS server and returns a list with all - * record values on success. - * - * If the DNS server sends a DNS response message that contains one or more - * records for this query, it will return a list with all record values - * from the response. You can use the `Message::TYPE_*` constants to control - * which type of query will be sent. Note that this method always returns a - * list of record values, but each record value type depends on the query - * type. For example, it returns the IPv4 addresses for type `A` queries, - * the IPv6 addresses for type `AAAA` queries, the hostname for type `NS`, - * `CNAME` and `PTR` queries and structured data for other queries. See also - * the `Record` documentation for more details. - * - * If the DNS server sends a DNS response message that indicates an error - * code, this method will reject with a `RecordNotFoundException`. Its - * message and code can be used to check for the response code. - * - * If the DNS communication fails and the server does not respond with a - * valid response message, this message will reject with an `Exception`. - * - * Pending DNS queries can be cancelled by cancelling its pending promise like so: - * - * ```php - * $promise = $resolver->resolveAll('reactphp.org', Message::TYPE_AAAA); - * - * $promise->cancel(); - * ``` - * - * @param string $domain - * @return \React\Promise\PromiseInterface - * Resolves with all record values on success or rejects with an Exception on error. - */ - public function resolveAll($domain, $type); -} diff --git a/digital_doctor/vendor/react/event-loop/CHANGELOG.md b/digital_doctor/vendor/react/event-loop/CHANGELOG.md deleted file mode 100644 index e634b12..0000000 --- a/digital_doctor/vendor/react/event-loop/CHANGELOG.md +++ /dev/null @@ -1,468 +0,0 @@ -# Changelog - -## 1.5.0 (2023-11-13) - -* Feature: Improve performance by using `spl_object_id()` on PHP 7.2+. - (#267 by @samsonasik) - -* Feature: Full PHP 8.3 compatibility. - (#269 by @clue) - -* Update tests for `ext-uv` on PHP 8+ and legacy PHP. - (#270 by @clue and #268 by @SimonFrings) - -## 1.4.0 (2023-05-05) - -* Feature: Improve performance of `Loop` by avoiding unneeded method calls. - (#266 by @clue) - -* Feature: Support checking `EINTR` constant from `ext-pcntl` without `ext-sockets`. - (#265 by @clue) - -* Minor documentation improvements. - (#254 by @nhedger) - -* Improve test suite, run tests on PHP 8.2 and report failed assertions. - (#258 by @WyriHaximus, #264 by @clue and #251, #261 and #262 by @SimonFrings) - -## 1.3.0 (2022-03-17) - -* Feature: Improve default `StreamSelectLoop` to report any warnings for invalid streams. - (#245 by @clue) - -* Feature: Improve performance of `StreamSelectLoop` when no timers are scheduled. - (#246 by @clue) - -* Fix: Fix periodic timer with zero interval for `ExtEvLoop` and legacy `ExtLibevLoop`. - (#243 by @lucasnetau) - -* Minor documentation improvements, update PHP version references. - (#240, #248 and #250 by @SimonFrings, #241 by @dbu and #249 by @clue) - -* Improve test suite and test against PHP 8.1. - (#238 by @WyriHaximus and #242 by @clue) - -## 1.2.0 (2021-07-11) - -A major new feature release, see [**release announcement**](https://clue.engineering/2021/announcing-reactphp-default-loop). - -* Feature: Introduce new concept of default loop with the new `Loop` class. - (#226 by @WyriHaximus, #229, #231 and #232 by @clue) - - The `Loop` class exists as a convenient global accessor for the event loop. - It provides all methods that exist on the `LoopInterface` as static methods and - will automatically execute the loop at the end of the program: - - ```php - $timer = Loop::addPeriodicTimer(0.1, function () { - echo 'Tick' . PHP_EOL; - }); - - Loop::addTimer(1.0, function () use ($timer) { - Loop::cancelTimer($timer); - echo 'Done' . PHP_EOL; - }); - ``` - - The explicit loop instructions are still valid and may still be useful in some applications, - especially for a transition period towards the more concise style. - The `Loop::get()` method can be used to get the currently active event loop instance. - - ```php - // deprecated - $loop = React\EventLoop\Factory::create(); - - // new - $loop = React\EventLoop\Loop::get(); - ``` - -* Minor documentation improvements and mark legacy extensions as deprecated. - (#234 by @SimonFrings, #214 by @WyriHaximus and #233 and #235 by @nhedger) - -* Improve test suite, use GitHub actions for continuous integration (CI), - update PHPUnit config and run tests on PHP 8. - (#212 and #215 by @SimonFrings and #230 by @clue) - -## 1.1.1 (2020-01-01) - -* Fix: Fix reporting connection refused errors with `ExtUvLoop` on Linux and `StreamSelectLoop` on Windows. - (#207 and #208 by @clue) - -* Fix: Fix unsupported EventConfig and `SEGFAULT` on shutdown with `ExtEventLoop` on Windows. - (#205 by @clue) - -* Fix: Prevent interval overflow for timers very far in the future with `ExtUvLoop`. - (#196 by @PabloKowalczyk) - -* Fix: Check PCNTL functions for signal support instead of PCNTL extension with `StreamSelectLoop`. - (#195 by @clue) - -* Add `.gitattributes` to exclude dev files from exports. - (#201 by @reedy) - -* Improve test suite to fix testing `ExtUvLoop` on Travis, - fix Travis CI builds, do not install `libuv` on legacy PHP setups, - fix failing test cases due to inaccurate timers, - run tests on Windows via Travis CI and - run tests on PHP 7.4 and simplify test matrix and test setup. - (#197 by @WyriHaximus and #202, #203, #204 and #209 by @clue) - -## 1.1.0 (2019-02-07) - -* New UV based event loop (ext-uv). - (#112 by @WyriHaximus) - -* Use high resolution timer on PHP 7.3+. - (#182 by @clue) - -* Improve PCNTL signals by using async signal dispatching if available. - (#179 by @CharlotteDunois) - -* Improve test suite and test suite set up. - (#174 by @WyriHaximus, #181 by @clue) - -* Fix PCNTL signals edge case. - (#183 by @clue) - -## 1.0.0 (2018-07-11) - -* First stable LTS release, now following [SemVer](https://semver.org/). - We'd like to emphasize that this component is production ready and battle-tested. - We plan to support all long-term support (LTS) releases for at least 24 months, - so you have a rock-solid foundation to build on top of. - -> Contains no other changes, so it's actually fully compatible with the v0.5.3 release. - -## 0.5.3 (2018-07-09) - -* Improve performance by importing global functions. - (#167 by @Ocramius) - -* Improve test suite by simplifying test bootstrap by using dev autoloader. - (#169 by @lcobucci) - -* Minor internal changes to improved backward compatibility with PHP 5.3. - (#166 by @Donatello-za) - -## 0.5.2 (2018-04-24) - -* Feature: Improve memory consumption and runtime performance for `StreamSelectLoop` timers. - (#164 by @clue) - -* Improve test suite by removing I/O dependency at `StreamSelectLoopTest` to fix Mac OS X tests. - (#161 by @nawarian) - -## 0.5.1 (2018-04-09) - -* Feature: New `ExtEvLoop` (PECL ext-ev) (#148 by @kaduev13) - -## 0.5.0 (2018-04-05) - -A major feature release with a significant documentation overhaul and long overdue API cleanup! - -This update involves a number of BC breaks due to dropped support for deprecated -functionality. We've tried hard to avoid BC breaks where possible and minimize -impact otherwise. We expect that most consumers of this package will actually -not be affected by any BC breaks, see below for more details. - -We realize that the changes listed below may seem overwhelming, but we've tried -to be very clear about any possible BC breaks. Don't worry: In fact, all ReactPHP -components are already compatible and support both this new release as well as -providing backwards compatibility with the last release. - -* Feature / BC break: Add support for signal handling via new - `LoopInterface::addSignal()` and `LoopInterface::removeSignal()` methods. - (#104 by @WyriHaximus and #111 and #150 by @clue) - - ```php - $loop->addSignal(SIGINT, function () { - echo 'CTRL-C'; - }); - ``` - -* Feature: Significant documentation updates for `LoopInterface` and `Factory`. - (#100, #119, #126, #127, #159 and #160 by @clue, #113 by @WyriHaximus and #81 and #91 by @jsor) - -* Feature: Add examples to ease getting started - (#99, #100 and #125 by @clue, #59 by @WyriHaximus and #143 by @jsor) - -* Feature: Documentation for advanced timer concepts, such as monotonic time source vs wall-clock time - and high precision timers with millisecond accuracy or below. - (#130 and #157 by @clue) - -* Feature: Documentation for advanced stream concepts, such as edge-triggered event listeners - and stream buffers and allow throwing Exception if stream resource is not supported. - (#129 and #158 by @clue) - -* Feature: Throw `BadMethodCallException` on manual loop creation when required extension isn't installed. - (#153 by @WyriHaximus) - -* Feature / BC break: First class support for legacy PHP 5.3 through PHP 7.2 and HHVM - and remove all `callable` type hints for consistency reasons. - (#141 and #151 by @clue) - -* BC break: Documentation for timer API and clean up unneeded timer API. - (#102 by @clue) - - Remove `TimerInterface::cancel()`, use `LoopInterface::cancelTimer()` instead: - - ```php - // old (method invoked on timer instance) - $timer->cancel(); - - // already supported before: invoke method on loop instance - $loop->cancelTimer($timer); - ``` - - Remove unneeded `TimerInterface::setData()` and `TimerInterface::getData()`, - use closure binding to add arbitrary data to timer instead: - - ```php - // old (limited setData() and getData() only allows single variable) - $name = 'Tester'; - $timer = $loop->addTimer(1.0, function ($timer) { - echo 'Hello ' . $timer->getData() . PHP_EOL; - }); - $timer->setData($name); - - // already supported before: closure binding allows any number of variables - $name = 'Tester'; - $loop->addTimer(1.0, function () use ($name) { - echo 'Hello ' . $name . PHP_EOL; - }); - ``` - - Remove unneeded `TimerInterface::getLoop()`, use closure binding instead: - - ```php - // old (getLoop() called on timer instance) - $loop->addTimer(0.1, function ($timer) { - $timer->getLoop()->stop(); - }); - - // already supported before: use closure binding as usual - $loop->addTimer(0.1, function () use ($loop) { - $loop->stop(); - }); - ``` - -* BC break: Remove unneeded `LoopInterface::isTimerActive()` and - `TimerInterface::isActive()` to reduce API surface. - (#133 by @clue) - - ```php - // old (method on timer instance or on loop instance) - $timer->isActive(); - $loop->isTimerActive($timer); - ``` - -* BC break: Move `TimerInterface` one level up to `React\EventLoop\TimerInterface`. - (#138 by @WyriHaximus) - - ```php - // old (notice obsolete "Timer" namespace) - assert($timer instanceof React\EventLoop\Timer\TimerInterface); - - // new - assert($timer instanceof React\EventLoop\TimerInterface); - ``` - -* BC break: Remove unneeded `LoopInterface::nextTick()` (and internal `NextTickQueue`), - use `LoopInterface::futureTick()` instead. - (#30 by @clue) - - ```php - // old (removed) - $loop->nextTick(function () { - echo 'tick'; - }); - - // already supported before - $loop->futureTick(function () { - echo 'tick'; - }); - ``` - -* BC break: Remove unneeded `$loop` argument for `LoopInterface::futureTick()` - (and fix internal cyclic dependency). - (#103 by @clue) - - ```php - // old ($loop gets passed by default) - $loop->futureTick(function ($loop) { - $loop->stop(); - }); - - // already supported before: use closure binding as usual - $loop->futureTick(function () use ($loop) { - $loop->stop(); - }); - ``` - -* BC break: Remove unneeded `LoopInterface::tick()`. - (#72 by @jsor) - - ```php - // old (removed) - $loop->tick(); - - // suggested work around for testing purposes only - $loop->futureTick(function () use ($loop) { - $loop->stop(); - }); - ``` - -* BC break: Documentation for advanced stream API and clean up unneeded stream API. - (#110 by @clue) - - Remove unneeded `$loop` argument for `LoopInterface::addReadStream()` - and `LoopInterface::addWriteStream()`, use closure binding instead: - - ```php - // old ($loop gets passed by default) - $loop->addReadStream($stream, function ($stream, $loop) { - $loop->removeReadStream($stream); - }); - - // already supported before: use closure binding as usual - $loop->addReadStream($stream, function ($stream) use ($loop) { - $loop->removeReadStream($stream); - }); - ``` - -* BC break: Remove unneeded `LoopInterface::removeStream()` method, - use `LoopInterface::removeReadStream()` and `LoopInterface::removeWriteStream()` instead. - (#118 by @clue) - - ```php - // old - $loop->removeStream($stream); - - // already supported before - $loop->removeReadStream($stream); - $loop->removeWriteStream($stream); - ``` - -* BC break: Rename `LibEventLoop` to `ExtLibeventLoop` and `LibEvLoop` to `ExtLibevLoop` - for consistent naming for event loop implementations. - (#128 by @clue) - -* BC break: Remove optional `EventBaseConfig` argument from `ExtEventLoop` - and make its `FEATURE_FDS` enabled by default. - (#156 by @WyriHaximus) - -* BC break: Mark all classes as final to discourage inheritance. - (#131 by @clue) - -* Fix: Fix `ExtEventLoop` to keep track of stream resources (refcount) - (#123 by @clue) - -* Fix: Ensure large timer interval does not overflow on 32bit systems - (#132 by @clue) - -* Fix: Fix separately removing readable and writable side of stream when closing - (#139 by @clue) - -* Fix: Properly clean up event watchers for `ext-event` and `ext-libev` - (#149 by @clue) - -* Fix: Minor code cleanup and remove unneeded references - (#145 by @seregazhuk) - -* Fix: Discourage outdated `ext-libevent` on PHP 7 - (#62 by @cboden) - -* Improve test suite by adding forward compatibility with PHPUnit 6 and PHPUnit 5, - lock Travis distro so new defaults will not break the build, - improve test suite to be less fragile and increase test timeouts, - test against PHP 7.2 and reduce fwrite() call length to one chunk. - (#106 and #144 by @clue, #120 and #124 by @carusogabriel, #147 by nawarian and #92 by @kelunik) - -* A number of changes were originally planned for this release but have been backported - to the last `v0.4.3` already: #74, #76, #79, #81 (refs #65, #66, #67), #88 and #93 - -## 0.4.3 (2017-04-27) - -* Bug fix: Bugfix in the usage sample code #57 (@dandelionred) -* Improvement: Remove branch-alias definition #53 (@WyriHaximus) -* Improvement: StreamSelectLoop: Use fresh time so Timers added during stream events are accurate #51 (@andrewminerd) -* Improvement: Avoid deprecation warnings in test suite due to deprecation of getMock() in PHPUnit #68 (@martinschroeder) -* Improvement: Add PHPUnit 4.8 to require-dev #69 (@shaunbramley) -* Improvement: Increase test timeouts for HHVM and unify timeout handling #70 (@clue) -* Improvement: Travis improvements (backported from #74) #75 (@clue) -* Improvement: Test suite now uses socket pairs instead of memory streams #66 (@martinschroeder) -* Improvement: StreamSelectLoop: Test suite uses signal constant names in data provider #67 (@martinschroeder) -* Improvement: ExtEventLoop: No longer suppress all errors #65 (@mamciek) -* Improvement: Readme cleanup #89 (@jsor) -* Improvement: Restructure and improve README #90 (@jsor) -* Bug fix: StreamSelectLoop: Fix erroneous zero-time sleep (backport to 0.4) #94 (@jsor) - -## 0.4.2 (2016-03-07) - -* Bug fix: No longer error when signals sent to StreamSelectLoop -* Support HHVM and PHP7 (@ondrejmirtes, @cebe) -* Feature: Added support for EventConfig for ExtEventLoop (@steverhoades) -* Bug fix: Fixed an issue loading loop extension libs via autoloader (@czarpino) - -## 0.4.1 (2014-04-13) - -* Bug fix: null timeout in StreamSelectLoop causing 100% CPU usage (@clue) -* Bug fix: v0.3.4 changes merged for v0.4.1 - -## 0.4.0 (2014-02-02) - -* Feature: Added `EventLoopInterface::nextTick()`, implemented in all event loops (@jmalloc) -* Feature: Added `EventLoopInterface::futureTick()`, implemented in all event loops (@jmalloc) -* Feature: Added `ExtEventLoop` implementation using pecl/event (@jmalloc) -* BC break: Bump minimum PHP version to PHP 5.4, remove 5.3 specific hacks -* BC break: New method: `EventLoopInterface::nextTick()` -* BC break: New method: `EventLoopInterface::futureTick()` -* Dependency: Autoloading and filesystem structure now PSR-4 instead of PSR-0 - -## 0.3.5 (2016-12-28) - -This is a compatibility release that eases upgrading to the v0.4 release branch. -You should consider upgrading to the v0.4 release branch. - -* Feature: Cap min timer interval at 1µs, thus improving compatibility with v0.4 - (#47 by @clue) - -## 0.3.4 (2014-03-30) - -* Bug fix: Changed StreamSelectLoop to use non-blocking behavior on tick() (@astephens25) - -## 0.3.3 (2013-07-08) - -* Bug fix: No error on removing non-existent streams (@clue) -* Bug fix: Do not silently remove feof listeners in `LibEvLoop` - -## 0.3.0 (2013-04-14) - -* BC break: New timers API (@nrk) -* BC break: Remove check on return value from stream callbacks (@nrk) - -## 0.2.7 (2013-01-05) - -* Bug fix: Fix libevent timers with PHP 5.3 -* Bug fix: Fix libevent timer cancellation (@nrk) - -## 0.2.6 (2012-12-26) - -* Bug fix: Plug memory issue in libevent timers (@cameronjacobson) -* Bug fix: Correctly pause LibEvLoop on stop() - -## 0.2.3 (2012-11-14) - -* Feature: LibEvLoop, integration of `php-libev` - -## 0.2.0 (2012-09-10) - -* Version bump - -## 0.1.1 (2012-07-12) - -* Version bump - -## 0.1.0 (2012-07-11) - -* First tagged release diff --git a/digital_doctor/vendor/react/event-loop/LICENSE b/digital_doctor/vendor/react/event-loop/LICENSE deleted file mode 100644 index d6f8901..0000000 --- a/digital_doctor/vendor/react/event-loop/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2012 Christian Lück, Cees-Jan Kiewiet, Jan Sorgalla, Chris Boden, Igor Wiedler - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/digital_doctor/vendor/react/event-loop/README.md b/digital_doctor/vendor/react/event-loop/README.md deleted file mode 100644 index 88a3e18..0000000 --- a/digital_doctor/vendor/react/event-loop/README.md +++ /dev/null @@ -1,930 +0,0 @@ -# EventLoop - -[![CI status](https://github.com/reactphp/event-loop/actions/workflows/ci.yml/badge.svg)](https://github.com/reactphp/event-loop/actions) -[![installs on Packagist](https://img.shields.io/packagist/dt/react/event-loop?color=blue&label=installs%20on%20Packagist)](https://packagist.org/packages/react/event-loop) - -[ReactPHP](https://reactphp.org/)'s core reactor event loop that libraries can use for evented I/O. - -In order for async based libraries to be interoperable, they need to use the -same event loop. This component provides a common `LoopInterface` that any -library can target. This allows them to be used in the same loop, with one -single [`run()`](#run) call that is controlled by the user. - -**Table of contents** - -* [Quickstart example](#quickstart-example) -* [Usage](#usage) - * [Loop](#loop) - * [Loop methods](#loop-methods) - * [Loop autorun](#loop-autorun) - * [get()](#get) - * [~~Factory~~](#factory) - * [~~create()~~](#create) - * [Loop implementations](#loop-implementations) - * [StreamSelectLoop](#streamselectloop) - * [ExtEventLoop](#exteventloop) - * [ExtEvLoop](#extevloop) - * [ExtUvLoop](#extuvloop) - * [~~ExtLibeventLoop~~](#extlibeventloop) - * [~~ExtLibevLoop~~](#extlibevloop) - * [LoopInterface](#loopinterface) - * [run()](#run) - * [stop()](#stop) - * [addTimer()](#addtimer) - * [addPeriodicTimer()](#addperiodictimer) - * [cancelTimer()](#canceltimer) - * [futureTick()](#futuretick) - * [addSignal()](#addsignal) - * [removeSignal()](#removesignal) - * [addReadStream()](#addreadstream) - * [addWriteStream()](#addwritestream) - * [removeReadStream()](#removereadstream) - * [removeWriteStream()](#removewritestream) -* [Install](#install) -* [Tests](#tests) -* [License](#license) -* [More](#more) - -## Quickstart example - -Here is an async HTTP server built with just the event loop. - -```php -addPeriodicTimer(0.1, function () { - echo 'Tick' . PHP_EOL; -}); - -$loop->addTimer(1.0, function () use ($loop, $timer) { - $loop->cancelTimer($timer); - echo 'Done' . PHP_EOL; -}); - -$loop->run(); -``` - -While the former is more concise, the latter is more explicit. -In both cases, the program would perform the exact same steps. - -1. The event loop instance is created at the beginning of the program. This is - implicitly done the first time you call the [`Loop` class](#loop) or - explicitly when using the deprecated [`Factory::create()` method](#create) - (or manually instantiating any of the [loop implementations](#loop-implementations)). -2. The event loop is used directly or passed as an instance to library and - application code. In this example, a periodic timer is registered with the - event loop which simply outputs `Tick` every fraction of a second until another - timer stops the periodic timer after a second. -3. The event loop is run at the end of the program. This is automatically done - when using the [`Loop` class](#loop) or explicitly with a single [`run()`](#run) - call at the end of the program. - -As of `v1.2.0`, we highly recommend using the [`Loop` class](#loop). -The explicit loop instructions are still valid and may still be useful in some -applications, especially for a transition period towards the more concise style. - -### Loop - -The `Loop` class exists as a convenient global accessor for the event loop. - -#### Loop methods - -The `Loop` class provides all methods that exist on the [`LoopInterface`](#loopinterface) -as static methods: - -* [run()](#run) -* [stop()](#stop) -* [addTimer()](#addtimer) -* [addPeriodicTimer()](#addperiodictimer) -* [cancelTimer()](#canceltimer) -* [futureTick()](#futuretick) -* [addSignal()](#addsignal) -* [removeSignal()](#removesignal) -* [addReadStream()](#addreadstream) -* [addWriteStream()](#addwritestream) -* [removeReadStream()](#removereadstream) -* [removeWriteStream()](#removewritestream) - -If you're working with the event loop in your application code, it's often -easiest to directly interface with the static methods defined on the `Loop` class -like this: - -```php -use React\EventLoop\Loop; - -$timer = Loop::addPeriodicTimer(0.1, function () { - echo 'Tick' . PHP_EOL; -}); - -Loop::addTimer(1.0, function () use ($timer) { - Loop::cancelTimer($timer); - echo 'Done' . PHP_EOL; -}); -``` - -On the other hand, if you're familiar with object-oriented programming (OOP) and -dependency injection (DI), you may want to inject an event loop instance and -invoke instance methods on the `LoopInterface` like this: - -```php -use React\EventLoop\Loop; -use React\EventLoop\LoopInterface; - -class Greeter -{ - private $loop; - - public function __construct(LoopInterface $loop) - { - $this->loop = $loop; - } - - public function greet(string $name) - { - $this->loop->addTimer(1.0, function () use ($name) { - echo 'Hello ' . $name . '!' . PHP_EOL; - }); - } -} - -$greeter = new Greeter(Loop::get()); -$greeter->greet('Alice'); -$greeter->greet('Bob'); -``` - -Each static method call will be forwarded as-is to the underlying event loop -instance by using the [`Loop::get()`](#get) call internally. -See [`LoopInterface`](#loopinterface) for more details about available methods. - -#### Loop autorun - -When using the `Loop` class, it will automatically execute the loop at the end of -the program. This means the following example will schedule a timer and will -automatically execute the program until the timer event fires: - -```php -use React\EventLoop\Loop; - -Loop::addTimer(1.0, function () { - echo 'Hello' . PHP_EOL; -}); -``` - -As of `v1.2.0`, we highly recommend using the `Loop` class this way and omitting any -explicit [`run()`](#run) calls. For BC reasons, the explicit [`run()`](#run) -method is still valid and may still be useful in some applications, especially -for a transition period towards the more concise style. - -If you don't want the `Loop` to run automatically, you can either explicitly -[`run()`](#run) or [`stop()`](#stop) it. This can be useful if you're using -a global exception handler like this: - -```php -use React\EventLoop\Loop; - -Loop::addTimer(10.0, function () { - echo 'Never happens'; -}); - -set_exception_handler(function (Throwable $e) { - echo 'Error: ' . $e->getMessage() . PHP_EOL; - Loop::stop(); -}); - -throw new RuntimeException('Demo'); -``` - -#### get() - -The `get(): LoopInterface` method can be used to -get the currently active event loop instance. - -This method will always return the same event loop instance throughout the -lifetime of your application. - -```php -use React\EventLoop\Loop; -use React\EventLoop\LoopInterface; - -$loop = Loop::get(); - -assert($loop instanceof LoopInterface); -assert($loop === Loop::get()); -``` - -This is particularly useful if you're using object-oriented programming (OOP) -and dependency injection (DI). In this case, you may want to inject an event -loop instance and invoke instance methods on the `LoopInterface` like this: - -```php -use React\EventLoop\Loop; -use React\EventLoop\LoopInterface; - -class Greeter -{ - private $loop; - - public function __construct(LoopInterface $loop) - { - $this->loop = $loop; - } - - public function greet(string $name) - { - $this->loop->addTimer(1.0, function () use ($name) { - echo 'Hello ' . $name . '!' . PHP_EOL; - }); - } -} - -$greeter = new Greeter(Loop::get()); -$greeter->greet('Alice'); -$greeter->greet('Bob'); -``` - -See [`LoopInterface`](#loopinterface) for more details about available methods. - -### ~~Factory~~ - -> Deprecated since v1.2.0, see [`Loop` class](#loop) instead. - -The deprecated `Factory` class exists as a convenient way to pick the best available -[event loop implementation](#loop-implementations). - -#### ~~create()~~ - -> Deprecated since v1.2.0, see [`Loop::get()`](#get) instead. - -The deprecated `create(): LoopInterface` method can be used to -create a new event loop instance: - -```php -// deprecated -$loop = React\EventLoop\Factory::create(); - -// new -$loop = React\EventLoop\Loop::get(); -``` - -This method always returns an instance implementing [`LoopInterface`](#loopinterface), -the actual [event loop implementation](#loop-implementations) is an implementation detail. - -This method should usually only be called once at the beginning of the program. - -### Loop implementations - -In addition to the [`LoopInterface`](#loopinterface), there are a number of -event loop implementations provided. - -All of the event loops support these features: - -* File descriptor polling -* One-off timers -* Periodic timers -* Deferred execution on future loop tick - -For most consumers of this package, the underlying event loop implementation is -an implementation detail. -You should use the [`Loop` class](#loop) to automatically create a new instance. - -Advanced! If you explicitly need a certain event loop implementation, you can -manually instantiate one of the following classes. -Note that you may have to install the required PHP extensions for the respective -event loop implementation first or they will throw a `BadMethodCallException` on creation. - -#### StreamSelectLoop - -A `stream_select()` based event loop. - -This uses the [`stream_select()`](https://www.php.net/manual/en/function.stream-select.php) -function and is the only implementation that works out of the box with PHP. - -This event loop works out of the box on PHP 5.3 through PHP 8+ and HHVM. -This means that no installation is required and this library works on all -platforms and supported PHP versions. -Accordingly, the [`Loop` class](#loop) and the deprecated [`Factory`](#factory) -will use this event loop by default if you do not install any of the event loop -extensions listed below. - -Under the hood, it does a simple `select` system call. -This system call is limited to the maximum file descriptor number of -`FD_SETSIZE` (platform dependent, commonly 1024) and scales with `O(m)` -(`m` being the maximum file descriptor number passed). -This means that you may run into issues when handling thousands of streams -concurrently and you may want to look into using one of the alternative -event loop implementations listed below in this case. -If your use case is among the many common use cases that involve handling only -dozens or a few hundred streams at once, then this event loop implementation -performs really well. - -If you want to use signal handling (see also [`addSignal()`](#addsignal) below), -this event loop implementation requires `ext-pcntl`. -This extension is only available for Unix-like platforms and does not support -Windows. -It is commonly installed as part of many PHP distributions. -If this extension is missing (or you're running on Windows), signal handling is -not supported and throws a `BadMethodCallException` instead. - -This event loop is known to rely on wall-clock time to schedule future timers -when using any version before PHP 7.3, because a monotonic time source is -only available as of PHP 7.3 (`hrtime()`). -While this does not affect many common use cases, this is an important -distinction for programs that rely on a high time precision or on systems -that are subject to discontinuous time adjustments (time jumps). -This means that if you schedule a timer to trigger in 30s on PHP < 7.3 and -then adjust your system time forward by 20s, the timer may trigger in 10s. -See also [`addTimer()`](#addtimer) for more details. - -#### ExtEventLoop - -An `ext-event` based event loop. - -This uses the [`event` PECL extension](https://pecl.php.net/package/event), -that provides an interface to `libevent` library. -`libevent` itself supports a number of system-specific backends (epoll, kqueue). - -This loop is known to work with PHP 5.4 through PHP 8+. - -#### ExtEvLoop - -An `ext-ev` based event loop. - -This loop uses the [`ev` PECL extension](https://pecl.php.net/package/ev), -that provides an interface to `libev` library. -`libev` itself supports a number of system-specific backends (epoll, kqueue). - - -This loop is known to work with PHP 5.4 through PHP 8+. - -#### ExtUvLoop - -An `ext-uv` based event loop. - -This loop uses the [`uv` PECL extension](https://pecl.php.net/package/uv), -that provides an interface to `libuv` library. -`libuv` itself supports a number of system-specific backends (epoll, kqueue). - -This loop is known to work with PHP 7+. - -#### ~~ExtLibeventLoop~~ - -> Deprecated since v1.2.0, use [`ExtEventLoop`](#exteventloop) instead. - -An `ext-libevent` based event loop. - -This uses the [`libevent` PECL extension](https://pecl.php.net/package/libevent), -that provides an interface to `libevent` library. -`libevent` itself supports a number of system-specific backends (epoll, kqueue). - -This event loop does only work with PHP 5. -An [unofficial update](https://github.com/php/pecl-event-libevent/pull/2) for -PHP 7 does exist, but it is known to cause regular crashes due to `SEGFAULT`s. -To reiterate: Using this event loop on PHP 7 is not recommended. -Accordingly, neither the [`Loop` class](#loop) nor the deprecated -[`Factory` class](#factory) will try to use this event loop on PHP 7. - -This event loop is known to trigger a readable listener only if -the stream *becomes* readable (edge-triggered) and may not trigger if the -stream has already been readable from the beginning. -This also implies that a stream may not be recognized as readable when data -is still left in PHP's internal stream buffers. -As such, it's recommended to use `stream_set_read_buffer($stream, 0);` -to disable PHP's internal read buffer in this case. -See also [`addReadStream()`](#addreadstream) for more details. - -#### ~~ExtLibevLoop~~ - -> Deprecated since v1.2.0, use [`ExtEvLoop`](#extevloop) instead. - -An `ext-libev` based event loop. - -This uses an [unofficial `libev` extension](https://github.com/m4rw3r/php-libev), -that provides an interface to `libev` library. -`libev` itself supports a number of system-specific backends (epoll, kqueue). - -This loop does only work with PHP 5. -An update for PHP 7 is [unlikely](https://github.com/m4rw3r/php-libev/issues/8) -to happen any time soon. - -### LoopInterface - -#### run() - -The `run(): void` method can be used to -run the event loop until there are no more tasks to perform. - -For many applications, this method is the only directly visible -invocation on the event loop. -As a rule of thumb, it is usually recommended to attach everything to the -same loop instance and then run the loop once at the bottom end of the -application. - -```php -$loop->run(); -``` - -This method will keep the loop running until there are no more tasks -to perform. In other words: This method will block until the last -timer, stream and/or signal has been removed. - -Likewise, it is imperative to ensure the application actually invokes -this method once. Adding listeners to the loop and missing to actually -run it will result in the application exiting without actually waiting -for any of the attached listeners. - -This method MUST NOT be called while the loop is already running. -This method MAY be called more than once after it has explicitly been -[`stop()`ped](#stop) or after it automatically stopped because it -previously did no longer have anything to do. - -#### stop() - -The `stop(): void` method can be used to -instruct a running event loop to stop. - -This method is considered advanced usage and should be used with care. -As a rule of thumb, it is usually recommended to let the loop stop -only automatically when it no longer has anything to do. - -This method can be used to explicitly instruct the event loop to stop: - -```php -$loop->addTimer(3.0, function () use ($loop) { - $loop->stop(); -}); -``` - -Calling this method on a loop instance that is not currently running or -on a loop instance that has already been stopped has no effect. - -#### addTimer() - -The `addTimer(float $interval, callable $callback): TimerInterface` method can be used to -enqueue a callback to be invoked once after the given interval. - -The second parameter MUST be a timer callback function that accepts -the timer instance as its only parameter. -If you don't use the timer instance inside your timer callback function -you MAY use a function which has no parameters at all. - -The timer callback function MUST NOT throw an `Exception`. -The return value of the timer callback function will be ignored and has -no effect, so for performance reasons you're recommended to not return -any excessive data structures. - -This method returns a timer instance. The same timer instance will also be -passed into the timer callback function as described above. -You can invoke [`cancelTimer`](#canceltimer) to cancel a pending timer. -Unlike [`addPeriodicTimer()`](#addperiodictimer), this method will ensure -the callback will be invoked only once after the given interval. - -```php -$loop->addTimer(0.8, function () { - echo 'world!' . PHP_EOL; -}); - -$loop->addTimer(0.3, function () { - echo 'hello '; -}); -``` - -See also [example #1](examples). - -If you want to access any variables within your callback function, you -can bind arbitrary data to a callback closure like this: - -```php -function hello($name, LoopInterface $loop) -{ - $loop->addTimer(1.0, function () use ($name) { - echo "hello $name\n"; - }); -} - -hello('Tester', $loop); -``` - -This interface does not enforce any particular timer resolution, so -special care may have to be taken if you rely on very high precision with -millisecond accuracy or below. Event loop implementations SHOULD work on -a best effort basis and SHOULD provide at least millisecond accuracy -unless otherwise noted. Many existing event loop implementations are -known to provide microsecond accuracy, but it's generally not recommended -to rely on this high precision. - -Similarly, the execution order of timers scheduled to execute at the -same time (within its possible accuracy) is not guaranteed. - -This interface suggests that event loop implementations SHOULD use a -monotonic time source if available. Given that a monotonic time source is -only available as of PHP 7.3 by default, event loop implementations MAY -fall back to using wall-clock time. -While this does not affect many common use cases, this is an important -distinction for programs that rely on a high time precision or on systems -that are subject to discontinuous time adjustments (time jumps). -This means that if you schedule a timer to trigger in 30s and then adjust -your system time forward by 20s, the timer SHOULD still trigger in 30s. -See also [event loop implementations](#loop-implementations) for more details. - -#### addPeriodicTimer() - -The `addPeriodicTimer(float $interval, callable $callback): TimerInterface` method can be used to -enqueue a callback to be invoked repeatedly after the given interval. - -The second parameter MUST be a timer callback function that accepts -the timer instance as its only parameter. -If you don't use the timer instance inside your timer callback function -you MAY use a function which has no parameters at all. - -The timer callback function MUST NOT throw an `Exception`. -The return value of the timer callback function will be ignored and has -no effect, so for performance reasons you're recommended to not return -any excessive data structures. - -This method returns a timer instance. The same timer instance will also be -passed into the timer callback function as described above. -Unlike [`addTimer()`](#addtimer), this method will ensure the callback -will be invoked infinitely after the given interval or until you invoke -[`cancelTimer`](#canceltimer). - -```php -$timer = $loop->addPeriodicTimer(0.1, function () { - echo 'tick!' . PHP_EOL; -}); - -$loop->addTimer(1.0, function () use ($loop, $timer) { - $loop->cancelTimer($timer); - echo 'Done' . PHP_EOL; -}); -``` - -See also [example #2](examples). - -If you want to limit the number of executions, you can bind -arbitrary data to a callback closure like this: - -```php -function hello($name, LoopInterface $loop) -{ - $n = 3; - $loop->addPeriodicTimer(1.0, function ($timer) use ($name, $loop, &$n) { - if ($n > 0) { - --$n; - echo "hello $name\n"; - } else { - $loop->cancelTimer($timer); - } - }); -} - -hello('Tester', $loop); -``` - -This interface does not enforce any particular timer resolution, so -special care may have to be taken if you rely on very high precision with -millisecond accuracy or below. Event loop implementations SHOULD work on -a best effort basis and SHOULD provide at least millisecond accuracy -unless otherwise noted. Many existing event loop implementations are -known to provide microsecond accuracy, but it's generally not recommended -to rely on this high precision. - -Similarly, the execution order of timers scheduled to execute at the -same time (within its possible accuracy) is not guaranteed. - -This interface suggests that event loop implementations SHOULD use a -monotonic time source if available. Given that a monotonic time source is -only available as of PHP 7.3 by default, event loop implementations MAY -fall back to using wall-clock time. -While this does not affect many common use cases, this is an important -distinction for programs that rely on a high time precision or on systems -that are subject to discontinuous time adjustments (time jumps). -This means that if you schedule a timer to trigger in 30s and then adjust -your system time forward by 20s, the timer SHOULD still trigger in 30s. -See also [event loop implementations](#loop-implementations) for more details. - -Additionally, periodic timers may be subject to timer drift due to -re-scheduling after each invocation. As such, it's generally not -recommended to rely on this for high precision intervals with millisecond -accuracy or below. - -#### cancelTimer() - -The `cancelTimer(TimerInterface $timer): void` method can be used to -cancel a pending timer. - -See also [`addPeriodicTimer()`](#addperiodictimer) and [example #2](examples). - -Calling this method on a timer instance that has not been added to this -loop instance or on a timer that has already been cancelled has no effect. - -#### futureTick() - -The `futureTick(callable $listener): void` method can be used to -schedule a callback to be invoked on a future tick of the event loop. - -This works very much similar to timers with an interval of zero seconds, -but does not require the overhead of scheduling a timer queue. - -The tick callback function MUST be able to accept zero parameters. - -The tick callback function MUST NOT throw an `Exception`. -The return value of the tick callback function will be ignored and has -no effect, so for performance reasons you're recommended to not return -any excessive data structures. - -If you want to access any variables within your callback function, you -can bind arbitrary data to a callback closure like this: - -```php -function hello($name, LoopInterface $loop) -{ - $loop->futureTick(function () use ($name) { - echo "hello $name\n"; - }); -} - -hello('Tester', $loop); -``` - -Unlike timers, tick callbacks are guaranteed to be executed in the order -they are enqueued. -Also, once a callback is enqueued, there's no way to cancel this operation. - -This is often used to break down bigger tasks into smaller steps (a form -of cooperative multitasking). - -```php -$loop->futureTick(function () { - echo 'b'; -}); -$loop->futureTick(function () { - echo 'c'; -}); -echo 'a'; -``` - -See also [example #3](examples). - -#### addSignal() - -The `addSignal(int $signal, callable $listener): void` method can be used to -register a listener to be notified when a signal has been caught by this process. - -This is useful to catch user interrupt signals or shutdown signals from -tools like `supervisor` or `systemd`. - -The second parameter MUST be a listener callback function that accepts -the signal as its only parameter. -If you don't use the signal inside your listener callback function -you MAY use a function which has no parameters at all. - -The listener callback function MUST NOT throw an `Exception`. -The return value of the listener callback function will be ignored and has -no effect, so for performance reasons you're recommended to not return -any excessive data structures. - -```php -$loop->addSignal(SIGINT, function (int $signal) { - echo 'Caught user interrupt signal' . PHP_EOL; -}); -``` - -See also [example #4](examples). - -Signaling is only available on Unix-like platforms, Windows isn't -supported due to operating system limitations. -This method may throw a `BadMethodCallException` if signals aren't -supported on this platform, for example when required extensions are -missing. - -**Note: A listener can only be added once to the same signal, any -attempts to add it more than once will be ignored.** - -#### removeSignal() - -The `removeSignal(int $signal, callable $listener): void` method can be used to -remove a previously added signal listener. - -```php -$loop->removeSignal(SIGINT, $listener); -``` - -Any attempts to remove listeners that aren't registered will be ignored. - -#### addReadStream() - -> Advanced! Note that this low-level API is considered advanced usage. - Most use cases should probably use the higher-level - [readable Stream API](https://github.com/reactphp/stream#readablestreaminterface) - instead. - -The `addReadStream(resource $stream, callable $callback): void` method can be used to -register a listener to be notified when a stream is ready to read. - -The first parameter MUST be a valid stream resource that supports -checking whether it is ready to read by this loop implementation. -A single stream resource MUST NOT be added more than once. -Instead, either call [`removeReadStream()`](#removereadstream) first or -react to this event with a single listener and then dispatch from this -listener. This method MAY throw an `Exception` if the given resource type -is not supported by this loop implementation. - -The second parameter MUST be a listener callback function that accepts -the stream resource as its only parameter. -If you don't use the stream resource inside your listener callback function -you MAY use a function which has no parameters at all. - -The listener callback function MUST NOT throw an `Exception`. -The return value of the listener callback function will be ignored and has -no effect, so for performance reasons you're recommended to not return -any excessive data structures. - -If you want to access any variables within your callback function, you -can bind arbitrary data to a callback closure like this: - -```php -$loop->addReadStream($stream, function ($stream) use ($name) { - echo $name . ' said: ' . fread($stream); -}); -``` - -See also [example #11](examples). - -You can invoke [`removeReadStream()`](#removereadstream) to remove the -read event listener for this stream. - -The execution order of listeners when multiple streams become ready at -the same time is not guaranteed. - -Some event loop implementations are known to only trigger the listener if -the stream *becomes* readable (edge-triggered) and may not trigger if the -stream has already been readable from the beginning. -This also implies that a stream may not be recognized as readable when data -is still left in PHP's internal stream buffers. -As such, it's recommended to use `stream_set_read_buffer($stream, 0);` -to disable PHP's internal read buffer in this case. - -#### addWriteStream() - -> Advanced! Note that this low-level API is considered advanced usage. - Most use cases should probably use the higher-level - [writable Stream API](https://github.com/reactphp/stream#writablestreaminterface) - instead. - -The `addWriteStream(resource $stream, callable $callback): void` method can be used to -register a listener to be notified when a stream is ready to write. - -The first parameter MUST be a valid stream resource that supports -checking whether it is ready to write by this loop implementation. -A single stream resource MUST NOT be added more than once. -Instead, either call [`removeWriteStream()`](#removewritestream) first or -react to this event with a single listener and then dispatch from this -listener. This method MAY throw an `Exception` if the given resource type -is not supported by this loop implementation. - -The second parameter MUST be a listener callback function that accepts -the stream resource as its only parameter. -If you don't use the stream resource inside your listener callback function -you MAY use a function which has no parameters at all. - -The listener callback function MUST NOT throw an `Exception`. -The return value of the listener callback function will be ignored and has -no effect, so for performance reasons you're recommended to not return -any excessive data structures. - -If you want to access any variables within your callback function, you -can bind arbitrary data to a callback closure like this: - -```php -$loop->addWriteStream($stream, function ($stream) use ($name) { - fwrite($stream, 'Hello ' . $name); -}); -``` - -See also [example #12](examples). - -You can invoke [`removeWriteStream()`](#removewritestream) to remove the -write event listener for this stream. - -The execution order of listeners when multiple streams become ready at -the same time is not guaranteed. - -#### removeReadStream() - -The `removeReadStream(resource $stream): void` method can be used to -remove the read event listener for the given stream. - -Removing a stream from the loop that has already been removed or trying -to remove a stream that was never added or is invalid has no effect. - -#### removeWriteStream() - -The `removeWriteStream(resource $stream): void` method can be used to -remove the write event listener for the given stream. - -Removing a stream from the loop that has already been removed or trying -to remove a stream that was never added or is invalid has no effect. - -## Install - -The recommended way to install this library is [through Composer](https://getcomposer.org/). -[New to Composer?](https://getcomposer.org/doc/00-intro.md) - -This project follows [SemVer](https://semver.org/). -This will install the latest supported version: - -```bash -composer require react/event-loop:^1.5 -``` - -See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades. - -This project aims to run on any platform and thus does not require any PHP -extensions and supports running on legacy PHP 5.3 through current PHP 8+ and -HHVM. -It's *highly recommended to use the latest supported PHP version* for this project. - -Installing any of the event loop extensions is suggested, but entirely optional. -See also [event loop implementations](#loop-implementations) for more details. - -## Tests - -To run the test suite, you first need to clone this repo and then install all -dependencies [through Composer](https://getcomposer.org/): - -```bash -composer install -``` - -To run the test suite, go to the project root and run: - -```bash -vendor/bin/phpunit -``` - -## License - -MIT, see [LICENSE file](LICENSE). - -## More - -* See our [Stream component](https://github.com/reactphp/stream) for more - information on how streams are used in real-world applications. -* See our [users wiki](https://github.com/reactphp/react/wiki/Users) and the - [dependents on Packagist](https://packagist.org/packages/react/event-loop/dependents) - for a list of packages that use the EventLoop in real-world applications. diff --git a/digital_doctor/vendor/react/event-loop/composer.json b/digital_doctor/vendor/react/event-loop/composer.json deleted file mode 100644 index 25a41fe..0000000 --- a/digital_doctor/vendor/react/event-loop/composer.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "name": "react/event-loop", - "description": "ReactPHP's core reactor event loop that libraries can use for evented I/O.", - "keywords": ["event-loop", "asynchronous"], - "license": "MIT", - "authors": [ - { - "name": "Christian Lück", - "homepage": "https://clue.engineering/", - "email": "christian@clue.engineering" - }, - { - "name": "Cees-Jan Kiewiet", - "homepage": "https://wyrihaximus.net/", - "email": "reactphp@ceesjankiewiet.nl" - }, - { - "name": "Jan Sorgalla", - "homepage": "https://sorgalla.com/", - "email": "jsorgalla@gmail.com" - }, - { - "name": "Chris Boden", - "homepage": "https://cboden.dev/", - "email": "cboden@gmail.com" - } - ], - "require": { - "php": ">=5.3.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" - }, - "suggest": { - "ext-pcntl": "For signal handling support when using the StreamSelectLoop" - }, - "autoload": { - "psr-4": { - "React\\EventLoop\\": "src/" - } - }, - "autoload-dev": { - "psr-4": { - "React\\Tests\\EventLoop\\": "tests/" - } - } -} diff --git a/digital_doctor/vendor/react/event-loop/src/ExtEvLoop.php b/digital_doctor/vendor/react/event-loop/src/ExtEvLoop.php deleted file mode 100644 index a3fcec6..0000000 --- a/digital_doctor/vendor/react/event-loop/src/ExtEvLoop.php +++ /dev/null @@ -1,253 +0,0 @@ -loop = new EvLoop(); - $this->futureTickQueue = new FutureTickQueue(); - $this->timers = new SplObjectStorage(); - $this->signals = new SignalsHandler(); - } - - public function addReadStream($stream, $listener) - { - $key = (int)$stream; - - if (isset($this->readStreams[$key])) { - return; - } - - $callback = $this->getStreamListenerClosure($stream, $listener); - $event = $this->loop->io($stream, Ev::READ, $callback); - $this->readStreams[$key] = $event; - } - - /** - * @param resource $stream - * @param callable $listener - * - * @return \Closure - */ - private function getStreamListenerClosure($stream, $listener) - { - return function () use ($stream, $listener) { - \call_user_func($listener, $stream); - }; - } - - public function addWriteStream($stream, $listener) - { - $key = (int)$stream; - - if (isset($this->writeStreams[$key])) { - return; - } - - $callback = $this->getStreamListenerClosure($stream, $listener); - $event = $this->loop->io($stream, Ev::WRITE, $callback); - $this->writeStreams[$key] = $event; - } - - public function removeReadStream($stream) - { - $key = (int)$stream; - - if (!isset($this->readStreams[$key])) { - return; - } - - $this->readStreams[$key]->stop(); - unset($this->readStreams[$key]); - } - - public function removeWriteStream($stream) - { - $key = (int)$stream; - - if (!isset($this->writeStreams[$key])) { - return; - } - - $this->writeStreams[$key]->stop(); - unset($this->writeStreams[$key]); - } - - public function addTimer($interval, $callback) - { - $timer = new Timer($interval, $callback, false); - - $that = $this; - $timers = $this->timers; - $callback = function () use ($timer, $timers, $that) { - \call_user_func($timer->getCallback(), $timer); - - if ($timers->contains($timer)) { - $that->cancelTimer($timer); - } - }; - - $event = $this->loop->timer($timer->getInterval(), 0.0, $callback); - $this->timers->attach($timer, $event); - - return $timer; - } - - public function addPeriodicTimer($interval, $callback) - { - $timer = new Timer($interval, $callback, true); - - $callback = function () use ($timer) { - \call_user_func($timer->getCallback(), $timer); - }; - - $event = $this->loop->timer($timer->getInterval(), $timer->getInterval(), $callback); - $this->timers->attach($timer, $event); - - return $timer; - } - - public function cancelTimer(TimerInterface $timer) - { - if (!isset($this->timers[$timer])) { - return; - } - - $event = $this->timers[$timer]; - $event->stop(); - $this->timers->detach($timer); - } - - public function futureTick($listener) - { - $this->futureTickQueue->add($listener); - } - - public function run() - { - $this->running = true; - - while ($this->running) { - $this->futureTickQueue->tick(); - - $hasPendingCallbacks = !$this->futureTickQueue->isEmpty(); - $wasJustStopped = !$this->running; - $nothingLeftToDo = !$this->readStreams - && !$this->writeStreams - && !$this->timers->count() - && $this->signals->isEmpty(); - - $flags = Ev::RUN_ONCE; - if ($wasJustStopped || $hasPendingCallbacks) { - $flags |= Ev::RUN_NOWAIT; - } elseif ($nothingLeftToDo) { - break; - } - - $this->loop->run($flags); - } - } - - public function stop() - { - $this->running = false; - } - - public function __destruct() - { - /** @var TimerInterface $timer */ - foreach ($this->timers as $timer) { - $this->cancelTimer($timer); - } - - foreach ($this->readStreams as $key => $stream) { - $this->removeReadStream($key); - } - - foreach ($this->writeStreams as $key => $stream) { - $this->removeWriteStream($key); - } - } - - public function addSignal($signal, $listener) - { - $this->signals->add($signal, $listener); - - if (!isset($this->signalEvents[$signal])) { - $this->signalEvents[$signal] = $this->loop->signal($signal, function() use ($signal) { - $this->signals->call($signal); - }); - } - } - - public function removeSignal($signal, $listener) - { - $this->signals->remove($signal, $listener); - - if (isset($this->signalEvents[$signal])) { - $this->signalEvents[$signal]->stop(); - unset($this->signalEvents[$signal]); - } - } -} diff --git a/digital_doctor/vendor/react/event-loop/src/ExtEventLoop.php b/digital_doctor/vendor/react/event-loop/src/ExtEventLoop.php deleted file mode 100644 index b162a40..0000000 --- a/digital_doctor/vendor/react/event-loop/src/ExtEventLoop.php +++ /dev/null @@ -1,275 +0,0 @@ -requireFeatures(\EventConfig::FEATURE_FDS); - } - - $this->eventBase = new EventBase($config); - $this->futureTickQueue = new FutureTickQueue(); - $this->timerEvents = new SplObjectStorage(); - $this->signals = new SignalsHandler(); - - $this->createTimerCallback(); - $this->createStreamCallback(); - } - - public function __destruct() - { - // explicitly clear all references to Event objects to prevent SEGFAULTs on Windows - foreach ($this->timerEvents as $timer) { - $this->timerEvents->detach($timer); - } - - $this->readEvents = array(); - $this->writeEvents = array(); - } - - public function addReadStream($stream, $listener) - { - $key = (int) $stream; - if (isset($this->readListeners[$key])) { - return; - } - - $event = new Event($this->eventBase, $stream, Event::PERSIST | Event::READ, $this->streamCallback); - $event->add(); - $this->readEvents[$key] = $event; - $this->readListeners[$key] = $listener; - - // ext-event does not increase refcount on stream resources for PHP 7+ - // manually keep track of stream resource to prevent premature garbage collection - if (\PHP_VERSION_ID >= 70000) { - $this->readRefs[$key] = $stream; - } - } - - public function addWriteStream($stream, $listener) - { - $key = (int) $stream; - if (isset($this->writeListeners[$key])) { - return; - } - - $event = new Event($this->eventBase, $stream, Event::PERSIST | Event::WRITE, $this->streamCallback); - $event->add(); - $this->writeEvents[$key] = $event; - $this->writeListeners[$key] = $listener; - - // ext-event does not increase refcount on stream resources for PHP 7+ - // manually keep track of stream resource to prevent premature garbage collection - if (\PHP_VERSION_ID >= 70000) { - $this->writeRefs[$key] = $stream; - } - } - - public function removeReadStream($stream) - { - $key = (int) $stream; - - if (isset($this->readEvents[$key])) { - $this->readEvents[$key]->free(); - unset( - $this->readEvents[$key], - $this->readListeners[$key], - $this->readRefs[$key] - ); - } - } - - public function removeWriteStream($stream) - { - $key = (int) $stream; - - if (isset($this->writeEvents[$key])) { - $this->writeEvents[$key]->free(); - unset( - $this->writeEvents[$key], - $this->writeListeners[$key], - $this->writeRefs[$key] - ); - } - } - - public function addTimer($interval, $callback) - { - $timer = new Timer($interval, $callback, false); - - $this->scheduleTimer($timer); - - return $timer; - } - - public function addPeriodicTimer($interval, $callback) - { - $timer = new Timer($interval, $callback, true); - - $this->scheduleTimer($timer); - - return $timer; - } - - public function cancelTimer(TimerInterface $timer) - { - if ($this->timerEvents->contains($timer)) { - $this->timerEvents[$timer]->free(); - $this->timerEvents->detach($timer); - } - } - - public function futureTick($listener) - { - $this->futureTickQueue->add($listener); - } - - public function addSignal($signal, $listener) - { - $this->signals->add($signal, $listener); - - if (!isset($this->signalEvents[$signal])) { - $this->signalEvents[$signal] = Event::signal($this->eventBase, $signal, array($this->signals, 'call')); - $this->signalEvents[$signal]->add(); - } - } - - public function removeSignal($signal, $listener) - { - $this->signals->remove($signal, $listener); - - if (isset($this->signalEvents[$signal]) && $this->signals->count($signal) === 0) { - $this->signalEvents[$signal]->free(); - unset($this->signalEvents[$signal]); - } - } - - public function run() - { - $this->running = true; - - while ($this->running) { - $this->futureTickQueue->tick(); - - $flags = EventBase::LOOP_ONCE; - if (!$this->running || !$this->futureTickQueue->isEmpty()) { - $flags |= EventBase::LOOP_NONBLOCK; - } elseif (!$this->readEvents && !$this->writeEvents && !$this->timerEvents->count() && $this->signals->isEmpty()) { - break; - } - - $this->eventBase->loop($flags); - } - } - - public function stop() - { - $this->running = false; - } - - /** - * Schedule a timer for execution. - * - * @param TimerInterface $timer - */ - private function scheduleTimer(TimerInterface $timer) - { - $flags = Event::TIMEOUT; - - if ($timer->isPeriodic()) { - $flags |= Event::PERSIST; - } - - $event = new Event($this->eventBase, -1, $flags, $this->timerCallback, $timer); - $this->timerEvents[$timer] = $event; - - $event->add($timer->getInterval()); - } - - /** - * Create a callback used as the target of timer events. - * - * A reference is kept to the callback for the lifetime of the loop - * to prevent "Cannot destroy active lambda function" fatal error from - * the event extension. - */ - private function createTimerCallback() - { - $timers = $this->timerEvents; - $this->timerCallback = function ($_, $__, $timer) use ($timers) { - \call_user_func($timer->getCallback(), $timer); - - if (!$timer->isPeriodic() && $timers->contains($timer)) { - $this->cancelTimer($timer); - } - }; - } - - /** - * Create a callback used as the target of stream events. - * - * A reference is kept to the callback for the lifetime of the loop - * to prevent "Cannot destroy active lambda function" fatal error from - * the event extension. - */ - private function createStreamCallback() - { - $read =& $this->readListeners; - $write =& $this->writeListeners; - $this->streamCallback = function ($stream, $flags) use (&$read, &$write) { - $key = (int) $stream; - - if (Event::READ === (Event::READ & $flags) && isset($read[$key])) { - \call_user_func($read[$key], $stream); - } - - if (Event::WRITE === (Event::WRITE & $flags) && isset($write[$key])) { - \call_user_func($write[$key], $stream); - } - }; - } -} diff --git a/digital_doctor/vendor/react/event-loop/src/ExtLibevLoop.php b/digital_doctor/vendor/react/event-loop/src/ExtLibevLoop.php deleted file mode 100644 index c303fdd..0000000 --- a/digital_doctor/vendor/react/event-loop/src/ExtLibevLoop.php +++ /dev/null @@ -1,201 +0,0 @@ -loop = new EventLoop(); - $this->futureTickQueue = new FutureTickQueue(); - $this->timerEvents = new SplObjectStorage(); - $this->signals = new SignalsHandler(); - } - - public function addReadStream($stream, $listener) - { - if (isset($this->readEvents[(int) $stream])) { - return; - } - - $callback = function () use ($stream, $listener) { - \call_user_func($listener, $stream); - }; - - $event = new IOEvent($callback, $stream, IOEvent::READ); - $this->loop->add($event); - - $this->readEvents[(int) $stream] = $event; - } - - public function addWriteStream($stream, $listener) - { - if (isset($this->writeEvents[(int) $stream])) { - return; - } - - $callback = function () use ($stream, $listener) { - \call_user_func($listener, $stream); - }; - - $event = new IOEvent($callback, $stream, IOEvent::WRITE); - $this->loop->add($event); - - $this->writeEvents[(int) $stream] = $event; - } - - public function removeReadStream($stream) - { - $key = (int) $stream; - - if (isset($this->readEvents[$key])) { - $this->readEvents[$key]->stop(); - $this->loop->remove($this->readEvents[$key]); - unset($this->readEvents[$key]); - } - } - - public function removeWriteStream($stream) - { - $key = (int) $stream; - - if (isset($this->writeEvents[$key])) { - $this->writeEvents[$key]->stop(); - $this->loop->remove($this->writeEvents[$key]); - unset($this->writeEvents[$key]); - } - } - - public function addTimer($interval, $callback) - { - $timer = new Timer( $interval, $callback, false); - - $that = $this; - $timers = $this->timerEvents; - $callback = function () use ($timer, $timers, $that) { - \call_user_func($timer->getCallback(), $timer); - - if ($timers->contains($timer)) { - $that->cancelTimer($timer); - } - }; - - $event = new TimerEvent($callback, $timer->getInterval()); - $this->timerEvents->attach($timer, $event); - $this->loop->add($event); - - return $timer; - } - - public function addPeriodicTimer($interval, $callback) - { - $timer = new Timer($interval, $callback, true); - - $callback = function () use ($timer) { - \call_user_func($timer->getCallback(), $timer); - }; - - $event = new TimerEvent($callback, $timer->getInterval(), $timer->getInterval()); - $this->timerEvents->attach($timer, $event); - $this->loop->add($event); - - return $timer; - } - - public function cancelTimer(TimerInterface $timer) - { - if (isset($this->timerEvents[$timer])) { - $this->loop->remove($this->timerEvents[$timer]); - $this->timerEvents->detach($timer); - } - } - - public function futureTick($listener) - { - $this->futureTickQueue->add($listener); - } - - public function addSignal($signal, $listener) - { - $this->signals->add($signal, $listener); - - if (!isset($this->signalEvents[$signal])) { - $signals = $this->signals; - $this->signalEvents[$signal] = new SignalEvent(function () use ($signals, $signal) { - $signals->call($signal); - }, $signal); - $this->loop->add($this->signalEvents[$signal]); - } - } - - public function removeSignal($signal, $listener) - { - $this->signals->remove($signal, $listener); - - if (isset($this->signalEvents[$signal]) && $this->signals->count($signal) === 0) { - $this->signalEvents[$signal]->stop(); - $this->loop->remove($this->signalEvents[$signal]); - unset($this->signalEvents[$signal]); - } - } - - public function run() - { - $this->running = true; - - while ($this->running) { - $this->futureTickQueue->tick(); - - $flags = EventLoop::RUN_ONCE; - if (!$this->running || !$this->futureTickQueue->isEmpty()) { - $flags |= EventLoop::RUN_NOWAIT; - } elseif (!$this->readEvents && !$this->writeEvents && !$this->timerEvents->count() && $this->signals->isEmpty()) { - break; - } - - $this->loop->run($flags); - } - } - - public function stop() - { - $this->running = false; - } -} diff --git a/digital_doctor/vendor/react/event-loop/src/ExtLibeventLoop.php b/digital_doctor/vendor/react/event-loop/src/ExtLibeventLoop.php deleted file mode 100644 index 099293a..0000000 --- a/digital_doctor/vendor/react/event-loop/src/ExtLibeventLoop.php +++ /dev/null @@ -1,285 +0,0 @@ -eventBase = \event_base_new(); - $this->futureTickQueue = new FutureTickQueue(); - $this->timerEvents = new SplObjectStorage(); - $this->signals = new SignalsHandler(); - - $this->createTimerCallback(); - $this->createStreamCallback(); - } - - public function addReadStream($stream, $listener) - { - $key = (int) $stream; - if (isset($this->readListeners[$key])) { - return; - } - - $event = \event_new(); - \event_set($event, $stream, \EV_PERSIST | \EV_READ, $this->streamCallback); - \event_base_set($event, $this->eventBase); - \event_add($event); - - $this->readEvents[$key] = $event; - $this->readListeners[$key] = $listener; - } - - public function addWriteStream($stream, $listener) - { - $key = (int) $stream; - if (isset($this->writeListeners[$key])) { - return; - } - - $event = \event_new(); - \event_set($event, $stream, \EV_PERSIST | \EV_WRITE, $this->streamCallback); - \event_base_set($event, $this->eventBase); - \event_add($event); - - $this->writeEvents[$key] = $event; - $this->writeListeners[$key] = $listener; - } - - public function removeReadStream($stream) - { - $key = (int) $stream; - - if (isset($this->readListeners[$key])) { - $event = $this->readEvents[$key]; - \event_del($event); - \event_free($event); - - unset( - $this->readEvents[$key], - $this->readListeners[$key] - ); - } - } - - public function removeWriteStream($stream) - { - $key = (int) $stream; - - if (isset($this->writeListeners[$key])) { - $event = $this->writeEvents[$key]; - \event_del($event); - \event_free($event); - - unset( - $this->writeEvents[$key], - $this->writeListeners[$key] - ); - } - } - - public function addTimer($interval, $callback) - { - $timer = new Timer($interval, $callback, false); - - $this->scheduleTimer($timer); - - return $timer; - } - - public function addPeriodicTimer($interval, $callback) - { - $timer = new Timer($interval, $callback, true); - - $this->scheduleTimer($timer); - - return $timer; - } - - public function cancelTimer(TimerInterface $timer) - { - if ($this->timerEvents->contains($timer)) { - $event = $this->timerEvents[$timer]; - \event_del($event); - \event_free($event); - - $this->timerEvents->detach($timer); - } - } - - public function futureTick($listener) - { - $this->futureTickQueue->add($listener); - } - - public function addSignal($signal, $listener) - { - $this->signals->add($signal, $listener); - - if (!isset($this->signalEvents[$signal])) { - $this->signalEvents[$signal] = \event_new(); - \event_set($this->signalEvents[$signal], $signal, \EV_PERSIST | \EV_SIGNAL, array($this->signals, 'call')); - \event_base_set($this->signalEvents[$signal], $this->eventBase); - \event_add($this->signalEvents[$signal]); - } - } - - public function removeSignal($signal, $listener) - { - $this->signals->remove($signal, $listener); - - if (isset($this->signalEvents[$signal]) && $this->signals->count($signal) === 0) { - \event_del($this->signalEvents[$signal]); - \event_free($this->signalEvents[$signal]); - unset($this->signalEvents[$signal]); - } - } - - public function run() - { - $this->running = true; - - while ($this->running) { - $this->futureTickQueue->tick(); - - $flags = \EVLOOP_ONCE; - if (!$this->running || !$this->futureTickQueue->isEmpty()) { - $flags |= \EVLOOP_NONBLOCK; - } elseif (!$this->readEvents && !$this->writeEvents && !$this->timerEvents->count() && $this->signals->isEmpty()) { - break; - } - - \event_base_loop($this->eventBase, $flags); - } - } - - public function stop() - { - $this->running = false; - } - - /** - * Schedule a timer for execution. - * - * @param TimerInterface $timer - */ - private function scheduleTimer(TimerInterface $timer) - { - $this->timerEvents[$timer] = $event = \event_timer_new(); - - \event_timer_set($event, $this->timerCallback, $timer); - \event_base_set($event, $this->eventBase); - \event_add($event, $timer->getInterval() * self::MICROSECONDS_PER_SECOND); - } - - /** - * Create a callback used as the target of timer events. - * - * A reference is kept to the callback for the lifetime of the loop - * to prevent "Cannot destroy active lambda function" fatal error from - * the event extension. - */ - private function createTimerCallback() - { - $that = $this; - $timers = $this->timerEvents; - $this->timerCallback = function ($_, $__, $timer) use ($timers, $that) { - \call_user_func($timer->getCallback(), $timer); - - // Timer already cancelled ... - if (!$timers->contains($timer)) { - return; - } - - // Reschedule periodic timers ... - if ($timer->isPeriodic()) { - \event_add( - $timers[$timer], - $timer->getInterval() * ExtLibeventLoop::MICROSECONDS_PER_SECOND - ); - - // Clean-up one shot timers ... - } else { - $that->cancelTimer($timer); - } - }; - } - - /** - * Create a callback used as the target of stream events. - * - * A reference is kept to the callback for the lifetime of the loop - * to prevent "Cannot destroy active lambda function" fatal error from - * the event extension. - */ - private function createStreamCallback() - { - $read =& $this->readListeners; - $write =& $this->writeListeners; - $this->streamCallback = function ($stream, $flags) use (&$read, &$write) { - $key = (int) $stream; - - if (\EV_READ === (\EV_READ & $flags) && isset($read[$key])) { - \call_user_func($read[$key], $stream); - } - - if (\EV_WRITE === (\EV_WRITE & $flags) && isset($write[$key])) { - \call_user_func($write[$key], $stream); - } - }; - } -} diff --git a/digital_doctor/vendor/react/event-loop/src/ExtUvLoop.php b/digital_doctor/vendor/react/event-loop/src/ExtUvLoop.php deleted file mode 100644 index 4434720..0000000 --- a/digital_doctor/vendor/react/event-loop/src/ExtUvLoop.php +++ /dev/null @@ -1,342 +0,0 @@ -uv = \uv_loop_new(); - $this->futureTickQueue = new FutureTickQueue(); - $this->timers = new SplObjectStorage(); - $this->streamListener = $this->createStreamListener(); - $this->signals = new SignalsHandler(); - } - - /** - * Returns the underlying ext-uv event loop. (Internal ReactPHP use only.) - * - * @internal - * - * @return resource - */ - public function getUvLoop() - { - return $this->uv; - } - - /** - * {@inheritdoc} - */ - public function addReadStream($stream, $listener) - { - if (isset($this->readStreams[(int) $stream])) { - return; - } - - $this->readStreams[(int) $stream] = $listener; - $this->addStream($stream); - } - - /** - * {@inheritdoc} - */ - public function addWriteStream($stream, $listener) - { - if (isset($this->writeStreams[(int) $stream])) { - return; - } - - $this->writeStreams[(int) $stream] = $listener; - $this->addStream($stream); - } - - /** - * {@inheritdoc} - */ - public function removeReadStream($stream) - { - if (!isset($this->streamEvents[(int) $stream])) { - return; - } - - unset($this->readStreams[(int) $stream]); - $this->removeStream($stream); - } - - /** - * {@inheritdoc} - */ - public function removeWriteStream($stream) - { - if (!isset($this->streamEvents[(int) $stream])) { - return; - } - - unset($this->writeStreams[(int) $stream]); - $this->removeStream($stream); - } - - /** - * {@inheritdoc} - */ - public function addTimer($interval, $callback) - { - $timer = new Timer($interval, $callback, false); - - $that = $this; - $timers = $this->timers; - $callback = function () use ($timer, $timers, $that) { - \call_user_func($timer->getCallback(), $timer); - - if ($timers->contains($timer)) { - $that->cancelTimer($timer); - } - }; - - $event = \uv_timer_init($this->uv); - $this->timers->attach($timer, $event); - \uv_timer_start( - $event, - $this->convertFloatSecondsToMilliseconds($interval), - 0, - $callback - ); - - return $timer; - } - - /** - * {@inheritdoc} - */ - public function addPeriodicTimer($interval, $callback) - { - $timer = new Timer($interval, $callback, true); - - $callback = function () use ($timer) { - \call_user_func($timer->getCallback(), $timer); - }; - - $interval = $this->convertFloatSecondsToMilliseconds($interval); - $event = \uv_timer_init($this->uv); - $this->timers->attach($timer, $event); - \uv_timer_start( - $event, - $interval, - (int) $interval === 0 ? 1 : $interval, - $callback - ); - - return $timer; - } - - /** - * {@inheritdoc} - */ - public function cancelTimer(TimerInterface $timer) - { - if (isset($this->timers[$timer])) { - @\uv_timer_stop($this->timers[$timer]); - $this->timers->detach($timer); - } - } - - /** - * {@inheritdoc} - */ - public function futureTick($listener) - { - $this->futureTickQueue->add($listener); - } - - public function addSignal($signal, $listener) - { - $this->signals->add($signal, $listener); - - if (!isset($this->signalEvents[$signal])) { - $signals = $this->signals; - $this->signalEvents[$signal] = \uv_signal_init($this->uv); - \uv_signal_start($this->signalEvents[$signal], function () use ($signals, $signal) { - $signals->call($signal); - }, $signal); - } - } - - public function removeSignal($signal, $listener) - { - $this->signals->remove($signal, $listener); - - if (isset($this->signalEvents[$signal]) && $this->signals->count($signal) === 0) { - \uv_signal_stop($this->signalEvents[$signal]); - unset($this->signalEvents[$signal]); - } - } - - /** - * {@inheritdoc} - */ - public function run() - { - $this->running = true; - - while ($this->running) { - $this->futureTickQueue->tick(); - - $hasPendingCallbacks = !$this->futureTickQueue->isEmpty(); - $wasJustStopped = !$this->running; - $nothingLeftToDo = !$this->readStreams - && !$this->writeStreams - && !$this->timers->count() - && $this->signals->isEmpty(); - - // Use UV::RUN_ONCE when there are only I/O events active in the loop and block until one of those triggers, - // otherwise use UV::RUN_NOWAIT. - // @link http://docs.libuv.org/en/v1.x/loop.html#c.uv_run - $flags = \UV::RUN_ONCE; - if ($wasJustStopped || $hasPendingCallbacks) { - $flags = \UV::RUN_NOWAIT; - } elseif ($nothingLeftToDo) { - break; - } - - \uv_run($this->uv, $flags); - } - } - - /** - * {@inheritdoc} - */ - public function stop() - { - $this->running = false; - } - - private function addStream($stream) - { - if (!isset($this->streamEvents[(int) $stream])) { - $this->streamEvents[(int)$stream] = \uv_poll_init_socket($this->uv, $stream); - } - - if ($this->streamEvents[(int) $stream] !== false) { - $this->pollStream($stream); - } - } - - private function removeStream($stream) - { - if (!isset($this->streamEvents[(int) $stream])) { - return; - } - - if (!isset($this->readStreams[(int) $stream]) - && !isset($this->writeStreams[(int) $stream])) { - \uv_poll_stop($this->streamEvents[(int) $stream]); - \uv_close($this->streamEvents[(int) $stream]); - unset($this->streamEvents[(int) $stream]); - return; - } - - $this->pollStream($stream); - } - - private function pollStream($stream) - { - if (!isset($this->streamEvents[(int) $stream])) { - return; - } - - $flags = 0; - if (isset($this->readStreams[(int) $stream])) { - $flags |= \UV::READABLE; - } - - if (isset($this->writeStreams[(int) $stream])) { - $flags |= \UV::WRITABLE; - } - - \uv_poll_start($this->streamEvents[(int) $stream], $flags, $this->streamListener); - } - - /** - * Create a stream listener - * - * @return callable Returns a callback - */ - private function createStreamListener() - { - $callback = function ($event, $status, $events, $stream) { - // libuv automatically stops polling on error, re-enable polling to match other loop implementations - if ($status !== 0) { - $this->pollStream($stream); - - // libuv may report no events on error, but this should still invoke stream listeners to report closed connections - // re-enable both readable and writable, correct listeners will be checked below anyway - if ($events === 0) { - $events = \UV::READABLE | \UV::WRITABLE; - } - } - - if (isset($this->readStreams[(int) $stream]) && ($events & \UV::READABLE)) { - \call_user_func($this->readStreams[(int) $stream], $stream); - } - - if (isset($this->writeStreams[(int) $stream]) && ($events & \UV::WRITABLE)) { - \call_user_func($this->writeStreams[(int) $stream], $stream); - } - }; - - return $callback; - } - - /** - * @param float $interval - * @return int - */ - private function convertFloatSecondsToMilliseconds($interval) - { - if ($interval < 0) { - return 0; - } - - $maxValue = (int) (\PHP_INT_MAX / 1000); - $intInterval = (int) $interval; - - if (($intInterval <= 0 && $interval > 1) || $intInterval >= $maxValue) { - throw new \InvalidArgumentException( - "Interval overflow, value must be lower than '{$maxValue}', but '{$interval}' passed." - ); - } - - return (int) \floor($interval * 1000); - } -} diff --git a/digital_doctor/vendor/react/event-loop/src/Factory.php b/digital_doctor/vendor/react/event-loop/src/Factory.php deleted file mode 100644 index 30bbfd7..0000000 --- a/digital_doctor/vendor/react/event-loop/src/Factory.php +++ /dev/null @@ -1,75 +0,0 @@ -futureTick(function () use (&$hasRun) { - $hasRun = true; - }); - - $stopped =& self::$stopped; - register_shutdown_function(function () use ($loop, &$hasRun, &$stopped) { - // Don't run if we're coming from a fatal error (uncaught exception). - $error = error_get_last(); - if ((isset($error['type']) ? $error['type'] : 0) & (E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR)) { - return; - } - - if (!$hasRun && !$stopped) { - $loop->run(); - } - }); - // @codeCoverageIgnoreEnd - - return self::$instance; - } - - /** - * Internal undocumented method, behavior might change or throw in the - * future. Use with caution and at your own risk. - * - * @internal - * @return void - */ - public static function set(LoopInterface $loop) - { - self::$instance = $loop; - } - - /** - * [Advanced] Register a listener to be notified when a stream is ready to read. - * - * @param resource $stream - * @param callable $listener - * @return void - * @throws \Exception - * @see LoopInterface::addReadStream() - */ - public static function addReadStream($stream, $listener) - { - // create loop instance on demand (legacy PHP < 7 doesn't like ternaries in method calls) - if (self::$instance === null) { - self::get(); - } - self::$instance->addReadStream($stream, $listener); - } - - /** - * [Advanced] Register a listener to be notified when a stream is ready to write. - * - * @param resource $stream - * @param callable $listener - * @return void - * @throws \Exception - * @see LoopInterface::addWriteStream() - */ - public static function addWriteStream($stream, $listener) - { - // create loop instance on demand (legacy PHP < 7 doesn't like ternaries in method calls) - if (self::$instance === null) { - self::get(); - } - self::$instance->addWriteStream($stream, $listener); - } - - /** - * Remove the read event listener for the given stream. - * - * @param resource $stream - * @return void - * @see LoopInterface::removeReadStream() - */ - public static function removeReadStream($stream) - { - if (self::$instance !== null) { - self::$instance->removeReadStream($stream); - } - } - - /** - * Remove the write event listener for the given stream. - * - * @param resource $stream - * @return void - * @see LoopInterface::removeWriteStream() - */ - public static function removeWriteStream($stream) - { - if (self::$instance !== null) { - self::$instance->removeWriteStream($stream); - } - } - - /** - * Enqueue a callback to be invoked once after the given interval. - * - * @param float $interval - * @param callable $callback - * @return TimerInterface - * @see LoopInterface::addTimer() - */ - public static function addTimer($interval, $callback) - { - // create loop instance on demand (legacy PHP < 7 doesn't like ternaries in method calls) - if (self::$instance === null) { - self::get(); - } - return self::$instance->addTimer($interval, $callback); - } - - /** - * Enqueue a callback to be invoked repeatedly after the given interval. - * - * @param float $interval - * @param callable $callback - * @return TimerInterface - * @see LoopInterface::addPeriodicTimer() - */ - public static function addPeriodicTimer($interval, $callback) - { - // create loop instance on demand (legacy PHP < 7 doesn't like ternaries in method calls) - if (self::$instance === null) { - self::get(); - } - return self::$instance->addPeriodicTimer($interval, $callback); - } - - /** - * Cancel a pending timer. - * - * @param TimerInterface $timer - * @return void - * @see LoopInterface::cancelTimer() - */ - public static function cancelTimer(TimerInterface $timer) - { - if (self::$instance !== null) { - self::$instance->cancelTimer($timer); - } - } - - /** - * Schedule a callback to be invoked on a future tick of the event loop. - * - * @param callable $listener - * @return void - * @see LoopInterface::futureTick() - */ - public static function futureTick($listener) - { - // create loop instance on demand (legacy PHP < 7 doesn't like ternaries in method calls) - if (self::$instance === null) { - self::get(); - } - - self::$instance->futureTick($listener); - } - - /** - * Register a listener to be notified when a signal has been caught by this process. - * - * @param int $signal - * @param callable $listener - * @return void - * @see LoopInterface::addSignal() - */ - public static function addSignal($signal, $listener) - { - // create loop instance on demand (legacy PHP < 7 doesn't like ternaries in method calls) - if (self::$instance === null) { - self::get(); - } - - self::$instance->addSignal($signal, $listener); - } - - /** - * Removes a previously added signal listener. - * - * @param int $signal - * @param callable $listener - * @return void - * @see LoopInterface::removeSignal() - */ - public static function removeSignal($signal, $listener) - { - if (self::$instance !== null) { - self::$instance->removeSignal($signal, $listener); - } - } - - /** - * Run the event loop until there are no more tasks to perform. - * - * @return void - * @see LoopInterface::run() - */ - public static function run() - { - // create loop instance on demand (legacy PHP < 7 doesn't like ternaries in method calls) - if (self::$instance === null) { - self::get(); - } - - self::$instance->run(); - } - - /** - * Instruct a running event loop to stop. - * - * @return void - * @see LoopInterface::stop() - */ - public static function stop() - { - self::$stopped = true; - if (self::$instance !== null) { - self::$instance->stop(); - } - } -} diff --git a/digital_doctor/vendor/react/event-loop/src/LoopInterface.php b/digital_doctor/vendor/react/event-loop/src/LoopInterface.php deleted file mode 100644 index 9266f71..0000000 --- a/digital_doctor/vendor/react/event-loop/src/LoopInterface.php +++ /dev/null @@ -1,472 +0,0 @@ -addReadStream($stream, function ($stream) use ($name) { - * echo $name . ' said: ' . fread($stream); - * }); - * ``` - * - * See also [example #11](examples). - * - * You can invoke [`removeReadStream()`](#removereadstream) to remove the - * read event listener for this stream. - * - * The execution order of listeners when multiple streams become ready at - * the same time is not guaranteed. - * - * @param resource $stream The PHP stream resource to check. - * @param callable $listener Invoked when the stream is ready. - * @throws \Exception if the given resource type is not supported by this loop implementation - * @see self::removeReadStream() - */ - public function addReadStream($stream, $listener); - - /** - * [Advanced] Register a listener to be notified when a stream is ready to write. - * - * Note that this low-level API is considered advanced usage. - * Most use cases should probably use the higher-level - * [writable Stream API](https://github.com/reactphp/stream#writablestreaminterface) - * instead. - * - * The first parameter MUST be a valid stream resource that supports - * checking whether it is ready to write by this loop implementation. - * A single stream resource MUST NOT be added more than once. - * Instead, either call [`removeWriteStream()`](#removewritestream) first or - * react to this event with a single listener and then dispatch from this - * listener. This method MAY throw an `Exception` if the given resource type - * is not supported by this loop implementation. - * - * The second parameter MUST be a listener callback function that accepts - * the stream resource as its only parameter. - * If you don't use the stream resource inside your listener callback function - * you MAY use a function which has no parameters at all. - * - * The listener callback function MUST NOT throw an `Exception`. - * The return value of the listener callback function will be ignored and has - * no effect, so for performance reasons you're recommended to not return - * any excessive data structures. - * - * If you want to access any variables within your callback function, you - * can bind arbitrary data to a callback closure like this: - * - * ```php - * $loop->addWriteStream($stream, function ($stream) use ($name) { - * fwrite($stream, 'Hello ' . $name); - * }); - * ``` - * - * See also [example #12](examples). - * - * You can invoke [`removeWriteStream()`](#removewritestream) to remove the - * write event listener for this stream. - * - * The execution order of listeners when multiple streams become ready at - * the same time is not guaranteed. - * - * Some event loop implementations are known to only trigger the listener if - * the stream *becomes* readable (edge-triggered) and may not trigger if the - * stream has already been readable from the beginning. - * This also implies that a stream may not be recognized as readable when data - * is still left in PHP's internal stream buffers. - * As such, it's recommended to use `stream_set_read_buffer($stream, 0);` - * to disable PHP's internal read buffer in this case. - * - * @param resource $stream The PHP stream resource to check. - * @param callable $listener Invoked when the stream is ready. - * @throws \Exception if the given resource type is not supported by this loop implementation - * @see self::removeWriteStream() - */ - public function addWriteStream($stream, $listener); - - /** - * Remove the read event listener for the given stream. - * - * Removing a stream from the loop that has already been removed or trying - * to remove a stream that was never added or is invalid has no effect. - * - * @param resource $stream The PHP stream resource. - */ - public function removeReadStream($stream); - - /** - * Remove the write event listener for the given stream. - * - * Removing a stream from the loop that has already been removed or trying - * to remove a stream that was never added or is invalid has no effect. - * - * @param resource $stream The PHP stream resource. - */ - public function removeWriteStream($stream); - - /** - * Enqueue a callback to be invoked once after the given interval. - * - * The second parameter MUST be a timer callback function that accepts - * the timer instance as its only parameter. - * If you don't use the timer instance inside your timer callback function - * you MAY use a function which has no parameters at all. - * - * The timer callback function MUST NOT throw an `Exception`. - * The return value of the timer callback function will be ignored and has - * no effect, so for performance reasons you're recommended to not return - * any excessive data structures. - * - * This method returns a timer instance. The same timer instance will also be - * passed into the timer callback function as described above. - * You can invoke [`cancelTimer`](#canceltimer) to cancel a pending timer. - * Unlike [`addPeriodicTimer()`](#addperiodictimer), this method will ensure - * the callback will be invoked only once after the given interval. - * - * ```php - * $loop->addTimer(0.8, function () { - * echo 'world!' . PHP_EOL; - * }); - * - * $loop->addTimer(0.3, function () { - * echo 'hello '; - * }); - * ``` - * - * See also [example #1](examples). - * - * If you want to access any variables within your callback function, you - * can bind arbitrary data to a callback closure like this: - * - * ```php - * function hello($name, LoopInterface $loop) - * { - * $loop->addTimer(1.0, function () use ($name) { - * echo "hello $name\n"; - * }); - * } - * - * hello('Tester', $loop); - * ``` - * - * This interface does not enforce any particular timer resolution, so - * special care may have to be taken if you rely on very high precision with - * millisecond accuracy or below. Event loop implementations SHOULD work on - * a best effort basis and SHOULD provide at least millisecond accuracy - * unless otherwise noted. Many existing event loop implementations are - * known to provide microsecond accuracy, but it's generally not recommended - * to rely on this high precision. - * - * Similarly, the execution order of timers scheduled to execute at the - * same time (within its possible accuracy) is not guaranteed. - * - * This interface suggests that event loop implementations SHOULD use a - * monotonic time source if available. Given that a monotonic time source is - * only available as of PHP 7.3 by default, event loop implementations MAY - * fall back to using wall-clock time. - * While this does not affect many common use cases, this is an important - * distinction for programs that rely on a high time precision or on systems - * that are subject to discontinuous time adjustments (time jumps). - * This means that if you schedule a timer to trigger in 30s and then adjust - * your system time forward by 20s, the timer SHOULD still trigger in 30s. - * See also [event loop implementations](#loop-implementations) for more details. - * - * @param int|float $interval The number of seconds to wait before execution. - * @param callable $callback The callback to invoke. - * - * @return TimerInterface - */ - public function addTimer($interval, $callback); - - /** - * Enqueue a callback to be invoked repeatedly after the given interval. - * - * The second parameter MUST be a timer callback function that accepts - * the timer instance as its only parameter. - * If you don't use the timer instance inside your timer callback function - * you MAY use a function which has no parameters at all. - * - * The timer callback function MUST NOT throw an `Exception`. - * The return value of the timer callback function will be ignored and has - * no effect, so for performance reasons you're recommended to not return - * any excessive data structures. - * - * This method returns a timer instance. The same timer instance will also be - * passed into the timer callback function as described above. - * Unlike [`addTimer()`](#addtimer), this method will ensure the callback - * will be invoked infinitely after the given interval or until you invoke - * [`cancelTimer`](#canceltimer). - * - * ```php - * $timer = $loop->addPeriodicTimer(0.1, function () { - * echo 'tick!' . PHP_EOL; - * }); - * - * $loop->addTimer(1.0, function () use ($loop, $timer) { - * $loop->cancelTimer($timer); - * echo 'Done' . PHP_EOL; - * }); - * ``` - * - * See also [example #2](examples). - * - * If you want to limit the number of executions, you can bind - * arbitrary data to a callback closure like this: - * - * ```php - * function hello($name, LoopInterface $loop) - * { - * $n = 3; - * $loop->addPeriodicTimer(1.0, function ($timer) use ($name, $loop, &$n) { - * if ($n > 0) { - * --$n; - * echo "hello $name\n"; - * } else { - * $loop->cancelTimer($timer); - * } - * }); - * } - * - * hello('Tester', $loop); - * ``` - * - * This interface does not enforce any particular timer resolution, so - * special care may have to be taken if you rely on very high precision with - * millisecond accuracy or below. Event loop implementations SHOULD work on - * a best effort basis and SHOULD provide at least millisecond accuracy - * unless otherwise noted. Many existing event loop implementations are - * known to provide microsecond accuracy, but it's generally not recommended - * to rely on this high precision. - * - * Similarly, the execution order of timers scheduled to execute at the - * same time (within its possible accuracy) is not guaranteed. - * - * This interface suggests that event loop implementations SHOULD use a - * monotonic time source if available. Given that a monotonic time source is - * only available as of PHP 7.3 by default, event loop implementations MAY - * fall back to using wall-clock time. - * While this does not affect many common use cases, this is an important - * distinction for programs that rely on a high time precision or on systems - * that are subject to discontinuous time adjustments (time jumps). - * This means that if you schedule a timer to trigger in 30s and then adjust - * your system time forward by 20s, the timer SHOULD still trigger in 30s. - * See also [event loop implementations](#loop-implementations) for more details. - * - * Additionally, periodic timers may be subject to timer drift due to - * re-scheduling after each invocation. As such, it's generally not - * recommended to rely on this for high precision intervals with millisecond - * accuracy or below. - * - * @param int|float $interval The number of seconds to wait before execution. - * @param callable $callback The callback to invoke. - * - * @return TimerInterface - */ - public function addPeriodicTimer($interval, $callback); - - /** - * Cancel a pending timer. - * - * See also [`addPeriodicTimer()`](#addperiodictimer) and [example #2](examples). - * - * Calling this method on a timer instance that has not been added to this - * loop instance or on a timer that has already been cancelled has no effect. - * - * @param TimerInterface $timer The timer to cancel. - * - * @return void - */ - public function cancelTimer(TimerInterface $timer); - - /** - * Schedule a callback to be invoked on a future tick of the event loop. - * - * This works very much similar to timers with an interval of zero seconds, - * but does not require the overhead of scheduling a timer queue. - * - * The tick callback function MUST be able to accept zero parameters. - * - * The tick callback function MUST NOT throw an `Exception`. - * The return value of the tick callback function will be ignored and has - * no effect, so for performance reasons you're recommended to not return - * any excessive data structures. - * - * If you want to access any variables within your callback function, you - * can bind arbitrary data to a callback closure like this: - * - * ```php - * function hello($name, LoopInterface $loop) - * { - * $loop->futureTick(function () use ($name) { - * echo "hello $name\n"; - * }); - * } - * - * hello('Tester', $loop); - * ``` - * - * Unlike timers, tick callbacks are guaranteed to be executed in the order - * they are enqueued. - * Also, once a callback is enqueued, there's no way to cancel this operation. - * - * This is often used to break down bigger tasks into smaller steps (a form - * of cooperative multitasking). - * - * ```php - * $loop->futureTick(function () { - * echo 'b'; - * }); - * $loop->futureTick(function () { - * echo 'c'; - * }); - * echo 'a'; - * ``` - * - * See also [example #3](examples). - * - * @param callable $listener The callback to invoke. - * - * @return void - */ - public function futureTick($listener); - - /** - * Register a listener to be notified when a signal has been caught by this process. - * - * This is useful to catch user interrupt signals or shutdown signals from - * tools like `supervisor` or `systemd`. - * - * The second parameter MUST be a listener callback function that accepts - * the signal as its only parameter. - * If you don't use the signal inside your listener callback function - * you MAY use a function which has no parameters at all. - * - * The listener callback function MUST NOT throw an `Exception`. - * The return value of the listener callback function will be ignored and has - * no effect, so for performance reasons you're recommended to not return - * any excessive data structures. - * - * ```php - * $loop->addSignal(SIGINT, function (int $signal) { - * echo 'Caught user interrupt signal' . PHP_EOL; - * }); - * ``` - * - * See also [example #4](examples). - * - * Signaling is only available on Unix-like platforms, Windows isn't - * supported due to operating system limitations. - * This method may throw a `BadMethodCallException` if signals aren't - * supported on this platform, for example when required extensions are - * missing. - * - * **Note: A listener can only be added once to the same signal, any - * attempts to add it more than once will be ignored.** - * - * @param int $signal - * @param callable $listener - * - * @throws \BadMethodCallException when signals aren't supported on this - * platform, for example when required extensions are missing. - * - * @return void - */ - public function addSignal($signal, $listener); - - /** - * Removes a previously added signal listener. - * - * ```php - * $loop->removeSignal(SIGINT, $listener); - * ``` - * - * Any attempts to remove listeners that aren't registered will be ignored. - * - * @param int $signal - * @param callable $listener - * - * @return void - */ - public function removeSignal($signal, $listener); - - /** - * Run the event loop until there are no more tasks to perform. - * - * For many applications, this method is the only directly visible - * invocation on the event loop. - * As a rule of thumb, it is usually recommended to attach everything to the - * same loop instance and then run the loop once at the bottom end of the - * application. - * - * ```php - * $loop->run(); - * ``` - * - * This method will keep the loop running until there are no more tasks - * to perform. In other words: This method will block until the last - * timer, stream and/or signal has been removed. - * - * Likewise, it is imperative to ensure the application actually invokes - * this method once. Adding listeners to the loop and missing to actually - * run it will result in the application exiting without actually waiting - * for any of the attached listeners. - * - * This method MUST NOT be called while the loop is already running. - * This method MAY be called more than once after it has explicitly been - * [`stop()`ped](#stop) or after it automatically stopped because it - * previously did no longer have anything to do. - * - * @return void - */ - public function run(); - - /** - * Instruct a running event loop to stop. - * - * This method is considered advanced usage and should be used with care. - * As a rule of thumb, it is usually recommended to let the loop stop - * only automatically when it no longer has anything to do. - * - * This method can be used to explicitly instruct the event loop to stop: - * - * ```php - * $loop->addTimer(3.0, function () use ($loop) { - * $loop->stop(); - * }); - * ``` - * - * Calling this method on a loop instance that is not currently running or - * on a loop instance that has already been stopped has no effect. - * - * @return void - */ - public function stop(); -} diff --git a/digital_doctor/vendor/react/event-loop/src/SignalsHandler.php b/digital_doctor/vendor/react/event-loop/src/SignalsHandler.php deleted file mode 100644 index 10d125d..0000000 --- a/digital_doctor/vendor/react/event-loop/src/SignalsHandler.php +++ /dev/null @@ -1,63 +0,0 @@ -signals[$signal])) { - $this->signals[$signal] = array(); - } - - if (\in_array($listener, $this->signals[$signal])) { - return; - } - - $this->signals[$signal][] = $listener; - } - - public function remove($signal, $listener) - { - if (!isset($this->signals[$signal])) { - return; - } - - $index = \array_search($listener, $this->signals[$signal], true); - unset($this->signals[$signal][$index]); - - if (isset($this->signals[$signal]) && \count($this->signals[$signal]) === 0) { - unset($this->signals[$signal]); - } - } - - public function call($signal) - { - if (!isset($this->signals[$signal])) { - return; - } - - foreach ($this->signals[$signal] as $listener) { - \call_user_func($listener, $signal); - } - } - - public function count($signal) - { - if (!isset($this->signals[$signal])) { - return 0; - } - - return \count($this->signals[$signal]); - } - - public function isEmpty() - { - return !$this->signals; - } -} diff --git a/digital_doctor/vendor/react/event-loop/src/StreamSelectLoop.php b/digital_doctor/vendor/react/event-loop/src/StreamSelectLoop.php deleted file mode 100644 index 1686fd7..0000000 --- a/digital_doctor/vendor/react/event-loop/src/StreamSelectLoop.php +++ /dev/null @@ -1,330 +0,0 @@ -futureTickQueue = new FutureTickQueue(); - $this->timers = new Timers(); - $this->pcntl = \function_exists('pcntl_signal') && \function_exists('pcntl_signal_dispatch'); - $this->pcntlPoll = $this->pcntl && !\function_exists('pcntl_async_signals'); - $this->signals = new SignalsHandler(); - - // prefer async signals if available (PHP 7.1+) or fall back to dispatching on each tick - if ($this->pcntl && !$this->pcntlPoll) { - \pcntl_async_signals(true); - } - } - - public function addReadStream($stream, $listener) - { - $key = (int) $stream; - - if (!isset($this->readStreams[$key])) { - $this->readStreams[$key] = $stream; - $this->readListeners[$key] = $listener; - } - } - - public function addWriteStream($stream, $listener) - { - $key = (int) $stream; - - if (!isset($this->writeStreams[$key])) { - $this->writeStreams[$key] = $stream; - $this->writeListeners[$key] = $listener; - } - } - - public function removeReadStream($stream) - { - $key = (int) $stream; - - unset( - $this->readStreams[$key], - $this->readListeners[$key] - ); - } - - public function removeWriteStream($stream) - { - $key = (int) $stream; - - unset( - $this->writeStreams[$key], - $this->writeListeners[$key] - ); - } - - public function addTimer($interval, $callback) - { - $timer = new Timer($interval, $callback, false); - - $this->timers->add($timer); - - return $timer; - } - - public function addPeriodicTimer($interval, $callback) - { - $timer = new Timer($interval, $callback, true); - - $this->timers->add($timer); - - return $timer; - } - - public function cancelTimer(TimerInterface $timer) - { - $this->timers->cancel($timer); - } - - public function futureTick($listener) - { - $this->futureTickQueue->add($listener); - } - - public function addSignal($signal, $listener) - { - if ($this->pcntl === false) { - throw new \BadMethodCallException('Event loop feature "signals" isn\'t supported by the "StreamSelectLoop"'); - } - - $first = $this->signals->count($signal) === 0; - $this->signals->add($signal, $listener); - - if ($first) { - \pcntl_signal($signal, array($this->signals, 'call')); - } - } - - public function removeSignal($signal, $listener) - { - if (!$this->signals->count($signal)) { - return; - } - - $this->signals->remove($signal, $listener); - - if ($this->signals->count($signal) === 0) { - \pcntl_signal($signal, \SIG_DFL); - } - } - - public function run() - { - $this->running = true; - - while ($this->running) { - $this->futureTickQueue->tick(); - - $this->timers->tick(); - - // Future-tick queue has pending callbacks ... - if (!$this->running || !$this->futureTickQueue->isEmpty()) { - $timeout = 0; - - // There is a pending timer, only block until it is due ... - } elseif ($scheduledAt = $this->timers->getFirst()) { - $timeout = $scheduledAt - $this->timers->getTime(); - if ($timeout < 0) { - $timeout = 0; - } else { - // Convert float seconds to int microseconds. - // Ensure we do not exceed maximum integer size, which may - // cause the loop to tick once every ~35min on 32bit systems. - $timeout *= self::MICROSECONDS_PER_SECOND; - $timeout = $timeout > \PHP_INT_MAX ? \PHP_INT_MAX : (int)$timeout; - } - - // The only possible event is stream or signal activity, so wait forever ... - } elseif ($this->readStreams || $this->writeStreams || !$this->signals->isEmpty()) { - $timeout = null; - - // There's nothing left to do ... - } else { - break; - } - - $this->waitForStreamActivity($timeout); - } - } - - public function stop() - { - $this->running = false; - } - - /** - * Wait/check for stream activity, or until the next timer is due. - * - * @param integer|null $timeout Activity timeout in microseconds, or null to wait forever. - */ - private function waitForStreamActivity($timeout) - { - $read = $this->readStreams; - $write = $this->writeStreams; - - $available = $this->streamSelect($read, $write, $timeout); - if ($this->pcntlPoll) { - \pcntl_signal_dispatch(); - } - if (false === $available) { - // if a system call has been interrupted, - // we cannot rely on it's outcome - return; - } - - foreach ($read as $stream) { - $key = (int) $stream; - - if (isset($this->readListeners[$key])) { - \call_user_func($this->readListeners[$key], $stream); - } - } - - foreach ($write as $stream) { - $key = (int) $stream; - - if (isset($this->writeListeners[$key])) { - \call_user_func($this->writeListeners[$key], $stream); - } - } - } - - /** - * Emulate a stream_select() implementation that does not break when passed - * empty stream arrays. - * - * @param array $read An array of read streams to select upon. - * @param array $write An array of write streams to select upon. - * @param int|null $timeout Activity timeout in microseconds, or null to wait forever. - * - * @return int|false The total number of streams that are ready for read/write. - * Can return false if stream_select() is interrupted by a signal. - */ - private function streamSelect(array &$read, array &$write, $timeout) - { - if ($read || $write) { - // We do not usually use or expose the `exceptfds` parameter passed to the underlying `select`. - // However, Windows does not report failed connection attempts in `writefds` passed to `select` like most other platforms. - // Instead, it uses `writefds` only for successful connection attempts and `exceptfds` for failed connection attempts. - // We work around this by adding all sockets that look like a pending connection attempt to `exceptfds` automatically on Windows and merge it back later. - // This ensures the public API matches other loop implementations across all platforms (see also test suite or rather test matrix). - // Lacking better APIs, every write-only socket that has not yet read any data is assumed to be in a pending connection attempt state. - // @link https://docs.microsoft.com/de-de/windows/win32/api/winsock2/nf-winsock2-select - $except = null; - if (\DIRECTORY_SEPARATOR === '\\') { - $except = array(); - foreach ($write as $key => $socket) { - if (!isset($read[$key]) && @\ftell($socket) === 0) { - $except[$key] = $socket; - } - } - } - - /** @var ?callable $previous */ - $previous = \set_error_handler(function ($errno, $errstr) use (&$previous) { - // suppress warnings that occur when `stream_select()` is interrupted by a signal - // PHP defines `EINTR` through `ext-sockets` or `ext-pcntl`, otherwise use common default (Linux & Mac) - $eintr = \defined('SOCKET_EINTR') ? \SOCKET_EINTR : (\defined('PCNTL_EINTR') ? \PCNTL_EINTR : 4); - if ($errno === \E_WARNING && \strpos($errstr, '[' . $eintr .']: ') !== false) { - return; - } - - // forward any other error to registered error handler or print warning - return ($previous !== null) ? \call_user_func_array($previous, \func_get_args()) : false; - }); - - try { - $ret = \stream_select($read, $write, $except, $timeout === null ? null : 0, $timeout); - \restore_error_handler(); - } catch (\Throwable $e) { // @codeCoverageIgnoreStart - \restore_error_handler(); - throw $e; - } catch (\Exception $e) { - \restore_error_handler(); - throw $e; - } // @codeCoverageIgnoreEnd - - if ($except) { - $write = \array_merge($write, $except); - } - return $ret; - } - - if ($timeout > 0) { - \usleep($timeout); - } elseif ($timeout === null) { - // wait forever (we only reach this if we're only awaiting signals) - // this may be interrupted and return earlier when a signal is received - \sleep(PHP_INT_MAX); - } - - return 0; - } -} diff --git a/digital_doctor/vendor/react/event-loop/src/Tick/FutureTickQueue.php b/digital_doctor/vendor/react/event-loop/src/Tick/FutureTickQueue.php deleted file mode 100644 index efabcbc..0000000 --- a/digital_doctor/vendor/react/event-loop/src/Tick/FutureTickQueue.php +++ /dev/null @@ -1,60 +0,0 @@ -queue = new SplQueue(); - } - - /** - * Add a callback to be invoked on a future tick of the event loop. - * - * Callbacks are guaranteed to be executed in the order they are enqueued. - * - * @param callable $listener The callback to invoke. - */ - public function add($listener) - { - $this->queue->enqueue($listener); - } - - /** - * Flush the callback queue. - */ - public function tick() - { - // Only invoke as many callbacks as were on the queue when tick() was called. - $count = $this->queue->count(); - - while ($count--) { - \call_user_func( - $this->queue->dequeue() - ); - } - } - - /** - * Check if the next tick queue is empty. - * - * @return boolean - */ - public function isEmpty() - { - return $this->queue->isEmpty(); - } -} diff --git a/digital_doctor/vendor/react/event-loop/src/Timer/Timer.php b/digital_doctor/vendor/react/event-loop/src/Timer/Timer.php deleted file mode 100644 index da3602a..0000000 --- a/digital_doctor/vendor/react/event-loop/src/Timer/Timer.php +++ /dev/null @@ -1,55 +0,0 @@ -interval = (float) $interval; - $this->callback = $callback; - $this->periodic = (bool) $periodic; - } - - public function getInterval() - { - return $this->interval; - } - - public function getCallback() - { - return $this->callback; - } - - public function isPeriodic() - { - return $this->periodic; - } -} diff --git a/digital_doctor/vendor/react/event-loop/src/Timer/Timers.php b/digital_doctor/vendor/react/event-loop/src/Timer/Timers.php deleted file mode 100644 index 53c46d0..0000000 --- a/digital_doctor/vendor/react/event-loop/src/Timer/Timers.php +++ /dev/null @@ -1,113 +0,0 @@ -useHighResolution = \function_exists('hrtime'); - } - - public function updateTime() - { - return $this->time = $this->useHighResolution ? \hrtime(true) * 1e-9 : \microtime(true); - } - - public function getTime() - { - return $this->time ?: $this->updateTime(); - } - - public function add(TimerInterface $timer) - { - $id = \PHP_VERSION_ID < 70200 ? \spl_object_hash($timer) : \spl_object_id($timer); - $this->timers[$id] = $timer; - $this->schedule[$id] = $timer->getInterval() + $this->updateTime(); - $this->sorted = false; - } - - public function contains(TimerInterface $timer) - { - $id = \PHP_VERSION_ID < 70200 ? \spl_object_hash($timer) : \spl_object_id($timer); - return isset($this->timers[$id]); - } - - public function cancel(TimerInterface $timer) - { - $id = \PHP_VERSION_ID < 70200 ? \spl_object_hash($timer) : \spl_object_id($timer); - unset($this->timers[$id], $this->schedule[$id]); - } - - public function getFirst() - { - // ensure timers are sorted to simply accessing next (first) one - if (!$this->sorted) { - $this->sorted = true; - \asort($this->schedule); - } - - return \reset($this->schedule); - } - - public function isEmpty() - { - return \count($this->timers) === 0; - } - - public function tick() - { - // hot path: skip timers if nothing is scheduled - if (!$this->schedule) { - return; - } - - // ensure timers are sorted so we can execute in order - if (!$this->sorted) { - $this->sorted = true; - \asort($this->schedule); - } - - $time = $this->updateTime(); - - foreach ($this->schedule as $id => $scheduled) { - // schedule is ordered, so loop until first timer that is not scheduled for execution now - if ($scheduled >= $time) { - break; - } - - // skip any timers that are removed while we process the current schedule - if (!isset($this->schedule[$id]) || $this->schedule[$id] !== $scheduled) { - continue; - } - - $timer = $this->timers[$id]; - \call_user_func($timer->getCallback(), $timer); - - // re-schedule if this is a periodic timer and it has not been cancelled explicitly already - if ($timer->isPeriodic() && isset($this->timers[$id])) { - $this->schedule[$id] = $timer->getInterval() + $time; - $this->sorted = false; - } else { - unset($this->timers[$id], $this->schedule[$id]); - } - } - } -} diff --git a/digital_doctor/vendor/react/event-loop/src/TimerInterface.php b/digital_doctor/vendor/react/event-loop/src/TimerInterface.php deleted file mode 100644 index cdcf773..0000000 --- a/digital_doctor/vendor/react/event-loop/src/TimerInterface.php +++ /dev/null @@ -1,27 +0,0 @@ -get('https://httpbingo.org/redirect/6')); - assert($response instanceof Psr\Http\Message\ResponseInterface); - ``` - -* Feature: Add `Request` class to represent outgoing HTTP request message. - (#480 by @clue) - -* Feature: Preserve request method and body for `307 Temporary Redirect` and `308 Permanent Redirect`. - (#442 by @dinooo13) - -* Feature: Include buffer logic to avoid dependency on reactphp/promise-stream. - (#482 by @clue) - -* Improve test suite and project setup and report failed assertions. - (#478 by @clue, #487 and #491 by @WyriHaximus and #475 and #479 by @SimonFrings) - -## 1.8.0 (2022-09-29) - -* Feature: Support for default request headers. - (#461 by @51imyy) - - ```php - $browser = new React\Http\Browser(); - $browser = $browser->withHeader('User-Agent', 'ACME'); - - $browser->get($url)->then(…); - ``` - -* Feature: Forward compatibility with upcoming Promise v3. - (#460 by @clue) - -## 1.7.0 (2022-08-23) - -This is a **SECURITY** and feature release for the 1.x series of ReactPHP's HTTP component. - -* Security fix: This release fixes a medium severity security issue in ReactPHP's HTTP server component - that affects all versions between `v0.7.0` and `v1.6.0`. All users are encouraged to upgrade immediately. - Special thanks to Marco Squarcina (TU Wien) for reporting this and working with us to coordinate this release. - (CVE-2022-36032 reported by @lavish and fixed by @clue) - -* Feature: Improve HTTP server performance by ~20%, reuse syscall values for clock time and socket addresses. - (#457 and #467 by @clue) - -* Feature: Full PHP 8.2+ compatibility, refactor internal `Transaction` to avoid assigning dynamic properties. - (#459 by @clue and #466 by @WyriHaximus) - -* Feature / Fix: Allow explicit `Content-Length` response header on `HEAD` requests. - (#444 by @mrsimonbennett) - -* Minor documentation improvements. - (#452 by @clue, #458 by @nhedger, #448 by @jorrit and #446 by @SimonFrings) - -* Improve test suite, update to use new reactphp/async package instead of clue/reactphp-block, - skip memory tests when lowering memory limit fails and fix legacy HHVM build. - (#464 and #440 by @clue and #450 by @SimonFrings) - -## 1.6.0 (2022-02-03) - -* Feature: Add factory methods for common HTML/JSON/plaintext/XML response types. - (#439 by @clue) - - ```php - $response = React\Http\Response\html("

Hello wörld!

\n"); - $response = React\Http\Response\json(['message' => 'Hello wörld!']); - $response = React\Http\Response\plaintext("Hello wörld!\n"); - $response = React\Http\Response\xml("Hello wörld!\n"); - ``` - -* Feature: Expose all status code constants via `Response` class. - (#432 by @clue) - - ```php - $response = new React\Http\Message\Response( - React\Http\Message\Response::STATUS_OK, // 200 OK - … - ); - $response = new React\Http\Message\Response( - React\Http\Message\Response::STATUS_NOT_FOUND, // 404 Not Found - … - ); - ``` - -* Feature: Full support for PHP 8.1 release. - (#433 by @SimonFrings and #434 by @clue) - -* Feature / Fix: Improve protocol handling for HTTP responses with no body. - (#429 and #430 by @clue) - -* Internal refactoring and internal improvements for handling requests and responses. - (#422 by @WyriHaximus and #431 by @clue) - -* Improve documentation, update proxy examples, include error reporting in examples. - (#420, #424, #426, and #427 by @clue) - -* Update test suite to use default loop. - (#438 by @clue) - -## 1.5.0 (2021-08-04) - -* Feature: Update `Browser` signature to take optional `$connector` as first argument and - to match new Socket API without nullable loop arguments. - (#418 and #419 by @clue) - - ```php - // unchanged - $browser = new React\Http\Browser(); - - // deprecated - $browser = new React\Http\Browser(null, $connector); - $browser = new React\Http\Browser($loop, $connector); - - // new - $browser = new React\Http\Browser($connector); - $browser = new React\Http\Browser($connector, $loop); - ``` - -* Feature: Rename `Server` to `HttpServer` to avoid class name collisions and - to avoid any ambiguities with regards to the new `SocketServer` API. - (#417 and #419 by @clue) - - ```php - // deprecated - $server = new React\Http\Server($handler); - $server->listen(new React\Socket\Server(8080)); - - // new - $http = new React\Http\HttpServer($handler); - $http->listen(new React\Socket\SocketServer('127.0.0.1:8080')); - ``` - -## 1.4.0 (2021-07-11) - -A major new feature release, see [**release announcement**](https://clue.engineering/2021/announcing-reactphp-default-loop). - -* Feature: Simplify usage by supporting new [default loop](https://reactphp.org/event-loop/#loop). - (#410 by @clue) - - ```php - // old (still supported) - $browser = new React\Http\Browser($loop); - $server = new React\Http\Server($loop, $handler); - - // new (using default loop) - $browser = new React\Http\Browser(); - $server = new React\Http\Server($handler); - ``` - -## 1.3.0 (2021-04-11) - -* Feature: Support persistent connections (`Connection: keep-alive`). - (#405 by @clue) - - This shows a noticeable performance improvement especially when benchmarking - using persistent connections (which is the default pretty much everywhere). - Together with other changes in this release, this improves benchmarking - performance by around 100%. - -* Feature: Require `Host` request header for HTTP/1.1 requests. - (#404 by @clue) - -* Minor documentation improvements. - (#398 by @fritz-gerneth and #399 and #400 by @pavog) - -* Improve test suite, use GitHub actions for continuous integration (CI). - (#402 by @SimonFrings) - -## 1.2.0 (2020-12-04) - -* Feature: Keep request body in memory also after consuming request body. - (#395 by @clue) - - This means consumers can now always access the complete request body as - detailed in the documentation. This allows building custom parsers and more - advanced processing models without having to mess with the default parsers. - -## 1.1.0 (2020-09-11) - -* Feature: Support upcoming PHP 8 release, update to reactphp/socket v1.6 and adjust type checks for invalid chunk headers. - (#391 by @clue) - -* Feature: Consistently resolve base URL according to HTTP specs. - (#379 by @clue) - -* Feature / Fix: Expose `Transfer-Encoding: chunked` response header and fix chunked responses for `HEAD` requests. - (#381 by @clue) - -* Internal refactoring to remove unneeded `MessageFactory` and `Response` classes. - (#380 and #389 by @clue) - -* Minor documentation improvements and improve test suite, update to support PHPUnit 9.3. - (#385 by @clue and #393 by @SimonFrings) - -## 1.0.0 (2020-07-11) - -A major new feature release, see [**release announcement**](https://clue.engineering/2020/announcing-reactphp-http). - -* First stable LTS release, now following [SemVer](https://semver.org/). - We'd like to emphasize that this component is production ready and battle-tested. - We plan to support all long-term support (LTS) releases for at least 24 months, - so you have a rock-solid foundation to build on top of. - -This update involves some major new features and a number of BC breaks due to -some necessary API cleanup. We've tried hard to avoid BC breaks where possible -and minimize impact otherwise. We expect that most consumers of this package -will be affected by BC breaks, but updating should take no longer than a few -minutes. See below for more details: - -* Feature: Add async HTTP client implementation. - (#368 by @clue) - - ```php - $browser = new React\Http\Browser($loop); - $browser->get($url)->then(function (Psr\Http\Message\ResponseInterface $response) { - echo $response->getBody(); - }); - ``` - - The code has been imported as-is from [clue/reactphp-buzz v2.9.0](https://github.com/clue/reactphp-buzz), - with only minor changes to the namespace and we otherwise leave all the existing APIs unchanged. - Upgrading from [clue/reactphp-buzz v2.9.0](https://github.com/clue/reactphp-buzz) - to this release should be a matter of updating some namespace references only: - - ```php - // old - $browser = new Clue\React\Buzz\Browser($loop); - - // new - $browser = new React\Http\Browser($loop); - ``` - -* Feature / BC break: Add `LoopInterface` as required first constructor argument to `Server` and - change `Server` to accept variadic middleware handlers instead of `array`. - (#361 and #362 by @WyriHaximus) - - ```php - // old - $server = new React\Http\Server($handler); - $server = new React\Http\Server([$middleware, $handler]); - - // new - $server = new React\Http\Server($loop, $handler); - $server = new React\Http\Server($loop, $middleware, $handler); - ``` - -* Feature / BC break: Move `Response` class to `React\Http\Message\Response` and - expose `ServerRequest` class to `React\Http\Message\ServerRequest`. - (#370 by @clue) - - ```php - // old - $response = new React\Http\Response(200, [], 'Hello!'); - - // new - $response = new React\Http\Message\Response(200, [], 'Hello!'); - ``` - -* Feature / BC break: Add `StreamingRequestMiddleware` to stream incoming requests, mark `StreamingServer` as internal. - (#367 by @clue) - - ```php - // old: advanced StreamingServer is now internal only - $server = new React\Http\StreamingServer($handler); - - // new: use StreamingRequestMiddleware instead of StreamingServer - $server = new React\Http\Server( - $loop, - new React\Http\Middleware\StreamingRequestMiddleware(), - $handler - ); - ``` - -* Feature / BC break: Improve default concurrency to 1024 requests and cap default request buffer at 64K. - (#371 by @clue) - - This improves default concurrency to 1024 requests and caps the default request buffer at 64K. - The previous defaults resulted in just 4 concurrent requests with a request buffer of 8M. - See [`Server`](README.md#server) for details on how to override these defaults. - -* Feature: Expose ReactPHP in `User-Agent` client-side request header and in `Server` server-side response header. - (#374 by @clue) - -* Mark all classes as `final` to discourage inheriting from it. - (#373 by @WyriHaximus) - -* Improve documentation and use fully-qualified class names throughout the documentation and - add ReactPHP core team as authors to `composer.json` and license file. - (#366 and #369 by @WyriHaximus and #375 by @clue) - -* Improve test suite and support skipping all online tests with `--exclude-group internet`. - (#372 by @clue) - -## 0.8.7 (2020-07-05) - -* Fix: Fix parsing multipart request body with quoted header parameters (dot net). - (#363 by @ebimmel) - -* Fix: Fix calculating concurrency when `post_max_size` ini is unlimited. - (#365 by @clue) - -* Improve test suite to run tests on PHPUnit 9 and clean up test suite. - (#364 by @SimonFrings) - -## 0.8.6 (2020-01-12) - -* Fix: Fix parsing `Cookie` request header with comma in its values. - (#352 by @fiskie) - -* Fix: Avoid unneeded warning when decoding invalid data on PHP 7.4. - (#357 by @WyriHaximus) - -* Add .gitattributes to exclude dev files from exports. - (#353 by @reedy) - -## 0.8.5 (2019-10-29) - -* Internal refactorings and optimizations to improve request parsing performance. - Benchmarks suggest number of requests/s improved by ~30% for common `GET` requests. - (#345, #346, #349 and #350 by @clue) - -* Add documentation and example for JSON/XML request body and - improve documentation for concurrency and streaming requests and for error handling. - (#341 and #342 by @clue) - -## 0.8.4 (2019-01-16) - -* Improvement: Internal refactoring to simplify response header logic. - (#321 by @clue) - -* Improvement: Assign Content-Length response header automatically only when size is known. - (#329 by @clue) - -* Improvement: Import global functions for better performance. - (#330 by @WyriHaximus) - -## 0.8.3 (2018-04-11) - -* Feature: Do not pause connection stream to detect closed connections immediately. - (#315 by @clue) - -* Feature: Keep incoming `Transfer-Encoding: chunked` request header. - (#316 by @clue) - -* Feature: Reject invalid requests that contain both `Content-Length` and `Transfer-Encoding` request headers. - (#318 by @clue) - -* Minor internal refactoring to simplify connection close logic after sending response. - (#317 by @clue) - -## 0.8.2 (2018-04-06) - -* Fix: Do not pass `$next` handler to final request handler. - (#308 by @clue) - -* Fix: Fix awaiting queued handlers when cancelling a queued handler. - (#313 by @clue) - -* Fix: Fix Server to skip `SERVER_ADDR` params for Unix domain sockets (UDS). - (#307 by @clue) - -* Documentation for PSR-15 middleware and minor documentation improvements. - (#314 by @clue and #297, #298 and #310 by @seregazhuk) - -* Minor code improvements and micro optimizations. - (#301 by @seregazhuk and #305 by @kalessil) - -## 0.8.1 (2018-01-05) - -* Major request handler performance improvement. Benchmarks suggest number of - requests/s improved by more than 50% for common `GET` requests! - We now avoid queuing, buffering and wrapping incoming requests in promises - when we're below limits and instead can directly process common requests. - (#291, #292, #293, #294 and #296 by @clue) - -* Fix: Fix concurrent invoking next middleware request handlers - (#293 by @clue) - -* Small code improvements - (#286 by @seregazhuk) - -* Improve test suite to be less fragile when using `ext-event` and - fix test suite forward compatibility with upcoming EventLoop releases - (#288 and #290 by @clue) - -## 0.8.0 (2017-12-12) - -* Feature / BC break: Add new `Server` facade that buffers and parses incoming - HTTP requests. This provides full PSR-7 compatibility, including support for - form submissions with POST fields and file uploads. - The old `Server` has been renamed to `StreamingServer` for advanced usage - and is used internally. - (#266, #271, #281, #282, #283 and #284 by @WyriHaximus and @clue) - - ```php - // old: handle incomplete/streaming requests - $server = new Server($handler); - - // new: handle complete, buffered and parsed requests - // new: full PSR-7 support, including POST fields and file uploads - $server = new Server($handler); - - // new: handle incomplete/streaming requests - $server = new StreamingServer($handler); - ``` - - > While this is technically a small BC break, this should in fact not break - most consuming code. If you rely on the old request streaming, you can - explicitly use the advanced `StreamingServer` to restore old behavior. - -* Feature: Add support for middleware request handler arrays - (#215, #228, #229, #236, #237, #238, #246, #247, #277, #279 and #285 by @WyriHaximus, @clue and @jsor) - - ```php - // new: middleware request handler arrays - $server = new Server(array( - function (ServerRequestInterface $request, callable $next) { - $request = $request->withHeader('Processed', time()); - return $next($request); - }, - function (ServerRequestInterface $request) { - return new Response(); - } - )); - ``` - -* Feature: Add support for limiting how many next request handlers can be - executed concurrently (`LimitConcurrentRequestsMiddleware`) - (#272 by @clue and @WyriHaximus) - - ```php - // new: explicitly limit concurrency - $server = new Server(array( - new LimitConcurrentRequestsMiddleware(10), - $handler - )); - ``` - -* Feature: Add support for buffering the incoming request body - (`RequestBodyBufferMiddleware`). - This feature mimics PHP's default behavior and respects its `post_max_size` - ini setting by default and allows explicit configuration. - (#216, #224, #263, #276 and #278 by @WyriHaximus and #235 by @andig) - - ```php - // new: buffer up to 10 requests with 8 MiB each - $server = new StreamingServer(array( - new LimitConcurrentRequestsMiddleware(10), - new RequestBodyBufferMiddleware('8M'), - $handler - )); - ``` - -* Feature: Add support for parsing form submissions with POST fields and file - uploads (`RequestBodyParserMiddleware`). - This feature mimics PHP's default behavior and respects its ini settings and - `MAX_FILE_SIZE` POST fields by default and allows explicit configuration. - (#220, #226, #252, #261, #264, #265, #267, #268, #274 by @WyriHaximus and @clue) - - ```php - // new: buffer up to 10 requests with 8 MiB each - // and limit to 4 uploads with 2 MiB each - $server = new StreamingServer(array( - new LimitConcurrentRequestsMiddleware(10), - new RequestBodyBufferMiddleware('8M'), - new RequestBodyParserMiddleware('2M', 4) - $handler - )); - ``` - -* Feature: Update Socket to work around sending secure HTTPS responses with PHP < 7.1.4 - (#244 by @clue) - -* Feature: Support sending same response header multiple times (e.g. `Set-Cookie`) - (#248 by @clue) - -* Feature: Raise maximum request header size to 8k to match common implementations - (#253 by @clue) - -* Improve test suite by adding forward compatibility with PHPUnit 6, test - against PHP 7.1 and PHP 7.2 and refactor and remove risky and duplicate tests. - (#243, #269 and #270 by @carusogabriel and #249 by @clue) - -* Minor code refactoring to move internal classes to `React\Http\Io` namespace - and clean up minor code and documentation issues - (#251 by @clue, #227 by @kalessil, #240 by @christoph-kluge, #230 by @jsor and #280 by @andig) - -## 0.7.4 (2017-08-16) - -* Improvement: Target evenement 3.0 a long side 2.0 and 1.0 - (#212 by @WyriHaximus) - -## 0.7.3 (2017-08-14) - -* Feature: Support `Throwable` when setting previous exception from server callback - (#155 by @jsor) - -* Fix: Fixed URI parsing for origin-form requests that contain scheme separator - such as `/path?param=http://example.com`. - (#209 by @aaronbonneau) - -* Improve test suite by locking Travis distro so new defaults will not break the build - (#211 by @clue) - -## 0.7.2 (2017-07-04) - -* Fix: Stricter check for invalid request-line in HTTP requests - (#206 by @clue) - -* Refactor to use HTTP response reason phrases from response object - (#205 by @clue) - -## 0.7.1 (2017-06-17) - -* Fix: Fix parsing CONNECT request without `Host` header - (#201 by @clue) - -* Internal preparation for future PSR-7 `UploadedFileInterface` - (#199 by @WyriHaximus) - -## 0.7.0 (2017-05-29) - -* Feature / BC break: Use PSR-7 (http-message) standard and - `Request-In-Response-Out`-style request handler callback. - Pass standard PSR-7 `ServerRequestInterface` and expect any standard - PSR-7 `ResponseInterface` in return for the request handler callback. - (#146 and #152 and #170 by @legionth) - - ```php - // old - $app = function (Request $request, Response $response) { - $response->writeHead(200, array('Content-Type' => 'text/plain')); - $response->end("Hello world!\n"); - }; - - // new - $app = function (ServerRequestInterface $request) { - return new Response( - 200, - array('Content-Type' => 'text/plain'), - "Hello world!\n" - ); - }; - ``` - - A `Content-Length` header will automatically be included if the size can be - determined from the response body. - (#164 by @maciejmrozinski) - - The request handler callback will automatically make sure that responses to - HEAD requests and certain status codes, such as `204` (No Content), never - contain a response body. - (#156 by @clue) - - The intermediary `100 Continue` response will automatically be sent if - demanded by a HTTP/1.1 client. - (#144 by @legionth) - - The request handler callback can now return a standard `Promise` if - processing the request needs some time, such as when querying a database. - Similarly, the request handler may return a streaming response if the - response body comes from a `ReadableStreamInterface` or its size is - unknown in advance. - - ```php - // old - $app = function (Request $request, Response $response) use ($db) { - $db->query()->then(function ($result) use ($response) { - $response->writeHead(200, array('Content-Type' => 'text/plain')); - $response->end($result); - }); - }; - - // new - $app = function (ServerRequestInterface $request) use ($db) { - return $db->query()->then(function ($result) { - return new Response( - 200, - array('Content-Type' => 'text/plain'), - $result - ); - }); - }; - ``` - - Pending promies and response streams will automatically be canceled once the - client connection closes. - (#187 and #188 by @clue) - - The `ServerRequestInterface` contains the full effective request URI, - server-side parameters, query parameters and parsed cookies values as - defined in PSR-7. - (#167 by @clue and #174, #175 and #180 by @legionth) - - ```php - $app = function (ServerRequestInterface $request) { - return new Response( - 200, - array('Content-Type' => 'text/plain'), - $request->getUri()->getScheme() - ); - }; - ``` - - Advanced: Support duplex stream response for `Upgrade` requests such as - `Upgrade: WebSocket` or custom protocols and `CONNECT` requests - (#189 and #190 by @clue) - - > Note that the request body will currently not be buffered and parsed by - default, which depending on your particilar use-case, may limit - interoperability with the PSR-7 (http-message) ecosystem. - The provided streaming request body interfaces allow you to perform - buffering and parsing as needed in the request handler callback. - See also the README and examples for more details. - -* Feature / BC break: Replace `request` listener with callback function and - use `listen()` method to support multiple listening sockets - (#97 by @legionth and #193 by @clue) - - ```php - // old - $server = new Server($socket); - $server->on('request', $app); - - // new - $server = new Server($app); - $server->listen($socket); - ``` - -* Feature: Support the more advanced HTTP requests, such as - `OPTIONS * HTTP/1.1` (`OPTIONS` method in asterisk-form), - `GET http://example.com/path HTTP/1.1` (plain proxy requests in absolute-form), - `CONNECT example.com:443 HTTP/1.1` (`CONNECT` proxy requests in authority-form) - and sanitize `Host` header value across all requests. - (#157, #158, #161, #165, #169 and #173 by @clue) - -* Feature: Forward compatibility with Socket v1.0, v0.8, v0.7 and v0.6 and - forward compatibility with Stream v1.0 and v0.7 - (#154, #163, #183, #184 and #191 by @clue) - -* Feature: Simplify examples to ease getting started and - add benchmarking example - (#151 and #162 by @clue) - -* Improve test suite by adding tests for case insensitive chunked transfer - encoding and ignoring HHVM test failures until Travis tests work again. - (#150 by @legionth and #185 by @clue) - -## 0.6.0 (2017-03-09) - -* Feature / BC break: The `Request` and `Response` objects now follow strict - stream semantics and their respective methods and events. - (#116, #129, #133, #135, #136, #137, #138, #140, #141 by @legionth - and #122, #123, #130, #131, #132, #142 by @clue) - - This implies that the `Server` now supports proper detection of the request - message body stream, such as supporting decoding chunked transfer encoding, - delimiting requests with an explicit `Content-Length` header - and those with an empty request message body. - - These streaming semantics are compatible with previous Stream v0.5, future - compatible with v0.5 and upcoming v0.6 versions and can be used like this: - - ```php - $http->on('request', function (Request $request, Response $response) { - $contentLength = 0; - $request->on('data', function ($data) use (&$contentLength) { - $contentLength += strlen($data); - }); - - $request->on('end', function () use ($response, &$contentLength){ - $response->writeHead(200, array('Content-Type' => 'text/plain')); - $response->end("The length of the submitted request body is: " . $contentLength); - }); - - // an error occured - // e.g. on invalid chunked encoded data or an unexpected 'end' event - $request->on('error', function (\Exception $exception) use ($response, &$contentLength) { - $response->writeHead(400, array('Content-Type' => 'text/plain')); - $response->end("An error occured while reading at length: " . $contentLength); - }); - }); - ``` - - Similarly, the `Request` and `Response` now strictly follow the - `close()` method and `close` event semantics. - Closing the `Request` does not interrupt the underlying TCP/IP in - order to allow still sending back a valid response message. - Closing the `Response` does terminate the underlying TCP/IP - connection in order to clean up resources. - - You should make sure to always attach a `request` event listener - like above. The `Server` will not respond to an incoming HTTP - request otherwise and keep the TCP/IP connection pending until the - other side chooses to close the connection. - -* Feature: Support `HTTP/1.1` and `HTTP/1.0` for `Request` and `Response`. - (#124, #125, #126, #127, #128 by @clue and #139 by @legionth) - - The outgoing `Response` will automatically use the same HTTP version as the - incoming `Request` message and will only apply `HTTP/1.1` semantics if - applicable. This includes that the `Response` will automatically attach a - `Date` and `Connection: close` header if applicable. - - This implies that the `Server` now automatically responds with HTTP error - messages for invalid requests (status 400) and those exceeding internal - request header limits (status 431). - -## 0.5.0 (2017-02-16) - -* Feature / BC break: Change `Request` methods to be in line with PSR-7 - (#117 by @clue) - * Rename `getQuery()` to `getQueryParams()` - * Rename `getHttpVersion()` to `getProtocolVersion()` - * Change `getHeaders()` to always return an array of string values - for each header - -* Feature / BC break: Update Socket component to v0.5 and - add secure HTTPS server support - (#90 and #119 by @clue) - - ```php - // old plaintext HTTP server - $socket = new React\Socket\Server($loop); - $socket->listen(8080, '127.0.0.1'); - $http = new React\Http\Server($socket); - - // new plaintext HTTP server - $socket = new React\Socket\Server('127.0.0.1:8080', $loop); - $http = new React\Http\Server($socket); - - // new secure HTTPS server - $socket = new React\Socket\Server('127.0.0.1:8080', $loop); - $socket = new React\Socket\SecureServer($socket, $loop, array( - 'local_cert' => __DIR__ . '/localhost.pem' - )); - $http = new React\Http\Server($socket); - ``` - -* BC break: Mark internal APIs as internal or private and - remove unneeded `ServerInterface` - (#118 by @clue, #95 by @legionth) - -## 0.4.4 (2017-02-13) - -* Feature: Add request header accessors (à la PSR-7) - (#103 by @clue) - - ```php - // get value of host header - $host = $request->getHeaderLine('Host'); - - // get list of all cookie headers - $cookies = $request->getHeader('Cookie'); - ``` - -* Feature: Forward `pause()` and `resume()` from `Request` to underlying connection - (#110 by @clue) - - ```php - // support back-pressure when piping request into slower destination - $request->pipe($dest); - - // manually pause/resume request - $request->pause(); - $request->resume(); - ``` - -* Fix: Fix `100-continue` to be handled case-insensitive and ignore it for HTTP/1.0. - Similarly, outgoing response headers are now handled case-insensitive, e.g - we no longer apply chunked transfer encoding with mixed-case `Content-Length`. - (#107 by @clue) - - ```php - // now handled case-insensitive - $request->expectsContinue(); - - // now works just like properly-cased header - $response->writeHead($status, array('content-length' => 0)); - ``` - -* Fix: Do not emit empty `data` events and ignore empty writes in order to - not mess up chunked transfer encoding - (#108 and #112 by @clue) - -* Lock and test minimum required dependency versions and support PHPUnit v5 - (#113, #115 and #114 by @andig) - -## 0.4.3 (2017-02-10) - -* Fix: Do not take start of body into account when checking maximum header size - (#88 by @nopolabs) - -* Fix: Remove `data` listener if `HeaderParser` emits an error - (#83 by @nick4fake) - -* First class support for PHP 5.3 through PHP 7 and HHVM - (#101 and #102 by @clue, #66 by @WyriHaximus) - -* Improve test suite by adding PHPUnit to require-dev, - improving forward compatibility with newer PHPUnit versions - and replacing unneeded test stubs - (#92 and #93 by @nopolabs, #100 by @legionth) - -## 0.4.2 (2016-11-09) - -* Remove all listeners after emitting error in RequestHeaderParser #68 @WyriHaximus -* Catch Guzzle parse request errors #65 @WyriHaximus -* Remove branch-alias definition as per reactphp/react#343 #58 @WyriHaximus -* Add functional example to ease getting started #64 by @clue -* Naming, immutable array manipulation #37 @cboden - -## 0.4.1 (2015-05-21) - -* Replaced guzzle/parser with guzzlehttp/psr7 by @cboden -* FIX Continue Header by @iannsp -* Missing type hint by @marenzo - -## 0.4.0 (2014-02-02) - -* BC break: Bump minimum PHP version to PHP 5.4, remove 5.3 specific hacks -* BC break: Update to React/Promise 2.0 -* BC break: Update to Evenement 2.0 -* Dependency: Autoloading and filesystem structure now PSR-4 instead of PSR-0 -* Bump React dependencies to v0.4 - -## 0.3.0 (2013-04-14) - -* Bump React dependencies to v0.3 - -## 0.2.6 (2012-12-26) - -* Bug fix: Emit end event when Response closes (@beaucollins) - -## 0.2.3 (2012-11-14) - -* Bug fix: Forward drain events from HTTP response (@cs278) -* Dependency: Updated guzzle deps to `3.0.*` - -## 0.2.2 (2012-10-28) - -* Version bump - -## 0.2.1 (2012-10-14) - -* Feature: Support HTTP 1.1 continue - -## 0.2.0 (2012-09-10) - -* Bump React dependencies to v0.2 - -## 0.1.1 (2012-07-12) - -* Version bump - -## 0.1.0 (2012-07-11) - -* First tagged release diff --git a/digital_doctor/vendor/react/http/LICENSE b/digital_doctor/vendor/react/http/LICENSE deleted file mode 100644 index d6f8901..0000000 --- a/digital_doctor/vendor/react/http/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2012 Christian Lück, Cees-Jan Kiewiet, Jan Sorgalla, Chris Boden, Igor Wiedler - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/digital_doctor/vendor/react/http/README.md b/digital_doctor/vendor/react/http/README.md deleted file mode 100644 index d055064..0000000 --- a/digital_doctor/vendor/react/http/README.md +++ /dev/null @@ -1,3024 +0,0 @@ -# HTTP - -[![CI status](https://github.com/reactphp/http/actions/workflows/ci.yml/badge.svg)](https://github.com/reactphp/http/actions) -[![installs on Packagist](https://img.shields.io/packagist/dt/react/http?color=blue&label=installs%20on%20Packagist)](https://packagist.org/packages/react/http) - -Event-driven, streaming HTTP client and server implementation for [ReactPHP](https://reactphp.org/). - -This HTTP library provides re-usable implementations for an HTTP client and -server based on ReactPHP's [`Socket`](https://github.com/reactphp/socket) and -[`EventLoop`](https://github.com/reactphp/event-loop) components. -Its client component allows you to send any number of async HTTP/HTTPS requests -concurrently. -Its server component allows you to build plaintext HTTP and secure HTTPS servers -that accept incoming HTTP requests from HTTP clients (such as web browsers). -This library provides async, streaming means for all of this, so you can handle -multiple concurrent HTTP requests without blocking. - -**Table of contents** - -* [Quickstart example](#quickstart-example) -* [Client Usage](#client-usage) - * [Request methods](#request-methods) - * [Promises](#promises) - * [Cancellation](#cancellation) - * [Timeouts](#timeouts) - * [Authentication](#authentication) - * [Redirects](#redirects) - * [Blocking](#blocking) - * [Concurrency](#concurrency) - * [Streaming response](#streaming-response) - * [Streaming request](#streaming-request) - * [HTTP proxy](#http-proxy) - * [SOCKS proxy](#socks-proxy) - * [SSH proxy](#ssh-proxy) - * [Unix domain sockets](#unix-domain-sockets) -* [Server Usage](#server-usage) - * [HttpServer](#httpserver) - * [listen()](#listen) - * [Server Request](#server-request) - * [Request parameters](#request-parameters) - * [Query parameters](#query-parameters) - * [Request body](#request-body) - * [Streaming incoming request](#streaming-incoming-request) - * [Request method](#request-method) - * [Cookie parameters](#cookie-parameters) - * [Invalid request](#invalid-request) - * [Server Response](#server-response) - * [Deferred response](#deferred-response) - * [Streaming outgoing response](#streaming-outgoing-response) - * [Response length](#response-length) - * [Invalid response](#invalid-response) - * [Default response headers](#default-response-headers) - * [Middleware](#middleware) - * [Custom middleware](#custom-middleware) - * [Third-Party Middleware](#third-party-middleware) -* [API](#api) - * [Browser](#browser) - * [get()](#get) - * [post()](#post) - * [head()](#head) - * [patch()](#patch) - * [put()](#put) - * [delete()](#delete) - * [request()](#request) - * [requestStreaming()](#requeststreaming) - * [withTimeout()](#withtimeout) - * [withFollowRedirects()](#withfollowredirects) - * [withRejectErrorResponse()](#withrejecterrorresponse) - * [withBase()](#withbase) - * [withProtocolVersion()](#withprotocolversion) - * [withResponseBuffer()](#withresponsebuffer) - * [withHeader()](#withheader) - * [withoutHeader()](#withoutheader) - * [React\Http\Message](#reacthttpmessage) - * [Response](#response) - * [html()](#html) - * [json()](#json) - * [plaintext()](#plaintext) - * [xml()](#xml) - * [Request](#request-1) - * [ServerRequest](#serverrequest) - * [Uri](#uri) - * [ResponseException](#responseexception) - * [React\Http\Middleware](#reacthttpmiddleware) - * [StreamingRequestMiddleware](#streamingrequestmiddleware) - * [LimitConcurrentRequestsMiddleware](#limitconcurrentrequestsmiddleware) - * [RequestBodyBufferMiddleware](#requestbodybuffermiddleware) - * [RequestBodyParserMiddleware](#requestbodyparsermiddleware) -* [Install](#install) -* [Tests](#tests) -* [License](#license) - -## Quickstart example - -Once [installed](#install), you can use the following code to access an -HTTP web server and send some simple HTTP GET requests: - -```php -get('http://www.google.com/')->then(function (Psr\Http\Message\ResponseInterface $response) { - var_dump($response->getHeaders(), (string)$response->getBody()); -}, function (Exception $e) { - echo 'Error: ' . $e->getMessage() . PHP_EOL; -}); -``` - -This is an HTTP server which responds with `Hello World!` to every request. - -```php -listen($socket); -``` - -See also the [examples](examples/). - -## Client Usage - -### Request methods - -Most importantly, this project provides a [`Browser`](#browser) object that -offers several methods that resemble the HTTP protocol methods: - -```php -$browser->get($url, array $headers = array()); -$browser->head($url, array $headers = array()); -$browser->post($url, array $headers = array(), string|ReadableStreamInterface $body = ''); -$browser->delete($url, array $headers = array(), string|ReadableStreamInterface $body = ''); -$browser->put($url, array $headers = array(), string|ReadableStreamInterface $body = ''); -$browser->patch($url, array $headers = array(), string|ReadableStreamInterface $body = ''); -``` - -Each of these methods requires a `$url` and some optional parameters to send an -HTTP request. Each of these method names matches the respective HTTP request -method, for example the [`get()`](#get) method sends an HTTP `GET` request. - -You can optionally pass an associative array of additional `$headers` that will be -sent with this HTTP request. Additionally, each method will automatically add a -matching `Content-Length` request header if an outgoing request body is given and its -size is known and non-empty. For an empty request body, if will only include a -`Content-Length: 0` request header if the request method usually expects a request -body (only applies to `POST`, `PUT` and `PATCH` HTTP request methods). - -If you're using a [streaming request body](#streaming-request), it will default -to using `Transfer-Encoding: chunked` unless you explicitly pass in a matching `Content-Length` -request header. See also [streaming request](#streaming-request) for more details. - -By default, all of the above methods default to sending requests using the -HTTP/1.1 protocol version. If you want to explicitly use the legacy HTTP/1.0 -protocol version, you can use the [`withProtocolVersion()`](#withprotocolversion) -method. If you want to use any other or even custom HTTP request method, you can -use the [`request()`](#request) method. - -Each of the above methods supports async operation and either *fulfills* with a -[PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface) -or *rejects* with an `Exception`. -Please see the following chapter about [promises](#promises) for more details. - -### Promises - -Sending requests is async (non-blocking), so you can actually send multiple -requests in parallel. -The `Browser` will respond to each request with a -[PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface) -message, the order is not guaranteed. -Sending requests uses a [Promise](https://github.com/reactphp/promise)-based -interface that makes it easy to react to when an HTTP request is completed -(i.e. either successfully fulfilled or rejected with an error): - -```php -$browser->get($url)->then( - function (Psr\Http\Message\ResponseInterface $response) { - var_dump('Response received', $response); - }, - function (Exception $e) { - echo 'Error: ' . $e->getMessage() . PHP_EOL; - } -); -``` - -If this looks strange to you, you can also use the more traditional [blocking API](#blocking). - -Keep in mind that resolving the Promise with the full response message means the -whole response body has to be kept in memory. -This is easy to get started and works reasonably well for smaller responses -(such as common HTML pages or RESTful or JSON API requests). - -You may also want to look into the [streaming API](#streaming-response): - -* If you're dealing with lots of concurrent requests (100+) or -* If you want to process individual data chunks as they happen (without having to wait for the full response body) or -* If you're expecting a big response body size (1 MiB or more, for example when downloading binary files) or -* If you're unsure about the response body size (better be safe than sorry when accessing arbitrary remote HTTP endpoints and the response body size is unknown in advance). - -### Cancellation - -The returned Promise is implemented in such a way that it can be cancelled -when it is still pending. -Cancelling a pending promise will reject its value with an Exception and -clean up any underlying resources. - -```php -$promise = $browser->get($url); - -Loop::addTimer(2.0, function () use ($promise) { - $promise->cancel(); -}); -``` - -### Timeouts - -This library uses a very efficient HTTP implementation, so most HTTP requests -should usually be completed in mere milliseconds. However, when sending HTTP -requests over an unreliable network (the internet), there are a number of things -that can go wrong and may cause the request to fail after a time. As such, this -library respects PHP's `default_socket_timeout` setting (default 60s) as a timeout -for sending the outgoing HTTP request and waiting for a successful response and -will otherwise cancel the pending request and reject its value with an Exception. - -Note that this timeout value covers creating the underlying transport connection, -sending the HTTP request, receiving the HTTP response headers and its full -response body and following any eventual [redirects](#redirects). See also -[redirects](#redirects) below to configure the number of redirects to follow (or -disable following redirects altogether) and also [streaming](#streaming-response) -below to not take receiving large response bodies into account for this timeout. - -You can use the [`withTimeout()` method](#withtimeout) to pass a custom timeout -value in seconds like this: - -```php -$browser = $browser->withTimeout(10.0); - -$browser->get($url)->then(function (Psr\Http\Message\ResponseInterface $response) { - // response received within 10 seconds maximum - var_dump($response->getHeaders()); -}, function (Exception $e) { - echo 'Error: ' . $e->getMessage() . PHP_EOL; -}); -``` - -Similarly, you can use a bool `false` to not apply a timeout at all -or use a bool `true` value to restore the default handling. -See [`withTimeout()`](#withtimeout) for more details. - -If you're using a [streaming response body](#streaming-response), the time it -takes to receive the response body stream will not be included in the timeout. -This allows you to keep this incoming stream open for a longer time, such as -when downloading a very large stream or when streaming data over a long-lived -connection. - -If you're using a [streaming request body](#streaming-request), the time it -takes to send the request body stream will not be included in the timeout. This -allows you to keep this outgoing stream open for a longer time, such as when -uploading a very large stream. - -Note that this timeout handling applies to the higher-level HTTP layer. Lower -layers such as socket and DNS may also apply (different) timeout values. In -particular, the underlying socket connection uses the same `default_socket_timeout` -setting to establish the underlying transport connection. To control this -connection timeout behavior, you can [inject a custom `Connector`](#browser) -like this: - -```php -$browser = new React\Http\Browser( - new React\Socket\Connector( - array( - 'timeout' => 5 - ) - ) -); -``` - -### Authentication - -This library supports [HTTP Basic Authentication](https://en.wikipedia.org/wiki/Basic_access_authentication) -using the `Authorization: Basic …` request header or allows you to set an explicit -`Authorization` request header. - -By default, this library does not include an outgoing `Authorization` request -header. If the server requires authentication, if may return a `401` (Unauthorized) -status code which will reject the request by default (see also the -[`withRejectErrorResponse()` method](#withrejecterrorresponse) below). - -In order to pass authentication details, you can simply pass the username and -password as part of the request URL like this: - -```php -$promise = $browser->get('https://user:pass@example.com/api'); -``` - -Note that special characters in the authentication details have to be -percent-encoded, see also [`rawurlencode()`](https://www.php.net/manual/en/function.rawurlencode.php). -This example will automatically pass the base64-encoded authentication details -using the outgoing `Authorization: Basic …` request header. If the HTTP endpoint -you're talking to requires any other authentication scheme, you can also pass -this header explicitly. This is common when using (RESTful) HTTP APIs that use -OAuth access tokens or JSON Web Tokens (JWT): - -```php -$token = 'abc123'; - -$promise = $browser->get( - 'https://example.com/api', - array( - 'Authorization' => 'Bearer ' . $token - ) -); -``` - -When following redirects, the `Authorization` request header will never be sent -to any remote hosts by default. When following a redirect where the `Location` -response header contains authentication details, these details will be sent for -following requests. See also [redirects](#redirects) below. - -### Redirects - -By default, this library follows any redirects and obeys `3xx` (Redirection) -status codes using the `Location` response header from the remote server. -The promise will be fulfilled with the last response from the chain of redirects. - -```php -$browser->get($url, $headers)->then(function (Psr\Http\Message\ResponseInterface $response) { - // the final response will end up here - var_dump($response->getHeaders()); -}, function (Exception $e) { - echo 'Error: ' . $e->getMessage() . PHP_EOL; -}); -``` - -Any redirected requests will follow the semantics of the original request and -will include the same request headers as the original request except for those -listed below. -If the original request is a temporary (307) or a permanent (308) redirect, request -body and headers will be passed to the redirected request. Otherwise, the request -body will never be passed to the redirected request. Accordingly, each redirected -request will remove any `Content-Length` and `Content-Type` request headers. - -If the original request used HTTP authentication with an `Authorization` request -header, this request header will only be passed as part of the redirected -request if the redirected URL is using the same host. In other words, the -`Authorizaton` request header will not be forwarded to other foreign hosts due to -possible privacy/security concerns. When following a redirect where the `Location` -response header contains authentication details, these details will be sent for -following requests. - -You can use the [`withFollowRedirects()`](#withfollowredirects) method to -control the maximum number of redirects to follow or to return any redirect -responses as-is and apply custom redirection logic like this: - -```php -$browser = $browser->withFollowRedirects(false); - -$browser->get($url)->then(function (Psr\Http\Message\ResponseInterface $response) { - // any redirects will now end up here - var_dump($response->getHeaders()); -}, function (Exception $e) { - echo 'Error: ' . $e->getMessage() . PHP_EOL; -}); -``` - -See also [`withFollowRedirects()`](#withfollowredirects) for more details. - -### Blocking - -As stated above, this library provides you a powerful, async API by default. - -You can also integrate this into your traditional, blocking environment by using -[reactphp/async](https://github.com/reactphp/async). This allows you to simply -await async HTTP requests like this: - -```php -use function React\Async\await; - -$browser = new React\Http\Browser(); - -$promise = $browser->get('http://example.com/'); - -try { - $response = await($promise); - // response successfully received -} catch (Exception $e) { - // an error occurred while performing the request -} -``` - -Similarly, you can also process multiple requests concurrently and await an array of `Response` objects: - -```php -use function React\Async\await; -use function React\Promise\all; - -$promises = array( - $browser->get('http://example.com/'), - $browser->get('http://www.example.org/'), -); - -$responses = await(all($promises)); -``` - -This is made possible thanks to fibers available in PHP 8.1+ and our -compatibility API that also works on all supported PHP versions. -Please refer to [reactphp/async](https://github.com/reactphp/async#readme) for more details. - -Keep in mind the above remark about buffering the whole response message in memory. -As an alternative, you may also see one of the following chapters for the -[streaming API](#streaming-response). - -### Concurrency - -As stated above, this library provides you a powerful, async API. Being able to -send a large number of requests at once is one of the core features of this -project. For instance, you can easily send 100 requests concurrently while -processing SQL queries at the same time. - -Remember, with great power comes great responsibility. Sending an excessive -number of requests may either take up all resources on your side or it may even -get you banned by the remote side if it sees an unreasonable number of requests -from your side. - -```php -// watch out if array contains many elements -foreach ($urls as $url) { - $browser->get($url)->then(function (Psr\Http\Message\ResponseInterface $response) { - var_dump($response->getHeaders()); - }, function (Exception $e) { - echo 'Error: ' . $e->getMessage() . PHP_EOL; - }); -} -``` - -As a consequence, it's usually recommended to limit concurrency on the sending -side to a reasonable value. It's common to use a rather small limit, as doing -more than a dozen of things at once may easily overwhelm the receiving side. You -can use [clue/reactphp-mq](https://github.com/clue/reactphp-mq) as a lightweight -in-memory queue to concurrently do many (but not too many) things at once: - -```php -// wraps Browser in a Queue object that executes no more than 10 operations at once -$q = new Clue\React\Mq\Queue(10, null, function ($url) use ($browser) { - return $browser->get($url); -}); - -foreach ($urls as $url) { - $q($url)->then(function (Psr\Http\Message\ResponseInterface $response) { - var_dump($response->getHeaders()); - }, function (Exception $e) { - echo 'Error: ' . $e->getMessage() . PHP_EOL; - }); -} -``` - -Additional requests that exceed the concurrency limit will automatically be -enqueued until one of the pending requests completes. This integrates nicely -with the existing [Promise-based API](#promises). Please refer to -[clue/reactphp-mq](https://github.com/clue/reactphp-mq) for more details. - -This in-memory approach works reasonably well for some thousand outstanding -requests. If you're processing a very large input list (think millions of rows -in a CSV or NDJSON file), you may want to look into using a streaming approach -instead. See [clue/reactphp-flux](https://github.com/clue/reactphp-flux) for -more details. - -### Streaming response - -All of the above examples assume you want to store the whole response body in memory. -This is easy to get started and works reasonably well for smaller responses. - -However, there are several situations where it's usually a better idea to use a -streaming approach, where only small chunks have to be kept in memory: - -* If you're dealing with lots of concurrent requests (100+) or -* If you want to process individual data chunks as they happen (without having to wait for the full response body) or -* If you're expecting a big response body size (1 MiB or more, for example when downloading binary files) or -* If you're unsure about the response body size (better be safe than sorry when accessing arbitrary remote HTTP endpoints and the response body size is unknown in advance). - -You can use the [`requestStreaming()`](#requeststreaming) method to send an -arbitrary HTTP request and receive a streaming response. It uses the same HTTP -message API, but does not buffer the response body in memory. It only processes -the response body in small chunks as data is received and forwards this data -through [ReactPHP's Stream API](https://github.com/reactphp/stream). This works -for (any number of) responses of arbitrary sizes. - -This means it resolves with a normal -[PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface), -which can be used to access the response message parameters as usual. -You can access the message body as usual, however it now also -implements [ReactPHP's `ReadableStreamInterface`](https://github.com/reactphp/stream#readablestreaminterface) -as well as parts of the [PSR-7 `StreamInterface`](https://www.php-fig.org/psr/psr-7/#34-psrhttpmessagestreaminterface). - -```php -$browser->requestStreaming('GET', $url)->then(function (Psr\Http\Message\ResponseInterface $response) { - $body = $response->getBody(); - assert($body instanceof Psr\Http\Message\StreamInterface); - assert($body instanceof React\Stream\ReadableStreamInterface); - - $body->on('data', function ($chunk) { - echo $chunk; - }); - - $body->on('error', function (Exception $e) { - echo 'Error: ' . $e->getMessage() . PHP_EOL; - }); - - $body->on('close', function () { - echo '[DONE]' . PHP_EOL; - }); -}, function (Exception $e) { - echo 'Error: ' . $e->getMessage() . PHP_EOL; -}); -``` - -See also the [stream download benchmark example](examples/91-client-benchmark-download.php) and -the [stream forwarding example](examples/21-client-request-streaming-to-stdout.php). - -You can invoke the following methods on the message body: - -```php -$body->on($event, $callback); -$body->eof(); -$body->isReadable(); -$body->pipe(React\Stream\WritableStreamInterface $dest, array $options = array()); -$body->close(); -$body->pause(); -$body->resume(); -``` - -Because the message body is in a streaming state, invoking the following methods -doesn't make much sense: - -```php -$body->__toString(); // '' -$body->detach(); // throws BadMethodCallException -$body->getSize(); // null -$body->tell(); // throws BadMethodCallException -$body->isSeekable(); // false -$body->seek(); // throws BadMethodCallException -$body->rewind(); // throws BadMethodCallException -$body->isWritable(); // false -$body->write(); // throws BadMethodCallException -$body->read(); // throws BadMethodCallException -$body->getContents(); // throws BadMethodCallException -``` - -Note how [timeouts](#timeouts) apply slightly differently when using streaming. -In streaming mode, the timeout value covers creating the underlying transport -connection, sending the HTTP request, receiving the HTTP response headers and -following any eventual [redirects](#redirects). In particular, the timeout value -does not take receiving (possibly large) response bodies into account. - -If you want to integrate the streaming response into a higher level API, then -working with Promise objects that resolve with Stream objects is often inconvenient. -Consider looking into also using [react/promise-stream](https://github.com/reactphp/promise-stream). -The resulting streaming code could look something like this: - -```php -use React\Promise\Stream; - -function download(Browser $browser, string $url): React\Stream\ReadableStreamInterface { - return Stream\unwrapReadable( - $browser->requestStreaming('GET', $url)->then(function (Psr\Http\Message\ResponseInterface $response) { - return $response->getBody(); - }) - ); -} - -$stream = download($browser, $url); -$stream->on('data', function ($data) { - echo $data; -}); -$stream->on('error', function (Exception $e) { - echo 'Error: ' . $e->getMessage() . PHP_EOL; -}); -``` - -See also the [`requestStreaming()`](#requeststreaming) method for more details. - -### Streaming request - -Besides streaming the response body, you can also stream the request body. -This can be useful if you want to send big POST requests (uploading files etc.) -or process many outgoing streams at once. -Instead of passing the body as a string, you can simply pass an instance -implementing [ReactPHP's `ReadableStreamInterface`](https://github.com/reactphp/stream#readablestreaminterface) -to the [request methods](#request-methods) like this: - -```php -$browser->post($url, array(), $stream)->then(function (Psr\Http\Message\ResponseInterface $response) { - echo 'Successfully sent.'; -}, function (Exception $e) { - echo 'Error: ' . $e->getMessage() . PHP_EOL; -}); -``` - -If you're using a streaming request body (`React\Stream\ReadableStreamInterface`), it will -default to using `Transfer-Encoding: chunked` or you have to explicitly pass in a -matching `Content-Length` request header like so: - -```php -$body = new React\Stream\ThroughStream(); -Loop::addTimer(1.0, function () use ($body) { - $body->end("hello world"); -}); - -$browser->post($url, array('Content-Length' => '11'), $body); -``` - -If the streaming request body emits an `error` event or is explicitly closed -without emitting a successful `end` event first, the request will automatically -be closed and rejected. - -### HTTP proxy - -You can also establish your outgoing connections through an HTTP CONNECT proxy server -by adding a dependency to [clue/reactphp-http-proxy](https://github.com/clue/reactphp-http-proxy). - -HTTP CONNECT proxy servers (also commonly known as "HTTPS proxy" or "SSL proxy") -are commonly used to tunnel HTTPS traffic through an intermediary ("proxy"), to -conceal the origin address (anonymity) or to circumvent address blocking -(geoblocking). While many (public) HTTP CONNECT proxy servers often limit this -to HTTPS port `443` only, this can technically be used to tunnel any TCP/IP-based -protocol, such as plain HTTP and TLS-encrypted HTTPS. - -```php -$proxy = new Clue\React\HttpProxy\ProxyConnector('127.0.0.1:8080'); - -$connector = new React\Socket\Connector(array( - 'tcp' => $proxy, - 'dns' => false -)); - -$browser = new React\Http\Browser($connector); -``` - -See also the [HTTP proxy example](examples/11-client-http-proxy.php). - -### SOCKS proxy - -You can also establish your outgoing connections through a SOCKS proxy server -by adding a dependency to [clue/reactphp-socks](https://github.com/clue/reactphp-socks). - -The SOCKS proxy protocol family (SOCKS5, SOCKS4 and SOCKS4a) is commonly used to -tunnel HTTP(S) traffic through an intermediary ("proxy"), to conceal the origin -address (anonymity) or to circumvent address blocking (geoblocking). While many -(public) SOCKS proxy servers often limit this to HTTP(S) port `80` and `443` -only, this can technically be used to tunnel any TCP/IP-based protocol. - -```php -$proxy = new Clue\React\Socks\Client('127.0.0.1:1080'); - -$connector = new React\Socket\Connector(array( - 'tcp' => $proxy, - 'dns' => false -)); - -$browser = new React\Http\Browser($connector); -``` - -See also the [SOCKS proxy example](examples/12-client-socks-proxy.php). - -### SSH proxy - -You can also establish your outgoing connections through an SSH server -by adding a dependency to [clue/reactphp-ssh-proxy](https://github.com/clue/reactphp-ssh-proxy). - -[Secure Shell (SSH)](https://en.wikipedia.org/wiki/Secure_Shell) is a secure -network protocol that is most commonly used to access a login shell on a remote -server. Its architecture allows it to use multiple secure channels over a single -connection. Among others, this can also be used to create an "SSH tunnel", which -is commonly used to tunnel HTTP(S) traffic through an intermediary ("proxy"), to -conceal the origin address (anonymity) or to circumvent address blocking -(geoblocking). This can be used to tunnel any TCP/IP-based protocol (HTTP, SMTP, -IMAP etc.), allows you to access local services that are otherwise not accessible -from the outside (database behind firewall) and as such can also be used for -plain HTTP and TLS-encrypted HTTPS. - -```php -$proxy = new Clue\React\SshProxy\SshSocksConnector('alice@example.com'); - -$connector = new React\Socket\Connector(array( - 'tcp' => $proxy, - 'dns' => false -)); - -$browser = new React\Http\Browser($connector); -``` - -See also the [SSH proxy example](examples/13-client-ssh-proxy.php). - -### Unix domain sockets - -By default, this library supports transport over plaintext TCP/IP and secure -TLS connections for the `http://` and `https://` URL schemes respectively. -This library also supports Unix domain sockets (UDS) when explicitly configured. - -In order to use a UDS path, you have to explicitly configure the connector to -override the destination URL so that the hostname given in the request URL will -no longer be used to establish the connection: - -```php -$connector = new React\Socket\FixedUriConnector( - 'unix:///var/run/docker.sock', - new React\Socket\UnixConnector() -); - -$browser = new React\Http\Browser($connector); - -$client->get('http://localhost/info')->then(function (Psr\Http\Message\ResponseInterface $response) { - var_dump($response->getHeaders(), (string)$response->getBody()); -}, function (Exception $e) { - echo 'Error: ' . $e->getMessage() . PHP_EOL; -}); -``` - -See also the [Unix Domain Sockets (UDS) example](examples/14-client-unix-domain-sockets.php). - - -## Server Usage - -### HttpServer - - - -The `React\Http\HttpServer` class is responsible for handling incoming connections and then -processing each incoming HTTP request. - -When a complete HTTP request has been received, it will invoke the given -request handler function. This request handler function needs to be passed to -the constructor and will be invoked with the respective [request](#server-request) -object and expects a [response](#server-response) object in return: - -```php -$http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) { - return React\Http\Message\Response::plaintext( - "Hello World!\n" - ); -}); -``` - -Each incoming HTTP request message is always represented by the -[PSR-7 `ServerRequestInterface`](https://www.php-fig.org/psr/psr-7/#321-psrhttpmessageserverrequestinterface), -see also following [request](#server-request) chapter for more details. - -Each outgoing HTTP response message is always represented by the -[PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface), -see also following [response](#server-response) chapter for more details. - -This class takes an optional `LoopInterface|null $loop` parameter that can be used to -pass the event loop instance to use for this object. You can use a `null` value -here in order to use the [default loop](https://github.com/reactphp/event-loop#loop). -This value SHOULD NOT be given unless you're sure you want to explicitly use a -given event loop instance. - -In order to start listening for any incoming connections, the `HttpServer` needs -to be attached to an instance of -[`React\Socket\ServerInterface`](https://github.com/reactphp/socket#serverinterface) -through the [`listen()`](#listen) method as described in the following -chapter. In its most simple form, you can attach this to a -[`React\Socket\SocketServer`](https://github.com/reactphp/socket#socketserver) -in order to start a plaintext HTTP server like this: - -```php -$http = new React\Http\HttpServer($handler); - -$socket = new React\Socket\SocketServer('0.0.0.0:8080'); -$http->listen($socket); -``` - -See also the [`listen()`](#listen) method and the -[hello world server example](examples/51-server-hello-world.php) -for more details. - -By default, the `HttpServer` buffers and parses the complete incoming HTTP -request in memory. It will invoke the given request handler function when the -complete request headers and request body has been received. This means the -[request](#server-request) object passed to your request handler function will be -fully compatible with PSR-7 (http-message). This provides sane defaults for -80% of the use cases and is the recommended way to use this library unless -you're sure you know what you're doing. - -On the other hand, buffering complete HTTP requests in memory until they can -be processed by your request handler function means that this class has to -employ a number of limits to avoid consuming too much memory. In order to -take the more advanced configuration out your hand, it respects setting from -your [`php.ini`](https://www.php.net/manual/en/ini.core.php) to apply its -default settings. This is a list of PHP settings this class respects with -their respective default values: - -``` -memory_limit 128M -post_max_size 8M // capped at 64K - -enable_post_data_reading 1 -max_input_nesting_level 64 -max_input_vars 1000 - -file_uploads 1 -upload_max_filesize 2M -max_file_uploads 20 -``` - -In particular, the `post_max_size` setting limits how much memory a single -HTTP request is allowed to consume while buffering its request body. This -needs to be limited because the server can process a large number of requests -concurrently, so the server may potentially consume a large amount of memory -otherwise. To support higher concurrency by default, this value is capped -at `64K`. If you assign a higher value, it will only allow `64K` by default. -If a request exceeds this limit, its request body will be ignored and it will -be processed like a request with no request body at all. See below for -explicit configuration to override this setting. - -By default, this class will try to avoid consuming more than half of your -`memory_limit` for buffering multiple concurrent HTTP requests. As such, with -the above default settings of `128M` max, it will try to consume no more than -`64M` for buffering multiple concurrent HTTP requests. As a consequence, it -will limit the concurrency to `1024` HTTP requests with the above defaults. - -It is imperative that you assign reasonable values to your PHP ini settings. -It is usually recommended to not support buffering incoming HTTP requests -with a large HTTP request body (e.g. large file uploads). If you want to -increase this buffer size, you will have to also increase the total memory -limit to allow for more concurrent requests (set `memory_limit 512M` or more) -or explicitly limit concurrency. - -In order to override the above buffering defaults, you can configure the -`HttpServer` explicitly. You can use the -[`LimitConcurrentRequestsMiddleware`](#limitconcurrentrequestsmiddleware) and -[`RequestBodyBufferMiddleware`](#requestbodybuffermiddleware) (see below) -to explicitly configure the total number of requests that can be handled at -once like this: - -```php -$http = new React\Http\HttpServer( - new React\Http\Middleware\StreamingRequestMiddleware(), - new React\Http\Middleware\LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers - new React\Http\Middleware\RequestBodyBufferMiddleware(2 * 1024 * 1024), // 2 MiB per request - new React\Http\Middleware\RequestBodyParserMiddleware(), - $handler -); -``` - -In this example, we allow processing up to 100 concurrent requests at once -and each request can buffer up to `2M`. This means you may have to keep a -maximum of `200M` of memory for incoming request body buffers. Accordingly, -you need to adjust the `memory_limit` ini setting to allow for these buffers -plus your actual application logic memory requirements (think `512M` or more). - -> Internally, this class automatically assigns these middleware handlers - automatically when no [`StreamingRequestMiddleware`](#streamingrequestmiddleware) - is given. Accordingly, you can use this example to override all default - settings to implement custom limits. - -As an alternative to buffering the complete request body in memory, you can -also use a streaming approach where only small chunks of data have to be kept -in memory: - -```php -$http = new React\Http\HttpServer( - new React\Http\Middleware\StreamingRequestMiddleware(), - $handler -); -``` - -In this case, it will invoke the request handler function once the HTTP -request headers have been received, i.e. before receiving the potentially -much larger HTTP request body. This means the [request](#server-request) passed to -your request handler function may not be fully compatible with PSR-7. This is -specifically designed to help with more advanced use cases where you want to -have full control over consuming the incoming HTTP request body and -concurrency settings. See also [streaming incoming request](#streaming-incoming-request) -below for more details. - -> Changelog v1.5.0: This class has been renamed to `HttpServer` from the - previous `Server` class in order to avoid any ambiguities. - The previous name has been deprecated and should not be used anymore. - -### listen() - -The `listen(React\Socket\ServerInterface $socket): void` method can be used to -start listening for HTTP requests on the given socket server instance. - -The given [`React\Socket\ServerInterface`](https://github.com/reactphp/socket#serverinterface) -is responsible for emitting the underlying streaming connections. This -HTTP server needs to be attached to it in order to process any -connections and pase incoming streaming data as incoming HTTP request -messages. In its most common form, you can attach this to a -[`React\Socket\SocketServer`](https://github.com/reactphp/socket#socketserver) -in order to start a plaintext HTTP server like this: - -```php -$http = new React\Http\HttpServer($handler); - -$socket = new React\Socket\SocketServer('0.0.0.0:8080'); -$http->listen($socket); -``` - -See also [hello world server example](examples/51-server-hello-world.php) -for more details. - -This example will start listening for HTTP requests on the alternative -HTTP port `8080` on all interfaces (publicly). As an alternative, it is -very common to use a reverse proxy and let this HTTP server listen on the -localhost (loopback) interface only by using the listen address -`127.0.0.1:8080` instead. This way, you host your application(s) on the -default HTTP port `80` and only route specific requests to this HTTP -server. - -Likewise, it's usually recommended to use a reverse proxy setup to accept -secure HTTPS requests on default HTTPS port `443` (TLS termination) and -only route plaintext requests to this HTTP server. As an alternative, you -can also accept secure HTTPS requests with this HTTP server by attaching -this to a [`React\Socket\SocketServer`](https://github.com/reactphp/socket#socketserver) -using a secure TLS listen address, a certificate file and optional -`passphrase` like this: - -```php -$http = new React\Http\HttpServer($handler); - -$socket = new React\Socket\SocketServer('tls://0.0.0.0:8443', array( - 'tls' => array( - 'local_cert' => __DIR__ . '/localhost.pem' - ) -)); -$http->listen($socket); -``` - -See also [hello world HTTPS example](examples/61-server-hello-world-https.php) -for more details. - -### Server Request - -As seen above, the [`HttpServer`](#httpserver) class is responsible for handling -incoming connections and then processing each incoming HTTP request. - -The request object will be processed once the request has -been received by the client. -This request object implements the -[PSR-7 `ServerRequestInterface`](https://www.php-fig.org/psr/psr-7/#321-psrhttpmessageserverrequestinterface) -which in turn extends the -[PSR-7 `RequestInterface`](https://www.php-fig.org/psr/psr-7/#32-psrhttpmessagerequestinterface) -and will be passed to the callback function like this. - - ```php -$http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) { - $body = "The method of the request is: " . $request->getMethod() . "\n"; - $body .= "The requested path is: " . $request->getUri()->getPath() . "\n"; - - return React\Http\Message\Response::plaintext( - $body - ); -}); -``` - -For more details about the request object, also check out the documentation of -[PSR-7 `ServerRequestInterface`](https://www.php-fig.org/psr/psr-7/#321-psrhttpmessageserverrequestinterface) -and -[PSR-7 `RequestInterface`](https://www.php-fig.org/psr/psr-7/#32-psrhttpmessagerequestinterface). - -#### Request parameters - -The `getServerParams(): mixed[]` method can be used to -get server-side parameters similar to the `$_SERVER` variable. -The following parameters are currently available: - -* `REMOTE_ADDR` - The IP address of the request sender -* `REMOTE_PORT` - Port of the request sender -* `SERVER_ADDR` - The IP address of the server -* `SERVER_PORT` - The port of the server -* `REQUEST_TIME` - Unix timestamp when the complete request header has been received, - as integer similar to `time()` -* `REQUEST_TIME_FLOAT` - Unix timestamp when the complete request header has been received, - as float similar to `microtime(true)` -* `HTTPS` - Set to 'on' if the request used HTTPS, otherwise it won't be set - -```php -$http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) { - $body = "Your IP is: " . $request->getServerParams()['REMOTE_ADDR'] . "\n"; - - return React\Http\Message\Response::plaintext( - $body - ); -}); -``` - -See also [whatsmyip server example](examples/53-server-whatsmyip.php). - -> Advanced: Note that address parameters will not be set if you're listening on - a Unix domain socket (UDS) path as this protocol lacks the concept of - host/port. - -#### Query parameters - -The `getQueryParams(): array` method can be used to get the query parameters -similiar to the `$_GET` variable. - -```php -$http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) { - $queryParams = $request->getQueryParams(); - - $body = 'The query parameter "foo" is not set. Click the following link '; - $body .= 'to use query parameter in your request'; - - if (isset($queryParams['foo'])) { - $body = 'The value of "foo" is: ' . htmlspecialchars($queryParams['foo']); - } - - return React\Http\Message\Response::html( - $body - ); -}); -``` - -The response in the above example will return a response body with a link. -The URL contains the query parameter `foo` with the value `bar`. -Use [`htmlentities`](https://www.php.net/manual/en/function.htmlentities.php) -like in this example to prevent -[Cross-Site Scripting (abbreviated as XSS)](https://en.wikipedia.org/wiki/Cross-site_scripting). - -See also [server query parameters example](examples/54-server-query-parameter.php). - -#### Request body - -By default, the [`Server`](#httpserver) will buffer and parse the full request body -in memory. This means the given request object includes the parsed request body -and any file uploads. - -> As an alternative to the default buffering logic, you can also use the - [`StreamingRequestMiddleware`](#streamingrequestmiddleware). Jump to the next - chapter to learn more about how to process a - [streaming incoming request](#streaming-incoming-request). - -As stated above, each incoming HTTP request is always represented by the -[PSR-7 `ServerRequestInterface`](https://www.php-fig.org/psr/psr-7/#321-psrhttpmessageserverrequestinterface). -This interface provides several methods that are useful when working with the -incoming request body as described below. - -The `getParsedBody(): null|array|object` method can be used to -get the parsed request body, similar to -[PHP's `$_POST` variable](https://www.php.net/manual/en/reserved.variables.post.php). -This method may return a (possibly nested) array structure with all body -parameters or a `null` value if the request body could not be parsed. -By default, this method will only return parsed data for requests using -`Content-Type: application/x-www-form-urlencoded` or `Content-Type: multipart/form-data` -request headers (commonly used for `POST` requests for HTML form submission data). - -```php -$http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) { - $name = $request->getParsedBody()['name'] ?? 'anonymous'; - - return React\Http\Message\Response::plaintext( - "Hello $name!\n" - ); -}); -``` - -See also [form upload example](examples/62-server-form-upload.php) for more details. - -The `getBody(): StreamInterface` method can be used to -get the raw data from this request body, similar to -[PHP's `php://input` stream](https://www.php.net/manual/en/wrappers.php.php#wrappers.php.input). -This method returns an instance of the request body represented by the -[PSR-7 `StreamInterface`](https://www.php-fig.org/psr/psr-7/#34-psrhttpmessagestreaminterface). -This is particularly useful when using a custom request body that will not -otherwise be parsed by default, such as a JSON (`Content-Type: application/json`) or -an XML (`Content-Type: application/xml`) request body (which is commonly used for -`POST`, `PUT` or `PATCH` requests in JSON-based or RESTful/RESTish APIs). - -```php -$http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) { - $data = json_decode((string)$request->getBody()); - $name = $data->name ?? 'anonymous'; - - return React\Http\Message\Response::json( - ['message' => "Hello $name!"] - ); -}); -``` - -See also [JSON API server example](examples/59-server-json-api.php) for more details. - -The `getUploadedFiles(): array` method can be used to -get the uploaded files in this request, similar to -[PHP's `$_FILES` variable](https://www.php.net/manual/en/reserved.variables.files.php). -This method returns a (possibly nested) array structure with all file uploads, each represented by the -[PSR-7 `UploadedFileInterface`](https://www.php-fig.org/psr/psr-7/#36-psrhttpmessageuploadedfileinterface). -This array will only be filled when using the `Content-Type: multipart/form-data` -request header (commonly used for `POST` requests for HTML file uploads). - -```php -$http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) { - $files = $request->getUploadedFiles(); - $name = isset($files['avatar']) ? $files['avatar']->getClientFilename() : 'nothing'; - - return React\Http\Message\Response::plaintext( - "Uploaded $name\n" - ); -}); -``` - -See also [form upload server example](examples/62-server-form-upload.php) for more details. - -The `getSize(): ?int` method can be used to -get the size of the request body, similar to PHP's `$_SERVER['CONTENT_LENGTH']` variable. -This method returns the complete size of the request body measured in number -of bytes as defined by the message boundaries. -This value may be `0` if the request message does not contain a request body -(such as a simple `GET` request). -This method operates on the buffered request body, i.e. the request body size -is always known, even when the request does not specify a `Content-Length` request -header or when using `Transfer-Encoding: chunked` for HTTP/1.1 requests. - -> Note: The `HttpServer` automatically takes care of handling requests with the - additional `Expect: 100-continue` request header. When HTTP/1.1 clients want to - send a bigger request body, they MAY send only the request headers with an - additional `Expect: 100-continue` request header and wait before sending the actual - (large) message body. In this case the server will automatically send an - intermediary `HTTP/1.1 100 Continue` response to the client. This ensures you - will receive the request body without a delay as expected. - -#### Streaming incoming request - -If you're using the advanced [`StreamingRequestMiddleware`](#streamingrequestmiddleware), -the request object will be processed once the request headers have been received. -This means that this happens irrespective of (i.e. *before*) receiving the -(potentially much larger) request body. - -> Note that this is non-standard behavior considered advanced usage. Jump to the - previous chapter to learn more about how to process a buffered [request body](#request-body). - -While this may be uncommon in the PHP ecosystem, this is actually a very powerful -approach that gives you several advantages not otherwise possible: - -* React to requests *before* receiving a large request body, - such as rejecting an unauthenticated request or one that exceeds allowed - message lengths (file uploads). -* Start processing parts of the request body before the remainder of the request - body arrives or if the sender is slowly streaming data. -* Process a large request body without having to buffer anything in memory, - such as accepting a huge file upload or possibly unlimited request body stream. - -The `getBody(): StreamInterface` method can be used to -access the request body stream. -In the streaming mode, this method returns a stream instance that implements both the -[PSR-7 `StreamInterface`](https://www.php-fig.org/psr/psr-7/#34-psrhttpmessagestreaminterface) -and the [ReactPHP `ReadableStreamInterface`](https://github.com/reactphp/stream#readablestreaminterface). -However, most of the -[PSR-7 `StreamInterface`](https://www.php-fig.org/psr/psr-7/#34-psrhttpmessagestreaminterface) -methods have been designed under the assumption of being in control of a -synchronous request body. -Given that this does not apply to this server, the following -[PSR-7 `StreamInterface`](https://www.php-fig.org/psr/psr-7/#34-psrhttpmessagestreaminterface) -methods are not used and SHOULD NOT be called: -`tell()`, `eof()`, `seek()`, `rewind()`, `write()` and `read()`. -If this is an issue for your use case and/or you want to access uploaded files, -it's highly recommended to use a buffered [request body](#request-body) or use the -[`RequestBodyBufferMiddleware`](#requestbodybuffermiddleware) instead. -The [ReactPHP `ReadableStreamInterface`](https://github.com/reactphp/stream#readablestreaminterface) -gives you access to the incoming request body as the individual chunks arrive: - -```php -$http = new React\Http\HttpServer( - new React\Http\Middleware\StreamingRequestMiddleware(), - function (Psr\Http\Message\ServerRequestInterface $request) { - $body = $request->getBody(); - assert($body instanceof Psr\Http\Message\StreamInterface); - assert($body instanceof React\Stream\ReadableStreamInterface); - - return new React\Promise\Promise(function ($resolve, $reject) use ($body) { - $bytes = 0; - $body->on('data', function ($data) use (&$bytes) { - $bytes += strlen($data); - }); - - $body->on('end', function () use ($resolve, &$bytes){ - $resolve(React\Http\Message\Response::plaintext( - "Received $bytes bytes\n" - )); - }); - - // an error occures e.g. on invalid chunked encoded data or an unexpected 'end' event - $body->on('error', function (Exception $e) use ($resolve, &$bytes) { - $resolve(React\Http\Message\Response::plaintext( - "Encountered error after $bytes bytes: {$e->getMessage()}\n" - )->withStatus(React\Http\Message\Response::STATUS_BAD_REQUEST)); - }); - }); - } -); -``` - -The above example simply counts the number of bytes received in the request body. -This can be used as a skeleton for buffering or processing the request body. - -See also [streaming request server example](examples/63-server-streaming-request.php) for more details. - -The `data` event will be emitted whenever new data is available on the request -body stream. -The server also automatically takes care of decoding any incoming requests using -`Transfer-Encoding: chunked` and will only emit the actual payload as data. - -The `end` event will be emitted when the request body stream terminates -successfully, i.e. it was read until its expected end. - -The `error` event will be emitted in case the request stream contains invalid -data for `Transfer-Encoding: chunked` or when the connection closes before -the complete request stream has been received. -The server will automatically stop reading from the connection and discard all -incoming data instead of closing it. -A response message can still be sent (unless the connection is already closed). - -A `close` event will be emitted after an `error` or `end` event. - -For more details about the request body stream, check out the documentation of -[ReactPHP `ReadableStreamInterface`](https://github.com/reactphp/stream#readablestreaminterface). - -The `getSize(): ?int` method can be used to -get the size of the request body, similar to PHP's `$_SERVER['CONTENT_LENGTH']` variable. -This method returns the complete size of the request body measured in number -of bytes as defined by the message boundaries. -This value may be `0` if the request message does not contain a request body -(such as a simple `GET` request). -This method operates on the streaming request body, i.e. the request body size -may be unknown (`null`) when using `Transfer-Encoding: chunked` for HTTP/1.1 requests. - -```php -$http = new React\Http\HttpServer( - new React\Http\Middleware\StreamingRequestMiddleware(), - function (Psr\Http\Message\ServerRequestInterface $request) { - $size = $request->getBody()->getSize(); - if ($size === null) { - $body = "The request does not contain an explicit length. "; - $body .= "This example does not accept chunked transfer encoding.\n"; - - return React\Http\Message\Response::plaintext( - $body - )->withStatus(React\Http\Message\Response::STATUS_LENGTH_REQUIRED); - } - - return React\Http\Message\Response::plaintext( - "Request body size: " . $size . " bytes\n" - ); - } -); -``` - -> Note: The `HttpServer` automatically takes care of handling requests with the - additional `Expect: 100-continue` request header. When HTTP/1.1 clients want to - send a bigger request body, they MAY send only the request headers with an - additional `Expect: 100-continue` request header and wait before sending the actual - (large) message body. In this case the server will automatically send an - intermediary `HTTP/1.1 100 Continue` response to the client. This ensures you - will receive the streaming request body without a delay as expected. - -#### Request method - -Note that the server supports *any* request method (including custom and non- -standard ones) and all request-target formats defined in the HTTP specs for each -respective method, including *normal* `origin-form` requests as well as -proxy requests in `absolute-form` and `authority-form`. -The `getUri(): UriInterface` method can be used to get the effective request -URI which provides you access to individiual URI components. -Note that (depending on the given `request-target`) certain URI components may -or may not be present, for example the `getPath(): string` method will return -an empty string for requests in `asterisk-form` or `authority-form`. -Its `getHost(): string` method will return the host as determined by the -effective request URI, which defaults to the local socket address if an HTTP/1.0 -client did not specify one (i.e. no `Host` header). -Its `getScheme(): string` method will return `http` or `https` depending -on whether the request was made over a secure TLS connection to the target host. - -The `Host` header value will be sanitized to match this host component plus the -port component only if it is non-standard for this URI scheme. - -You can use `getMethod(): string` and `getRequestTarget(): string` to -check this is an accepted request and may want to reject other requests with -an appropriate error code, such as `400` (Bad Request) or `405` (Method Not -Allowed). - -> The `CONNECT` method is useful in a tunneling setup (HTTPS proxy) and not - something most HTTP servers would want to care about. - Note that if you want to handle this method, the client MAY send a different - request-target than the `Host` header value (such as removing default ports) - and the request-target MUST take precendence when forwarding. - -#### Cookie parameters - -The `getCookieParams(): string[]` method can be used to -get all cookies sent with the current request. - -```php -$http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) { - $key = 'greeting'; - - if (isset($request->getCookieParams()[$key])) { - $body = "Your cookie value is: " . $request->getCookieParams()[$key] . "\n"; - - return React\Http\Message\Response::plaintext( - $body - ); - } - - return React\Http\Message\Response::plaintext( - "Your cookie has been set.\n" - )->withHeader('Set-Cookie', $key . '=' . urlencode('Hello world!')); -}); -``` - -The above example will try to set a cookie on first access and -will try to print the cookie value on all subsequent tries. -Note how the example uses the `urlencode()` function to encode -non-alphanumeric characters. -This encoding is also used internally when decoding the name and value of cookies -(which is in line with other implementations, such as PHP's cookie functions). - -See also [cookie server example](examples/55-server-cookie-handling.php) for more details. - -#### Invalid request - -The `HttpServer` class supports both HTTP/1.1 and HTTP/1.0 request messages. -If a client sends an invalid request message, uses an invalid HTTP -protocol version or sends an invalid `Transfer-Encoding` request header value, -the server will automatically send a `400` (Bad Request) HTTP error response -to the client and close the connection. -On top of this, it will emit an `error` event that can be used for logging -purposes like this: - -```php -$http->on('error', function (Exception $e) { - echo 'Error: ' . $e->getMessage() . PHP_EOL; -}); -``` - -Note that the server will also emit an `error` event if you do not return a -valid response object from your request handler function. See also -[invalid response](#invalid-response) for more details. - -### Server Response - -The callback function passed to the constructor of the [`HttpServer`](#httpserver) is -responsible for processing the request and returning a response, which will be -delivered to the client. - -This function MUST return an instance implementing -[PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface) -object or a -[ReactPHP Promise](https://github.com/reactphp/promise) -which resolves with a [PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface) object. - -This projects ships a [`Response` class](#response) which implements the -[PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface). -In its most simple form, you can use it like this: - -```php -$http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) { - return React\Http\Message\Response::plaintext( - "Hello World!\n" - ); -}); -``` - -We use this [`Response` class](#response) throughout our project examples, but -feel free to use any other implementation of the -[PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface). -See also the [`Response` class](#response) for more details. - -#### Deferred response - -The example above returns the response directly, because it needs -no time to be processed. -Using a database, the file system or long calculations -(in fact every action that will take >=1ms) to create your -response, will slow down the server. -To prevent this you SHOULD use a -[ReactPHP Promise](https://github.com/reactphp/promise#reactpromise). -This example shows how such a long-term action could look like: - -```php -$http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) { - $promise = new Promise(function ($resolve, $reject) { - Loop::addTimer(1.5, function() use ($resolve) { - $resolve(); - }); - }); - - return $promise->then(function () { - return React\Http\Message\Response::plaintext( - "Hello World!" - ); - }); -}); -``` - -The above example will create a response after 1.5 second. -This example shows that you need a promise, -if your response needs time to created. -The `ReactPHP Promise` will resolve in a `Response` object when the request -body ends. -If the client closes the connection while the promise is still pending, the -promise will automatically be cancelled. -The promise cancellation handler can be used to clean up any pending resources -allocated in this case (if applicable). -If a promise is resolved after the client closes, it will simply be ignored. - -#### Streaming outgoing response - -The `Response` class in this project supports to add an instance which implements the -[ReactPHP `ReadableStreamInterface`](https://github.com/reactphp/stream#readablestreaminterface) -for the response body. -So you are able stream data directly into the response body. -Note that other implementations of the -[PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface) -may only support strings. - -```php -$http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) { - $stream = new ThroughStream(); - - // send some data every once in a while with periodic timer - $timer = Loop::addPeriodicTimer(0.5, function () use ($stream) { - $stream->write(microtime(true) . PHP_EOL); - }); - - // end stream after a few seconds - $timeout = Loop::addTimer(5.0, function() use ($stream, $timer) { - Loop::cancelTimer($timer); - $stream->end(); - }); - - // stop timer if stream is closed (such as when connection is closed) - $stream->on('close', function () use ($timer, $timeout) { - Loop::cancelTimer($timer); - Loop::cancelTimer($timeout); - }); - - return new React\Http\Message\Response( - React\Http\Message\Response::STATUS_OK, - array( - 'Content-Type' => 'text/plain' - ), - $stream - ); -}); -``` - -The above example will emit every 0.5 seconds the current Unix timestamp -with microseconds as float to the client and will end after 5 seconds. -This is just a example you could use of the streaming, -you could also send a big amount of data via little chunks -or use it for body data that needs to calculated. - -If the request handler resolves with a response stream that is already closed, -it will simply send an empty response body. -If the client closes the connection while the stream is still open, the -response stream will automatically be closed. -If a promise is resolved with a streaming body after the client closes, the -response stream will automatically be closed. -The `close` event can be used to clean up any pending resources allocated -in this case (if applicable). - -> Note that special care has to be taken if you use a body stream instance that - implements ReactPHP's - [`DuplexStreamInterface`](https://github.com/reactphp/stream#duplexstreaminterface) - (such as the `ThroughStream` in the above example). -> -> For *most* cases, this will simply only consume its readable side and forward - (send) any data that is emitted by the stream, thus entirely ignoring the - writable side of the stream. - If however this is either a `101` (Switching Protocols) response or a `2xx` - (Successful) response to a `CONNECT` method, it will also *write* data to the - writable side of the stream. - This can be avoided by either rejecting all requests with the `CONNECT` - method (which is what most *normal* origin HTTP servers would likely do) or - or ensuring that only ever an instance of - [ReactPHP's `ReadableStreamInterface`](https://github.com/reactphp/stream#readablestreaminterface) - is used. -> -> The `101` (Switching Protocols) response code is useful for the more advanced - `Upgrade` requests, such as upgrading to the WebSocket protocol or - implementing custom protocol logic that is out of scope of the HTTP specs and - this HTTP library. - If you want to handle the `Upgrade: WebSocket` header, you will likely want - to look into using [Ratchet](http://socketo.me/) instead. - If you want to handle a custom protocol, you will likely want to look into the - [HTTP specs](https://tools.ietf.org/html/rfc7230#section-6.7) and also see - [examples #81 and #82](examples/) for more details. - In particular, the `101` (Switching Protocols) response code MUST NOT be used - unless you send an `Upgrade` response header value that is also present in - the corresponding HTTP/1.1 `Upgrade` request header value. - The server automatically takes care of sending a `Connection: upgrade` - header value in this case, so you don't have to. -> -> The `CONNECT` method is useful in a tunneling setup (HTTPS proxy) and not - something most origin HTTP servers would want to care about. - The HTTP specs define an opaque "tunneling mode" for this method and make no - use of the message body. - For consistency reasons, this library uses a `DuplexStreamInterface` in the - response body for tunneled application data. - This implies that that a `2xx` (Successful) response to a `CONNECT` request - can in fact use a streaming response body for the tunneled application data, - so that any raw data the client sends over the connection will be piped - through the writable stream for consumption. - Note that while the HTTP specs make no use of the request body for `CONNECT` - requests, one may still be present. Normal request body processing applies - here and the connection will only turn to "tunneling mode" after the request - body has been processed (which should be empty in most cases). - See also [HTTP CONNECT server example](examples/72-server-http-connect-proxy.php) for more details. - -#### Response length - -If the response body size is known, a `Content-Length` response header will be -added automatically. This is the most common use case, for example when using -a `string` response body like this: - -```php -$http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) { - return React\Http\Message\Response::plaintext( - "Hello World!\n" - ); -}); -``` - -If the response body size is unknown, a `Content-Length` response header can not -be added automatically. When using a [streaming outgoing response](#streaming-outgoing-response) -without an explicit `Content-Length` response header, outgoing HTTP/1.1 response -messages will automatically use `Transfer-Encoding: chunked` while legacy HTTP/1.0 -response messages will contain the plain response body. If you know the length -of your streaming response body, you MAY want to specify it explicitly like this: - -```php -$http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) { - $stream = new ThroughStream(); - - Loop::addTimer(2.0, function () use ($stream) { - $stream->end("Hello World!\n"); - }); - - return new React\Http\Message\Response( - React\Http\Message\Response::STATUS_OK, - array( - 'Content-Length' => '13', - 'Content-Type' => 'text/plain', - ), - $stream - ); -}); -``` - -Any response to a `HEAD` request and any response with a `1xx` (Informational), -`204` (No Content) or `304` (Not Modified) status code will *not* include a -message body as per the HTTP specs. -This means that your callback does not have to take special care of this and any -response body will simply be ignored. - -Similarly, any `2xx` (Successful) response to a `CONNECT` request, any response -with a `1xx` (Informational) or `204` (No Content) status code will *not* -include a `Content-Length` or `Transfer-Encoding` header as these do not apply -to these messages. -Note that a response to a `HEAD` request and any response with a `304` (Not -Modified) status code MAY include these headers even though -the message does not contain a response body, because these header would apply -to the message if the same request would have used an (unconditional) `GET`. - -#### Invalid response - -As stated above, each outgoing HTTP response is always represented by the -[PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface). -If your request handler function returns an invalid value or throws an -unhandled `Exception` or `Throwable`, the server will automatically send a `500` -(Internal Server Error) HTTP error response to the client. -On top of this, it will emit an `error` event that can be used for logging -purposes like this: - -```php -$http->on('error', function (Exception $e) { - echo 'Error: ' . $e->getMessage() . PHP_EOL; - if ($e->getPrevious() !== null) { - echo 'Previous: ' . $e->getPrevious()->getMessage() . PHP_EOL; - } -}); -``` - -Note that the server will also emit an `error` event if the client sends an -invalid HTTP request that never reaches your request handler function. See -also [invalid request](#invalid-request) for more details. -Additionally, a [streaming incoming request](#streaming-incoming-request) body -can also emit an `error` event on the request body. - -The server will only send a very generic `500` (Interval Server Error) HTTP -error response without any further details to the client if an unhandled -error occurs. While we understand this might make initial debugging harder, -it also means that the server does not leak any application details or stack -traces to the outside by default. It is usually recommended to catch any -`Exception` or `Throwable` within your request handler function or alternatively -use a [`middleware`](#middleware) to avoid this generic error handling and -create your own HTTP response message instead. - -#### Default response headers - -When a response is returned from the request handler function, it will be -processed by the [`HttpServer`](#httpserver) and then sent back to the client. - -A `Server: ReactPHP/1` response header will be added automatically. You can add -a custom `Server` response header like this: - -```php -$http = new React\Http\HttpServer(function (ServerRequestInterface $request) { - return new React\Http\Message\Response( - React\Http\Message\Response::STATUS_OK, - array( - 'Server' => 'PHP/3' - ) - ); -}); -``` - -If you do not want to send this `Sever` response header at all (such as when you -don't want to expose the underlying server software), you can use an empty -string value like this: - -```php -$http = new React\Http\HttpServer(function (ServerRequestInterface $request) { - return new React\Http\Message\Response( - React\Http\Message\Response::STATUS_OK, - array( - 'Server' => '' - ) - ); -}); -``` - -A `Date` response header will be added automatically with the current system -date and time if none is given. You can add a custom `Date` response header -like this: - -```php -$http = new React\Http\HttpServer(function (ServerRequestInterface $request) { - return new React\Http\Message\Response( - React\Http\Message\Response::STATUS_OK, - array( - 'Date' => gmdate('D, d M Y H:i:s \G\M\T') - ) - ); -}); -``` - -If you do not want to send this `Date` response header at all (such as when you -don't have an appropriate clock to rely on), you can use an empty string value -like this: - -```php -$http = new React\Http\HttpServer(function (ServerRequestInterface $request) { - return new React\Http\Message\Response( - React\Http\Message\Response::STATUS_OK, - array( - 'Date' => '' - ) - ); -}); -``` - -The `HttpServer` class will automatically add the protocol version of the request, -so you don't have to. For instance, if the client sends the request using the -HTTP/1.1 protocol version, the response message will also use the same protocol -version, no matter what version is returned from the request handler function. - -The server supports persistent connections. An appropriate `Connection: keep-alive` -or `Connection: close` response header will be added automatically, respecting the -matching request header value and HTTP default header values. The server is -responsible for handling the `Connection` response header, so you SHOULD NOT pass -this response header yourself, unless you explicitly want to override the user's -choice with a `Connection: close` response header. - -### Middleware - -As documented above, the [`HttpServer`](#httpserver) accepts a single request handler -argument that is responsible for processing an incoming HTTP request and then -creating and returning an outgoing HTTP response. - -Many common use cases involve validating, processing, manipulating the incoming -HTTP request before passing it to the final business logic request handler. -As such, this project supports the concept of middleware request handlers. - -#### Custom middleware - -A middleware request handler is expected to adhere the following rules: - -* It is a valid `callable`. -* It accepts an instance implementing - [PSR-7 `ServerRequestInterface`](https://www.php-fig.org/psr/psr-7/#321-psrhttpmessageserverrequestinterface) - as first argument and an optional `callable` as second argument. -* It returns either: - * An instance implementing - [PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface) - for direct consumption. - * Any promise which can be consumed by - [`Promise\resolve()`](https://reactphp.org/promise/#resolve) resolving to a - [PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface) - for deferred consumption. - * It MAY throw an `Exception` (or return a rejected promise) in order to - signal an error condition and abort the chain. -* It calls `$next($request)` to continue processing the next middleware - request handler or returns explicitly without calling `$next` to - abort the chain. - * The `$next` request handler (recursively) invokes the next request - handler from the chain with the same logic as above and returns (or throws) - as above. - * The `$request` may be modified prior to calling `$next($request)` to - change the incoming request the next middleware operates on. - * The `$next` return value may be consumed to modify the outgoing response. - * The `$next` request handler MAY be called more than once if you want to - implement custom "retry" logic etc. - -Note that this very simple definition allows you to use either anonymous -functions or any classes that use the magic `__invoke()` method. -This allows you to easily create custom middleware request handlers on the fly -or use a class based approach to ease using existing middleware implementations. - -While this project does provide the means to *use* middleware implementations, -it does not aim to *define* how middleware implementations should look like. -We realize that there's a vivid ecosystem of middleware implementations and -ongoing effort to standardize interfaces between these with -[PSR-15](https://www.php-fig.org/psr/psr-15/) (HTTP Server Request Handlers) -and support this goal. -As such, this project only bundles a few middleware implementations that are -required to match PHP's request behavior (see below) and otherwise actively -encourages [Third-Party Middleware](#third-party-middleware) implementations. - -In order to use middleware request handlers, simply pass a list of all -callables as defined above to the [`HttpServer`](#httpserver). -The following example adds a middleware request handler that adds the current time to the request as a -header (`Request-Time`) and a final request handler that always returns a `200 OK` status code without a body: - -```php -$http = new React\Http\HttpServer( - function (Psr\Http\Message\ServerRequestInterface $request, callable $next) { - $request = $request->withHeader('Request-Time', time()); - return $next($request); - }, - function (Psr\Http\Message\ServerRequestInterface $request) { - return new React\Http\Message\Response(React\Http\Message\Response::STATUS_OK); - } -); -``` - -> Note how the middleware request handler and the final request handler have a - very simple (and similar) interface. The only difference is that the final - request handler does not receive a `$next` handler. - -Similarly, you can use the result of the `$next` middleware request handler -function to modify the outgoing response. -Note that as per the above documentation, the `$next` middleware request handler may return a -[PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface) -directly or one wrapped in a promise for deferred resolution. -In order to simplify handling both paths, you can simply wrap this in a -[`Promise\resolve()`](https://reactphp.org/promise/#resolve) call like this: - -```php -$http = new React\Http\HttpServer( - function (Psr\Http\Message\ServerRequestInterface $request, callable $next) { - $promise = React\Promise\resolve($next($request)); - return $promise->then(function (ResponseInterface $response) { - return $response->withHeader('Content-Type', 'text/html'); - }); - }, - function (Psr\Http\Message\ServerRequestInterface $request) { - return new React\Http\Message\Response(React\Http\Message\Response::STATUS_OK); - } -); -``` - -Note that the `$next` middleware request handler may also throw an -`Exception` (or return a rejected promise) as described above. -The previous example does not catch any exceptions and would thus signal an -error condition to the `HttpServer`. -Alternatively, you can also catch any `Exception` to implement custom error -handling logic (or logging etc.) by wrapping this in a -[`Promise`](https://reactphp.org/promise/#promise) like this: - -```php -$http = new React\Http\HttpServer( - function (Psr\Http\Message\ServerRequestInterface $request, callable $next) { - $promise = new React\Promise\Promise(function ($resolve) use ($next, $request) { - $resolve($next($request)); - }); - return $promise->then(null, function (Exception $e) { - return React\Http\Message\Response::plaintext( - 'Internal error: ' . $e->getMessage() . "\n" - )->withStatus(React\Http\Message\Response::STATUS_INTERNAL_SERVER_ERROR); - }); - }, - function (Psr\Http\Message\ServerRequestInterface $request) { - if (mt_rand(0, 1) === 1) { - throw new RuntimeException('Database error'); - } - return new React\Http\Message\Response(React\Http\Message\Response::STATUS_OK); - } -); -``` - -#### Third-Party Middleware - -While this project does provide the means to *use* middleware implementations -(see above), it does not aim to *define* how middleware implementations should -look like. We realize that there's a vivid ecosystem of middleware -implementations and ongoing effort to standardize interfaces between these with -[PSR-15](https://www.php-fig.org/psr/psr-15/) (HTTP Server Request Handlers) -and support this goal. -As such, this project only bundles a few middleware implementations that are -required to match PHP's request behavior (see -[middleware implementations](#reacthttpmiddleware)) and otherwise actively -encourages third-party middleware implementations. - -While we would love to support PSR-15 directly in `react/http`, we understand -that this interface does not specifically target async APIs and as such does -not take advantage of promises for [deferred responses](#deferred-response). -The gist of this is that where PSR-15 enforces a -[PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface) -return value, we also accept a `PromiseInterface`. -As such, we suggest using the external -[PSR-15 middleware adapter](https://github.com/friends-of-reactphp/http-middleware-psr15-adapter) -that uses on the fly monkey patching of these return values which makes using -most PSR-15 middleware possible with this package without any changes required. - -Other than that, you can also use the above [middleware definition](#middleware) -to create custom middleware. A non-exhaustive list of third-party middleware can -be found at the [middleware wiki](https://github.com/reactphp/reactphp/wiki/Users#http-middleware). -If you build or know a custom middleware, make sure to let the world know and -feel free to add it to this list. - -## API - -### Browser - -The `React\Http\Browser` is responsible for sending HTTP requests to your HTTP server -and keeps track of pending incoming HTTP responses. - -```php -$browser = new React\Http\Browser(); -``` - -This class takes two optional arguments for more advanced usage: - -```php -// constructor signature as of v1.5.0 -$browser = new React\Http\Browser(?ConnectorInterface $connector = null, ?LoopInterface $loop = null); - -// legacy constructor signature before v1.5.0 -$browser = new React\Http\Browser(?LoopInterface $loop = null, ?ConnectorInterface $connector = null); -``` - -If you need custom connector settings (DNS resolution, TLS parameters, timeouts, -proxy servers etc.), you can explicitly pass a custom instance of the -[`ConnectorInterface`](https://github.com/reactphp/socket#connectorinterface): - -```php -$connector = new React\Socket\Connector(array( - 'dns' => '127.0.0.1', - 'tcp' => array( - 'bindto' => '192.168.10.1:0' - ), - 'tls' => array( - 'verify_peer' => false, - 'verify_peer_name' => false - ) -)); - -$browser = new React\Http\Browser($connector); -``` - -This class takes an optional `LoopInterface|null $loop` parameter that can be used to -pass the event loop instance to use for this object. You can use a `null` value -here in order to use the [default loop](https://github.com/reactphp/event-loop#loop). -This value SHOULD NOT be given unless you're sure you want to explicitly use a -given event loop instance. - -> Note that the browser class is final and shouldn't be extended, it is likely to be marked final in a future release. - -#### get() - -The `get(string $url, array $headers = array()): PromiseInterface` method can be used to -send an HTTP GET request. - -```php -$browser->get($url)->then(function (Psr\Http\Message\ResponseInterface $response) { - var_dump((string)$response->getBody()); -}, function (Exception $e) { - echo 'Error: ' . $e->getMessage() . PHP_EOL; -}); -``` - -See also [GET request client example](examples/01-client-get-request.php). - -#### post() - -The `post(string $url, array $headers = array(), string|ReadableStreamInterface $body = ''): PromiseInterface` method can be used to -send an HTTP POST request. - -```php -$browser->post( - $url, - [ - 'Content-Type' => 'application/json' - ], - json_encode($data) -)->then(function (Psr\Http\Message\ResponseInterface $response) { - var_dump(json_decode((string)$response->getBody())); -}, function (Exception $e) { - echo 'Error: ' . $e->getMessage() . PHP_EOL; -}); -``` - -See also [POST JSON client example](examples/04-client-post-json.php). - -This method is also commonly used to submit HTML form data: - -```php -$data = [ - 'user' => 'Alice', - 'password' => 'secret' -]; - -$browser->post( - $url, - [ - 'Content-Type' => 'application/x-www-form-urlencoded' - ], - http_build_query($data) -); -``` - -This method will automatically add a matching `Content-Length` request -header if the outgoing request body is a `string`. If you're using a -streaming request body (`ReadableStreamInterface`), it will default to -using `Transfer-Encoding: chunked` or you have to explicitly pass in a -matching `Content-Length` request header like so: - -```php -$body = new React\Stream\ThroughStream(); -Loop::addTimer(1.0, function () use ($body) { - $body->end("hello world"); -}); - -$browser->post($url, array('Content-Length' => '11'), $body); -``` - -#### head() - -The `head(string $url, array $headers = array()): PromiseInterface` method can be used to -send an HTTP HEAD request. - -```php -$browser->head($url)->then(function (Psr\Http\Message\ResponseInterface $response) { - var_dump($response->getHeaders()); -}, function (Exception $e) { - echo 'Error: ' . $e->getMessage() . PHP_EOL; -}); -``` - -#### patch() - -The `patch(string $url, array $headers = array(), string|ReadableStreamInterface $body = ''): PromiseInterface` method can be used to -send an HTTP PATCH request. - -```php -$browser->patch( - $url, - [ - 'Content-Type' => 'application/json' - ], - json_encode($data) -)->then(function (Psr\Http\Message\ResponseInterface $response) { - var_dump(json_decode((string)$response->getBody())); -}, function (Exception $e) { - echo 'Error: ' . $e->getMessage() . PHP_EOL; -}); -``` - -This method will automatically add a matching `Content-Length` request -header if the outgoing request body is a `string`. If you're using a -streaming request body (`ReadableStreamInterface`), it will default to -using `Transfer-Encoding: chunked` or you have to explicitly pass in a -matching `Content-Length` request header like so: - -```php -$body = new React\Stream\ThroughStream(); -Loop::addTimer(1.0, function () use ($body) { - $body->end("hello world"); -}); - -$browser->patch($url, array('Content-Length' => '11'), $body); -``` - -#### put() - -The `put(string $url, array $headers = array(), string|ReadableStreamInterface $body = ''): PromiseInterface` method can be used to -send an HTTP PUT request. - -```php -$browser->put( - $url, - [ - 'Content-Type' => 'text/xml' - ], - $xml->asXML() -)->then(function (Psr\Http\Message\ResponseInterface $response) { - var_dump((string)$response->getBody()); -}, function (Exception $e) { - echo 'Error: ' . $e->getMessage() . PHP_EOL; -}); -``` - -See also [PUT XML client example](examples/05-client-put-xml.php). - -This method will automatically add a matching `Content-Length` request -header if the outgoing request body is a `string`. If you're using a -streaming request body (`ReadableStreamInterface`), it will default to -using `Transfer-Encoding: chunked` or you have to explicitly pass in a -matching `Content-Length` request header like so: - -```php -$body = new React\Stream\ThroughStream(); -Loop::addTimer(1.0, function () use ($body) { - $body->end("hello world"); -}); - -$browser->put($url, array('Content-Length' => '11'), $body); -``` - -#### delete() - -The `delete(string $url, array $headers = array(), string|ReadableStreamInterface $body = ''): PromiseInterface` method can be used to -send an HTTP DELETE request. - -```php -$browser->delete($url)->then(function (Psr\Http\Message\ResponseInterface $response) { - var_dump((string)$response->getBody()); -}, function (Exception $e) { - echo 'Error: ' . $e->getMessage() . PHP_EOL; -}); -``` - -#### request() - -The `request(string $method, string $url, array $headers = array(), string|ReadableStreamInterface $body = ''): PromiseInterface` method can be used to -send an arbitrary HTTP request. - -The preferred way to send an HTTP request is by using the above -[request methods](#request-methods), for example the [`get()`](#get) -method to send an HTTP `GET` request. - -As an alternative, if you want to use a custom HTTP request method, you -can use this method: - -```php -$browser->request('OPTIONS', $url)->then(function (Psr\Http\Message\ResponseInterface $response) { - var_dump((string)$response->getBody()); -}, function (Exception $e) { - echo 'Error: ' . $e->getMessage() . PHP_EOL; -}); -``` - -This method will automatically add a matching `Content-Length` request -header if the size of the outgoing request body is known and non-empty. -For an empty request body, if will only include a `Content-Length: 0` -request header if the request method usually expects a request body (only -applies to `POST`, `PUT` and `PATCH`). - -If you're using a streaming request body (`ReadableStreamInterface`), it -will default to using `Transfer-Encoding: chunked` or you have to -explicitly pass in a matching `Content-Length` request header like so: - -```php -$body = new React\Stream\ThroughStream(); -Loop::addTimer(1.0, function () use ($body) { - $body->end("hello world"); -}); - -$browser->request('POST', $url, array('Content-Length' => '11'), $body); -``` - -#### requestStreaming() - -The `requestStreaming(string $method, string $url, array $headers = array(), string|ReadableStreamInterface $body = ''): PromiseInterface` method can be used to -send an arbitrary HTTP request and receive a streaming response without buffering the response body. - -The preferred way to send an HTTP request is by using the above -[request methods](#request-methods), for example the [`get()`](#get) -method to send an HTTP `GET` request. Each of these methods will buffer -the whole response body in memory by default. This is easy to get started -and works reasonably well for smaller responses. - -In some situations, it's a better idea to use a streaming approach, where -only small chunks have to be kept in memory. You can use this method to -send an arbitrary HTTP request and receive a streaming response. It uses -the same HTTP message API, but does not buffer the response body in -memory. It only processes the response body in small chunks as data is -received and forwards this data through [ReactPHP's Stream API](https://github.com/reactphp/stream). -This works for (any number of) responses of arbitrary sizes. - -```php -$browser->requestStreaming('GET', $url)->then(function (Psr\Http\Message\ResponseInterface $response) { - $body = $response->getBody(); - assert($body instanceof Psr\Http\Message\StreamInterface); - assert($body instanceof React\Stream\ReadableStreamInterface); - - $body->on('data', function ($chunk) { - echo $chunk; - }); - - $body->on('error', function (Exception $e) { - echo 'Error: ' . $e->getMessage() . PHP_EOL; - }); - - $body->on('close', function () { - echo '[DONE]' . PHP_EOL; - }); -}, function (Exception $e) { - echo 'Error: ' . $e->getMessage() . PHP_EOL; -}); -``` - -See also [ReactPHP's `ReadableStreamInterface`](https://github.com/reactphp/stream#readablestreaminterface) -and the [streaming response](#streaming-response) for more details, -examples and possible use-cases. - -This method will automatically add a matching `Content-Length` request -header if the size of the outgoing request body is known and non-empty. -For an empty request body, if will only include a `Content-Length: 0` -request header if the request method usually expects a request body (only -applies to `POST`, `PUT` and `PATCH`). - -If you're using a streaming request body (`ReadableStreamInterface`), it -will default to using `Transfer-Encoding: chunked` or you have to -explicitly pass in a matching `Content-Length` request header like so: - -```php -$body = new React\Stream\ThroughStream(); -Loop::addTimer(1.0, function () use ($body) { - $body->end("hello world"); -}); - -$browser->requestStreaming('POST', $url, array('Content-Length' => '11'), $body); -``` - -#### withTimeout() - -The `withTimeout(bool|number $timeout): Browser` method can be used to -change the maximum timeout used for waiting for pending requests. - -You can pass in the number of seconds to use as a new timeout value: - -```php -$browser = $browser->withTimeout(10.0); -``` - -You can pass in a bool `false` to disable any timeouts. In this case, -requests can stay pending forever: - -```php -$browser = $browser->withTimeout(false); -``` - -You can pass in a bool `true` to re-enable default timeout handling. This -will respects PHP's `default_socket_timeout` setting (default 60s): - -```php -$browser = $browser->withTimeout(true); -``` - -See also [timeouts](#timeouts) for more details about timeout handling. - -Notice that the [`Browser`](#browser) is an immutable object, i.e. this -method actually returns a *new* [`Browser`](#browser) instance with the -given timeout value applied. - -#### withFollowRedirects() - -The `withFollowRedirects(bool|int $followRedirects): Browser` method can be used to -change how HTTP redirects will be followed. - -You can pass in the maximum number of redirects to follow: - -```php -$browser = $browser->withFollowRedirects(5); -``` - -The request will automatically be rejected when the number of redirects -is exceeded. You can pass in a `0` to reject the request for any -redirects encountered: - -```php -$browser = $browser->withFollowRedirects(0); - -$browser->get($url)->then(function (Psr\Http\Message\ResponseInterface $response) { - // only non-redirected responses will now end up here - var_dump($response->getHeaders()); -}, function (Exception $e) { - echo 'Error: ' . $e->getMessage() . PHP_EOL; -}); -``` - -You can pass in a bool `false` to disable following any redirects. In -this case, requests will resolve with the redirection response instead -of following the `Location` response header: - -```php -$browser = $browser->withFollowRedirects(false); - -$browser->get($url)->then(function (Psr\Http\Message\ResponseInterface $response) { - // any redirects will now end up here - var_dump($response->getHeaderLine('Location')); -}, function (Exception $e) { - echo 'Error: ' . $e->getMessage() . PHP_EOL; -}); -``` - -You can pass in a bool `true` to re-enable default redirect handling. -This defaults to following a maximum of 10 redirects: - -```php -$browser = $browser->withFollowRedirects(true); -``` - -See also [redirects](#redirects) for more details about redirect handling. - -Notice that the [`Browser`](#browser) is an immutable object, i.e. this -method actually returns a *new* [`Browser`](#browser) instance with the -given redirect setting applied. - -#### withRejectErrorResponse() - -The `withRejectErrorResponse(bool $obeySuccessCode): Browser` method can be used to -change whether non-successful HTTP response status codes (4xx and 5xx) will be rejected. - -You can pass in a bool `false` to disable rejecting incoming responses -that use a 4xx or 5xx response status code. In this case, requests will -resolve with the response message indicating an error condition: - -```php -$browser = $browser->withRejectErrorResponse(false); - -$browser->get($url)->then(function (Psr\Http\Message\ResponseInterface $response) { - // any HTTP response will now end up here - var_dump($response->getStatusCode(), $response->getReasonPhrase()); -}, function (Exception $e) { - echo 'Error: ' . $e->getMessage() . PHP_EOL; -}); -``` - -You can pass in a bool `true` to re-enable default status code handling. -This defaults to rejecting any response status codes in the 4xx or 5xx -range with a [`ResponseException`](#responseexception): - -```php -$browser = $browser->withRejectErrorResponse(true); - -$browser->get($url)->then(function (Psr\Http\Message\ResponseInterface $response) { - // any successful HTTP response will now end up here - var_dump($response->getStatusCode(), $response->getReasonPhrase()); -}, function (Exception $e) { - if ($e instanceof React\Http\Message\ResponseException) { - // any HTTP response error message will now end up here - $response = $e->getResponse(); - var_dump($response->getStatusCode(), $response->getReasonPhrase()); - } else { - echo 'Error: ' . $e->getMessage() . PHP_EOL; - } -}); -``` - -Notice that the [`Browser`](#browser) is an immutable object, i.e. this -method actually returns a *new* [`Browser`](#browser) instance with the -given setting applied. - -#### withBase() - -The `withBase(string|null $baseUrl): Browser` method can be used to -change the base URL used to resolve relative URLs to. - -If you configure a base URL, any requests to relative URLs will be -processed by first resolving this relative to the given absolute base -URL. This supports resolving relative path references (like `../` etc.). -This is particularly useful for (RESTful) API calls where all endpoints -(URLs) are located under a common base URL. - -```php -$browser = $browser->withBase('http://api.example.com/v3/'); - -// will request http://api.example.com/v3/users -$browser->get('users')->then(…); -``` - -You can pass in a `null` base URL to return a new instance that does not -use a base URL: - -```php -$browser = $browser->withBase(null); -``` - -Accordingly, any requests using relative URLs to a browser that does not -use a base URL can not be completed and will be rejected without sending -a request. - -This method will throw an `InvalidArgumentException` if the given -`$baseUrl` argument is not a valid URL. - -Notice that the [`Browser`](#browser) is an immutable object, i.e. the `withBase()` method -actually returns a *new* [`Browser`](#browser) instance with the given base URL applied. - -#### withProtocolVersion() - -The `withProtocolVersion(string $protocolVersion): Browser` method can be used to -change the HTTP protocol version that will be used for all subsequent requests. - -All the above [request methods](#request-methods) default to sending -requests as HTTP/1.1. This is the preferred HTTP protocol version which -also provides decent backwards-compatibility with legacy HTTP/1.0 -servers. As such, there should rarely be a need to explicitly change this -protocol version. - -If you want to explicitly use the legacy HTTP/1.0 protocol version, you -can use this method: - -```php -$browser = $browser->withProtocolVersion('1.0'); - -$browser->get($url)->then(…); -``` - -Notice that the [`Browser`](#browser) is an immutable object, i.e. this -method actually returns a *new* [`Browser`](#browser) instance with the -new protocol version applied. - -#### withResponseBuffer() - -The `withResponseBuffer(int $maximumSize): Browser` method can be used to -change the maximum size for buffering a response body. - -The preferred way to send an HTTP request is by using the above -[request methods](#request-methods), for example the [`get()`](#get) -method to send an HTTP `GET` request. Each of these methods will buffer -the whole response body in memory by default. This is easy to get started -and works reasonably well for smaller responses. - -By default, the response body buffer will be limited to 16 MiB. If the -response body exceeds this maximum size, the request will be rejected. - -You can pass in the maximum number of bytes to buffer: - -```php -$browser = $browser->withResponseBuffer(1024 * 1024); - -$browser->get($url)->then(function (Psr\Http\Message\ResponseInterface $response) { - // response body will not exceed 1 MiB - var_dump($response->getHeaders(), (string) $response->getBody()); -}, function (Exception $e) { - echo 'Error: ' . $e->getMessage() . PHP_EOL; -}); -``` - -Note that the response body buffer has to be kept in memory for each -pending request until its transfer is completed and it will only be freed -after a pending request is fulfilled. As such, increasing this maximum -buffer size to allow larger response bodies is usually not recommended. -Instead, you can use the [`requestStreaming()` method](#requeststreaming) -to receive responses with arbitrary sizes without buffering. Accordingly, -this maximum buffer size setting has no effect on streaming responses. - -Notice that the [`Browser`](#browser) is an immutable object, i.e. this -method actually returns a *new* [`Browser`](#browser) instance with the -given setting applied. - -#### withHeader() - -The `withHeader(string $header, string $value): Browser` method can be used to -add a request header for all following requests. - -```php -$browser = $browser->withHeader('User-Agent', 'ACME'); - -$browser->get($url)->then(…); -``` - -Note that the new header will overwrite any headers previously set with -the same name (case-insensitive). Following requests will use these headers -by default unless they are explicitly set for any requests. - -#### withoutHeader() - -The `withoutHeader(string $header): Browser` method can be used to -remove any default request headers previously set via -the [`withHeader()` method](#withheader). - -```php -$browser = $browser->withoutHeader('User-Agent'); - -$browser->get($url)->then(…); -``` - -Note that this method only affects the headers which were set with the -method `withHeader(string $header, string $value): Browser` - -### React\Http\Message - -#### Response - -The `React\Http\Message\Response` class can be used to -represent an outgoing server response message. - -```php -$response = new React\Http\Message\Response( - React\Http\Message\Response::STATUS_OK, - array( - 'Content-Type' => 'text/html' - ), - "Hello world!\n" -); -``` - -This class implements the -[PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface) -which in turn extends the -[PSR-7 `MessageInterface`](https://www.php-fig.org/psr/psr-7/#31-psrhttpmessagemessageinterface). - -On top of this, this class implements the -[PSR-7 Message Util `StatusCodeInterface`](https://github.com/php-fig/http-message-util/blob/master/src/StatusCodeInterface.php) -which means that most common HTTP status codes are available as class -constants with the `STATUS_*` prefix. For instance, the `200 OK` and -`404 Not Found` status codes can used as `Response::STATUS_OK` and -`Response::STATUS_NOT_FOUND` respectively. - -> Internally, this implementation builds on top of a base class which is - considered an implementation detail that may change in the future. - -##### html() - -The static `html(string $html): Response` method can be used to -create an HTML response. - -```php -$html = << - -Hello wörld! - - -HTML; - -$response = React\Http\Message\Response::html($html); -``` - -This is a convenient shortcut method that returns the equivalent of this: - -``` -$response = new React\Http\Message\Response( - React\Http\Message\Response::STATUS_OK, - [ - 'Content-Type' => 'text/html; charset=utf-8' - ], - $html -); -``` - -This method always returns a response with a `200 OK` status code and -the appropriate `Content-Type` response header for the given HTTP source -string encoded in UTF-8 (Unicode). It's generally recommended to end the -given plaintext string with a trailing newline. - -If you want to use a different status code or custom HTTP response -headers, you can manipulate the returned response object using the -provided PSR-7 methods or directly instantiate a custom HTTP response -object using the `Response` constructor: - -```php -$response = React\Http\Message\Response::html( - "

Error

\n

Invalid user name given.

\n" -)->withStatus(React\Http\Message\Response::STATUS_BAD_REQUEST); -``` - -##### json() - -The static `json(mixed $data): Response` method can be used to -create a JSON response. - -```php -$response = React\Http\Message\Response::json(['name' => 'Alice']); -``` - -This is a convenient shortcut method that returns the equivalent of this: - -``` -$response = new React\Http\Message\Response( - React\Http\Message\Response::STATUS_OK, - [ - 'Content-Type' => 'application/json' - ], - json_encode( - ['name' => 'Alice'], - JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRESERVE_ZERO_FRACTION - ) . "\n" -); -``` - -This method always returns a response with a `200 OK` status code and -the appropriate `Content-Type` response header for the given structured -data encoded as a JSON text. - -The given structured data will be encoded as a JSON text. Any `string` -values in the data must be encoded in UTF-8 (Unicode). If the encoding -fails, this method will throw an `InvalidArgumentException`. - -By default, the given structured data will be encoded with the flags as -shown above. This includes pretty printing (PHP 5.4+) and preserving -zero fractions for `float` values (PHP 5.6.6+) to ease debugging. It is -assumed any additional data overhead is usually compensated by using HTTP -response compression. - -If you want to use a different status code or custom HTTP response -headers, you can manipulate the returned response object using the -provided PSR-7 methods or directly instantiate a custom HTTP response -object using the `Response` constructor: - -```php -$response = React\Http\Message\Response::json( - ['error' => 'Invalid user name given'] -)->withStatus(React\Http\Message\Response::STATUS_BAD_REQUEST); -``` - -##### plaintext() - -The static `plaintext(string $text): Response` method can be used to -create a plaintext response. - -```php -$response = React\Http\Message\Response::plaintext("Hello wörld!\n"); -``` - -This is a convenient shortcut method that returns the equivalent of this: - -``` -$response = new React\Http\Message\Response( - React\Http\Message\Response::STATUS_OK, - [ - 'Content-Type' => 'text/plain; charset=utf-8' - ], - "Hello wörld!\n" -); -``` - -This method always returns a response with a `200 OK` status code and -the appropriate `Content-Type` response header for the given plaintext -string encoded in UTF-8 (Unicode). It's generally recommended to end the -given plaintext string with a trailing newline. - -If you want to use a different status code or custom HTTP response -headers, you can manipulate the returned response object using the -provided PSR-7 methods or directly instantiate a custom HTTP response -object using the `Response` constructor: - -```php -$response = React\Http\Message\Response::plaintext( - "Error: Invalid user name given.\n" -)->withStatus(React\Http\Message\Response::STATUS_BAD_REQUEST); -``` - -##### xml() - -The static `xml(string $xml): Response` method can be used to -create an XML response. - -```php -$xml = << - - Hello wörld! - - -XML; - -$response = React\Http\Message\Response::xml($xml); -``` - -This is a convenient shortcut method that returns the equivalent of this: - -``` -$response = new React\Http\Message\Response( - React\Http\Message\Response::STATUS_OK, - [ - 'Content-Type' => 'application/xml' - ], - $xml -); -``` - -This method always returns a response with a `200 OK` status code and -the appropriate `Content-Type` response header for the given XML source -string. It's generally recommended to use UTF-8 (Unicode) and specify -this as part of the leading XML declaration and to end the given XML -source string with a trailing newline. - -If you want to use a different status code or custom HTTP response -headers, you can manipulate the returned response object using the -provided PSR-7 methods or directly instantiate a custom HTTP response -object using the `Response` constructor: - -```php -$response = React\Http\Message\Response::xml( - "Invalid user name given.\n" -)->withStatus(React\Http\Message\Response::STATUS_BAD_REQUEST); -``` - -#### Request - -The `React\Http\Message\Request` class can be used to -respresent an outgoing HTTP request message. - -This class implements the -[PSR-7 `RequestInterface`](https://www.php-fig.org/psr/psr-7/#32-psrhttpmessagerequestinterface) -which extends the -[PSR-7 `MessageInterface`](https://www.php-fig.org/psr/psr-7/#31-psrhttpmessagemessageinterface). - -This is mostly used internally to represent each outgoing HTTP request -message for the HTTP client implementation. Likewise, you can also use this -class with other HTTP client implementations and for tests. - -> Internally, this implementation builds on top of a base class which is - considered an implementation detail that may change in the future. - -#### ServerRequest - -The `React\Http\Message\ServerRequest` class can be used to -respresent an incoming server request message. - -This class implements the -[PSR-7 `ServerRequestInterface`](https://www.php-fig.org/psr/psr-7/#321-psrhttpmessageserverrequestinterface) -which extends the -[PSR-7 `RequestInterface`](https://www.php-fig.org/psr/psr-7/#32-psrhttpmessagerequestinterface) -which in turn extends the -[PSR-7 `MessageInterface`](https://www.php-fig.org/psr/psr-7/#31-psrhttpmessagemessageinterface). - -This is mostly used internally to represent each incoming request message. -Likewise, you can also use this class in test cases to test how your web -application reacts to certain HTTP requests. - -> Internally, this implementation builds on top of a base class which is - considered an implementation detail that may change in the future. - -#### Uri - -The `React\Http\Message\Uri` class can be used to -respresent a URI (or URL). - -This class implements the -[PSR-7 `UriInterface`](https://www.php-fig.org/psr/psr-7/#35-psrhttpmessageuriinterface). - -This is mostly used internally to represent the URI of each HTTP request -message for our HTTP client and server implementations. Likewise, you may -also use this class with other HTTP implementations and for tests. - -#### ResponseException - -The `React\Http\Message\ResponseException` is an `Exception` sub-class that will be used to reject -a request promise if the remote server returns a non-success status code -(anything but 2xx or 3xx). -You can control this behavior via the [`withRejectErrorResponse()` method](#withrejecterrorresponse). - -The `getCode(): int` method can be used to -return the HTTP response status code. - -The `getResponse(): ResponseInterface` method can be used to -access its underlying response object. - -### React\Http\Middleware - -#### StreamingRequestMiddleware - -The `React\Http\Middleware\StreamingRequestMiddleware` can be used to -process incoming requests with a streaming request body (without buffering). - -This allows you to process requests of any size without buffering the request -body in memory. Instead, it will represent the request body as a -[`ReadableStreamInterface`](https://github.com/reactphp/stream#readablestreaminterface) -that emit chunks of incoming data as it is received: - -```php -$http = new React\Http\HttpServer( - new React\Http\Middleware\StreamingRequestMiddleware(), - function (Psr\Http\Message\ServerRequestInterface $request) { - $body = $request->getBody(); - assert($body instanceof Psr\Http\Message\StreamInterface); - assert($body instanceof React\Stream\ReadableStreamInterface); - - return new React\Promise\Promise(function ($resolve) use ($body) { - $bytes = 0; - $body->on('data', function ($chunk) use (&$bytes) { - $bytes += \count($chunk); - }); - $body->on('close', function () use (&$bytes, $resolve) { - $resolve(new React\Http\Message\Response( - React\Http\Message\Response::STATUS_OK, - [], - "Received $bytes bytes\n" - )); - }); - }); - } -); -``` - -See also [streaming incoming request](#streaming-incoming-request) -for more details. - -Additionally, this middleware can be used in combination with the -[`LimitConcurrentRequestsMiddleware`](#limitconcurrentrequestsmiddleware) and -[`RequestBodyBufferMiddleware`](#requestbodybuffermiddleware) (see below) -to explicitly configure the total number of requests that can be handled at -once: - -```php -$http = new React\Http\HttpServer( - new React\Http\Middleware\StreamingRequestMiddleware(), - new React\Http\Middleware\LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers - new React\Http\Middleware\RequestBodyBufferMiddleware(2 * 1024 * 1024), // 2 MiB per request - new React\Http\Middleware\RequestBodyParserMiddleware(), - $handler -); -``` - -> Internally, this class is used as a "marker" to not trigger the default - request buffering behavior in the `HttpServer`. It does not implement any logic - on its own. - -#### LimitConcurrentRequestsMiddleware - -The `React\Http\Middleware\LimitConcurrentRequestsMiddleware` can be used to -limit how many next handlers can be executed concurrently. - -If this middleware is invoked, it will check if the number of pending -handlers is below the allowed limit and then simply invoke the next handler -and it will return whatever the next handler returns (or throws). - -If the number of pending handlers exceeds the allowed limit, the request will -be queued (and its streaming body will be paused) and it will return a pending -promise. -Once a pending handler returns (or throws), it will pick the oldest request -from this queue and invokes the next handler (and its streaming body will be -resumed). - -The following example shows how this middleware can be used to ensure no more -than 10 handlers will be invoked at once: - -```php -$http = new React\Http\HttpServer( - new React\Http\Middleware\LimitConcurrentRequestsMiddleware(10), - $handler -); -``` - -Similarly, this middleware is often used in combination with the -[`RequestBodyBufferMiddleware`](#requestbodybuffermiddleware) (see below) -to limit the total number of requests that can be buffered at once: - -```php -$http = new React\Http\HttpServer( - new React\Http\Middleware\StreamingRequestMiddleware(), - new React\Http\Middleware\LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers - new React\Http\Middleware\RequestBodyBufferMiddleware(2 * 1024 * 1024), // 2 MiB per request - new React\Http\Middleware\RequestBodyParserMiddleware(), - $handler -); -``` - -More sophisticated examples include limiting the total number of requests -that can be buffered at once and then ensure the actual request handler only -processes one request after another without any concurrency: - -```php -$http = new React\Http\HttpServer( - new React\Http\Middleware\StreamingRequestMiddleware(), - new React\Http\Middleware\LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers - new React\Http\Middleware\RequestBodyBufferMiddleware(2 * 1024 * 1024), // 2 MiB per request - new React\Http\Middleware\RequestBodyParserMiddleware(), - new React\Http\Middleware\LimitConcurrentRequestsMiddleware(1), // only execute 1 handler (no concurrency) - $handler -); -``` - -#### RequestBodyBufferMiddleware - -One of the built-in middleware is the `React\Http\Middleware\RequestBodyBufferMiddleware` which -can be used to buffer the whole incoming request body in memory. -This can be useful if full PSR-7 compatibility is needed for the request handler -and the default streaming request body handling is not needed. -The constructor accepts one optional argument, the maximum request body size. -When one isn't provided it will use `post_max_size` (default 8 MiB) from PHP's -configuration. -(Note that the value from your matching SAPI will be used, which is the CLI -configuration in most cases.) - -Any incoming request that has a request body that exceeds this limit will be -accepted, but its request body will be discarded (empty request body). -This is done in order to avoid having to keep an incoming request with an -excessive size (for example, think of a 2 GB file upload) in memory. -This allows the next middleware handler to still handle this request, but it -will see an empty request body. -This is similar to PHP's default behavior, where the body will not be parsed -if this limit is exceeded. However, unlike PHP's default behavior, the raw -request body is not available via `php://input`. - -The `RequestBodyBufferMiddleware` will buffer requests with bodies of known size -(i.e. with `Content-Length` header specified) as well as requests with bodies of -unknown size (i.e. with `Transfer-Encoding: chunked` header). - -All requests will be buffered in memory until the request body end has -been reached and then call the next middleware handler with the complete, -buffered request. -Similarly, this will immediately invoke the next middleware handler for requests -that have an empty request body (such as a simple `GET` request) and requests -that are already buffered (such as due to another middleware). - -Note that the given buffer size limit is applied to each request individually. -This means that if you allow a 2 MiB limit and then receive 1000 concurrent -requests, up to 2000 MiB may be allocated for these buffers alone. -As such, it's highly recommended to use this along with the -[`LimitConcurrentRequestsMiddleware`](#limitconcurrentrequestsmiddleware) (see above) to limit -the total number of concurrent requests. - -Usage: - -```php -$http = new React\Http\HttpServer( - new React\Http\Middleware\StreamingRequestMiddleware(), - new React\Http\Middleware\LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers - new React\Http\Middleware\RequestBodyBufferMiddleware(16 * 1024 * 1024), // 16 MiB - function (Psr\Http\Message\ServerRequestInterface $request) { - // The body from $request->getBody() is now fully available without the need to stream it - return new React\Http\Message\Response(React\Http\Message\Response::STATUS_OK); - }, -); -``` - -#### RequestBodyParserMiddleware - -The `React\Http\Middleware\RequestBodyParserMiddleware` takes a fully buffered request body -(generally from [`RequestBodyBufferMiddleware`](#requestbodybuffermiddleware)), -and parses the form values and file uploads from the incoming HTTP request body. - -This middleware handler takes care of applying values from HTTP -requests that use `Content-Type: application/x-www-form-urlencoded` or -`Content-Type: multipart/form-data` to resemble PHP's default superglobals -`$_POST` and `$_FILES`. -Instead of relying on these superglobals, you can use the -`$request->getParsedBody()` and `$request->getUploadedFiles()` methods -as defined by PSR-7. - -Accordingly, each file upload will be represented as instance implementing the -[PSR-7 `UploadedFileInterface`](https://www.php-fig.org/psr/psr-7/#36-psrhttpmessageuploadedfileinterface). -Due to its blocking nature, the `moveTo()` method is not available and throws -a `RuntimeException` instead. -You can use `$contents = (string)$file->getStream();` to access the file -contents and persist this to your favorite data store. - -```php -$handler = function (Psr\Http\Message\ServerRequestInterface $request) { - // If any, parsed form fields are now available from $request->getParsedBody() - $body = $request->getParsedBody(); - $name = isset($body['name']) ? $body['name'] : 'unnamed'; - - $files = $request->getUploadedFiles(); - $avatar = isset($files['avatar']) ? $files['avatar'] : null; - if ($avatar instanceof Psr\Http\Message\UploadedFileInterface) { - if ($avatar->getError() === UPLOAD_ERR_OK) { - $uploaded = $avatar->getSize() . ' bytes'; - } elseif ($avatar->getError() === UPLOAD_ERR_INI_SIZE) { - $uploaded = 'file too large'; - } else { - $uploaded = 'with error'; - } - } else { - $uploaded = 'nothing'; - } - - return new React\Http\Message\Response( - React\Http\Message\Response::STATUS_OK, - array( - 'Content-Type' => 'text/plain' - ), - $name . ' uploaded ' . $uploaded - ); -}; - -$http = new React\Http\HttpServer( - new React\Http\Middleware\StreamingRequestMiddleware(), - new React\Http\Middleware\LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers - new React\Http\Middleware\RequestBodyBufferMiddleware(16 * 1024 * 1024), // 16 MiB - new React\Http\Middleware\RequestBodyParserMiddleware(), - $handler -); -``` - -See also [form upload server example](examples/62-server-form-upload.php) for more details. - -By default, this middleware respects the -[`upload_max_filesize`](https://www.php.net/manual/en/ini.core.php#ini.upload-max-filesize) -(default `2M`) ini setting. -Files that exceed this limit will be rejected with an `UPLOAD_ERR_INI_SIZE` error. -You can control the maximum filesize for each individual file upload by -explicitly passing the maximum filesize in bytes as the first parameter to the -constructor like this: - -```php -new React\Http\Middleware\RequestBodyParserMiddleware(8 * 1024 * 1024); // 8 MiB limit per file -``` - -By default, this middleware respects the -[`file_uploads`](https://www.php.net/manual/en/ini.core.php#ini.file-uploads) -(default `1`) and -[`max_file_uploads`](https://www.php.net/manual/en/ini.core.php#ini.max-file-uploads) -(default `20`) ini settings. -These settings control if any and how many files can be uploaded in a single request. -If you upload more files in a single request, additional files will be ignored -and the `getUploadedFiles()` method returns a truncated array. -Note that upload fields left blank on submission do not count towards this limit. -You can control the maximum number of file uploads per request by explicitly -passing the second parameter to the constructor like this: - -```php -new React\Http\Middleware\RequestBodyParserMiddleware(10 * 1024, 100); // 100 files with 10 KiB each -``` - -> Note that this middleware handler simply parses everything that is already - buffered in the request body. - It is imperative that the request body is buffered by a prior middleware - handler as given in the example above. - This previous middleware handler is also responsible for rejecting incoming - requests that exceed allowed message sizes (such as big file uploads). - The [`RequestBodyBufferMiddleware`](#requestbodybuffermiddleware) used above - simply discards excessive request bodies, resulting in an empty body. - If you use this middleware without buffering first, it will try to parse an - empty (streaming) body and may thus assume an empty data structure. - See also [`RequestBodyBufferMiddleware`](#requestbodybuffermiddleware) for - more details. - -> PHP's `MAX_FILE_SIZE` hidden field is respected by this middleware. - Files that exceed this limit will be rejected with an `UPLOAD_ERR_FORM_SIZE` error. - -> This middleware respects the - [`max_input_vars`](https://www.php.net/manual/en/info.configuration.php#ini.max-input-vars) - (default `1000`) and - [`max_input_nesting_level`](https://www.php.net/manual/en/info.configuration.php#ini.max-input-nesting-level) - (default `64`) ini settings. - -> Note that this middleware ignores the - [`enable_post_data_reading`](https://www.php.net/manual/en/ini.core.php#ini.enable-post-data-reading) - (default `1`) ini setting because it makes little sense to respect here and - is left up to higher-level implementations. - If you want to respect this setting, you have to check its value and - effectively avoid using this middleware entirely. - -## Install - -The recommended way to install this library is [through Composer](https://getcomposer.org/). -[New to Composer?](https://getcomposer.org/doc/00-intro.md) - -This project follows [SemVer](https://semver.org/). -This will install the latest supported version: - -```bash -composer require react/http:^1.10 -``` - -See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades. - -This project aims to run on any platform and thus does not require any PHP -extensions and supports running on legacy PHP 5.3 through current PHP 8+ and -HHVM. -It's *highly recommended to use the latest supported PHP version* for this project. - -## Tests - -To run the test suite, you first need to clone this repo and then install all -dependencies [through Composer](https://getcomposer.org/): - -```bash -composer install -``` - -To run the test suite, go to the project root and run: - -```bash -vendor/bin/phpunit -``` - -The test suite also contains a number of functional integration tests that rely -on a stable internet connection. -If you do not want to run these, they can simply be skipped like this: - -```bash -vendor/bin/phpunit --exclude-group internet -``` - -## License - -MIT, see [LICENSE file](LICENSE). diff --git a/digital_doctor/vendor/react/http/composer.json b/digital_doctor/vendor/react/http/composer.json deleted file mode 100644 index 23783c0..0000000 --- a/digital_doctor/vendor/react/http/composer.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "name": "react/http", - "description": "Event-driven, streaming HTTP client and server implementation for ReactPHP", - "keywords": ["HTTP client", "HTTP server", "HTTP", "HTTPS", "event-driven", "streaming", "client", "server", "PSR-7", "async", "ReactPHP"], - "license": "MIT", - "authors": [ - { - "name": "Christian Lück", - "homepage": "https://clue.engineering/", - "email": "christian@clue.engineering" - }, - { - "name": "Cees-Jan Kiewiet", - "homepage": "https://wyrihaximus.net/", - "email": "reactphp@ceesjankiewiet.nl" - }, - { - "name": "Jan Sorgalla", - "homepage": "https://sorgalla.com/", - "email": "jsorgalla@gmail.com" - }, - { - "name": "Chris Boden", - "homepage": "https://cboden.dev/", - "email": "cboden@gmail.com" - } - ], - "require": { - "php": ">=5.3.0", - "evenement/evenement": "^3.0 || ^2.0 || ^1.0", - "fig/http-message-util": "^1.1", - "psr/http-message": "^1.0", - "react/event-loop": "^1.2", - "react/promise": "^3 || ^2.3 || ^1.2.1", - "react/socket": "^1.12", - "react/stream": "^1.2" - }, - "require-dev": { - "clue/http-proxy-react": "^1.8", - "clue/reactphp-ssh-proxy": "^1.4", - "clue/socks-react": "^1.4", - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", - "react/async": "^4 || ^3 || ^2", - "react/promise-stream": "^1.4", - "react/promise-timer": "^1.9" - }, - "autoload": { - "psr-4": { - "React\\Http\\": "src/" - } - }, - "autoload-dev": { - "psr-4": { - "React\\Tests\\Http\\": "tests/" - } - } -} diff --git a/digital_doctor/vendor/react/http/src/Browser.php b/digital_doctor/vendor/react/http/src/Browser.php deleted file mode 100644 index 01a266c..0000000 --- a/digital_doctor/vendor/react/http/src/Browser.php +++ /dev/null @@ -1,857 +0,0 @@ - 'ReactPHP/1' - ); - - /** - * The `Browser` is responsible for sending HTTP requests to your HTTP server - * and keeps track of pending incoming HTTP responses. - * - * ```php - * $browser = new React\Http\Browser(); - * ``` - * - * This class takes two optional arguments for more advanced usage: - * - * ```php - * // constructor signature as of v1.5.0 - * $browser = new React\Http\Browser(?ConnectorInterface $connector = null, ?LoopInterface $loop = null); - * - * // legacy constructor signature before v1.5.0 - * $browser = new React\Http\Browser(?LoopInterface $loop = null, ?ConnectorInterface $connector = null); - * ``` - * - * If you need custom connector settings (DNS resolution, TLS parameters, timeouts, - * proxy servers etc.), you can explicitly pass a custom instance of the - * [`ConnectorInterface`](https://github.com/reactphp/socket#connectorinterface): - * - * ```php - * $connector = new React\Socket\Connector(array( - * 'dns' => '127.0.0.1', - * 'tcp' => array( - * 'bindto' => '192.168.10.1:0' - * ), - * 'tls' => array( - * 'verify_peer' => false, - * 'verify_peer_name' => false - * ) - * )); - * - * $browser = new React\Http\Browser($connector); - * ``` - * - * This class takes an optional `LoopInterface|null $loop` parameter that can be used to - * pass the event loop instance to use for this object. You can use a `null` value - * here in order to use the [default loop](https://github.com/reactphp/event-loop#loop). - * This value SHOULD NOT be given unless you're sure you want to explicitly use a - * given event loop instance. - * - * @param null|ConnectorInterface|LoopInterface $connector - * @param null|LoopInterface|ConnectorInterface $loop - * @throws \InvalidArgumentException for invalid arguments - */ - public function __construct($connector = null, $loop = null) - { - // swap arguments for legacy constructor signature - if (($connector instanceof LoopInterface || $connector === null) && ($loop instanceof ConnectorInterface || $loop === null)) { - $swap = $loop; - $loop = $connector; - $connector = $swap; - } - - if (($connector !== null && !$connector instanceof ConnectorInterface) || ($loop !== null && !$loop instanceof LoopInterface)) { - throw new \InvalidArgumentException('Expected "?ConnectorInterface $connector" and "?LoopInterface $loop" arguments'); - } - - $loop = $loop ?: Loop::get(); - $this->transaction = new Transaction( - Sender::createFromLoop($loop, $connector), - $loop - ); - } - - /** - * Sends an HTTP GET request - * - * ```php - * $browser->get($url)->then(function (Psr\Http\Message\ResponseInterface $response) { - * var_dump((string)$response->getBody()); - * }, function (Exception $e) { - * echo 'Error: ' . $e->getMessage() . PHP_EOL; - * }); - * ``` - * - * See also [GET request client example](../examples/01-client-get-request.php). - * - * @param string $url URL for the request. - * @param array $headers - * @return PromiseInterface - */ - public function get($url, array $headers = array()) - { - return $this->requestMayBeStreaming('GET', $url, $headers); - } - - /** - * Sends an HTTP POST request - * - * ```php - * $browser->post( - * $url, - * [ - * 'Content-Type' => 'application/json' - * ], - * json_encode($data) - * )->then(function (Psr\Http\Message\ResponseInterface $response) { - * var_dump(json_decode((string)$response->getBody())); - * }, function (Exception $e) { - * echo 'Error: ' . $e->getMessage() . PHP_EOL; - * }); - * ``` - * - * See also [POST JSON client example](../examples/04-client-post-json.php). - * - * This method is also commonly used to submit HTML form data: - * - * ```php - * $data = [ - * 'user' => 'Alice', - * 'password' => 'secret' - * ]; - * - * $browser->post( - * $url, - * [ - * 'Content-Type' => 'application/x-www-form-urlencoded' - * ], - * http_build_query($data) - * ); - * ``` - * - * This method will automatically add a matching `Content-Length` request - * header if the outgoing request body is a `string`. If you're using a - * streaming request body (`ReadableStreamInterface`), it will default to - * using `Transfer-Encoding: chunked` or you have to explicitly pass in a - * matching `Content-Length` request header like so: - * - * ```php - * $body = new React\Stream\ThroughStream(); - * Loop::addTimer(1.0, function () use ($body) { - * $body->end("hello world"); - * }); - * - * $browser->post($url, array('Content-Length' => '11'), $body); - * ``` - * - * @param string $url URL for the request. - * @param array $headers - * @param string|ReadableStreamInterface $body - * @return PromiseInterface - */ - public function post($url, array $headers = array(), $body = '') - { - return $this->requestMayBeStreaming('POST', $url, $headers, $body); - } - - /** - * Sends an HTTP HEAD request - * - * ```php - * $browser->head($url)->then(function (Psr\Http\Message\ResponseInterface $response) { - * var_dump($response->getHeaders()); - * }, function (Exception $e) { - * echo 'Error: ' . $e->getMessage() . PHP_EOL; - * }); - * ``` - * - * @param string $url URL for the request. - * @param array $headers - * @return PromiseInterface - */ - public function head($url, array $headers = array()) - { - return $this->requestMayBeStreaming('HEAD', $url, $headers); - } - - /** - * Sends an HTTP PATCH request - * - * ```php - * $browser->patch( - * $url, - * [ - * 'Content-Type' => 'application/json' - * ], - * json_encode($data) - * )->then(function (Psr\Http\Message\ResponseInterface $response) { - * var_dump(json_decode((string)$response->getBody())); - * }, function (Exception $e) { - * echo 'Error: ' . $e->getMessage() . PHP_EOL; - * }); - * ``` - * - * This method will automatically add a matching `Content-Length` request - * header if the outgoing request body is a `string`. If you're using a - * streaming request body (`ReadableStreamInterface`), it will default to - * using `Transfer-Encoding: chunked` or you have to explicitly pass in a - * matching `Content-Length` request header like so: - * - * ```php - * $body = new React\Stream\ThroughStream(); - * Loop::addTimer(1.0, function () use ($body) { - * $body->end("hello world"); - * }); - * - * $browser->patch($url, array('Content-Length' => '11'), $body); - * ``` - * - * @param string $url URL for the request. - * @param array $headers - * @param string|ReadableStreamInterface $body - * @return PromiseInterface - */ - public function patch($url, array $headers = array(), $body = '') - { - return $this->requestMayBeStreaming('PATCH', $url , $headers, $body); - } - - /** - * Sends an HTTP PUT request - * - * ```php - * $browser->put( - * $url, - * [ - * 'Content-Type' => 'text/xml' - * ], - * $xml->asXML() - * )->then(function (Psr\Http\Message\ResponseInterface $response) { - * var_dump((string)$response->getBody()); - * }, function (Exception $e) { - * echo 'Error: ' . $e->getMessage() . PHP_EOL; - * }); - * ``` - * - * See also [PUT XML client example](../examples/05-client-put-xml.php). - * - * This method will automatically add a matching `Content-Length` request - * header if the outgoing request body is a `string`. If you're using a - * streaming request body (`ReadableStreamInterface`), it will default to - * using `Transfer-Encoding: chunked` or you have to explicitly pass in a - * matching `Content-Length` request header like so: - * - * ```php - * $body = new React\Stream\ThroughStream(); - * Loop::addTimer(1.0, function () use ($body) { - * $body->end("hello world"); - * }); - * - * $browser->put($url, array('Content-Length' => '11'), $body); - * ``` - * - * @param string $url URL for the request. - * @param array $headers - * @param string|ReadableStreamInterface $body - * @return PromiseInterface - */ - public function put($url, array $headers = array(), $body = '') - { - return $this->requestMayBeStreaming('PUT', $url, $headers, $body); - } - - /** - * Sends an HTTP DELETE request - * - * ```php - * $browser->delete($url)->then(function (Psr\Http\Message\ResponseInterface $response) { - * var_dump((string)$response->getBody()); - * }, function (Exception $e) { - * echo 'Error: ' . $e->getMessage() . PHP_EOL; - * }); - * ``` - * - * @param string $url URL for the request. - * @param array $headers - * @param string|ReadableStreamInterface $body - * @return PromiseInterface - */ - public function delete($url, array $headers = array(), $body = '') - { - return $this->requestMayBeStreaming('DELETE', $url, $headers, $body); - } - - /** - * Sends an arbitrary HTTP request. - * - * The preferred way to send an HTTP request is by using the above - * [request methods](#request-methods), for example the [`get()`](#get) - * method to send an HTTP `GET` request. - * - * As an alternative, if you want to use a custom HTTP request method, you - * can use this method: - * - * ```php - * $browser->request('OPTIONS', $url)->then(function (Psr\Http\Message\ResponseInterface $response) { - * var_dump((string)$response->getBody()); - * }, function (Exception $e) { - * echo 'Error: ' . $e->getMessage() . PHP_EOL; - * }); - * ``` - * - * This method will automatically add a matching `Content-Length` request - * header if the size of the outgoing request body is known and non-empty. - * For an empty request body, if will only include a `Content-Length: 0` - * request header if the request method usually expects a request body (only - * applies to `POST`, `PUT` and `PATCH`). - * - * If you're using a streaming request body (`ReadableStreamInterface`), it - * will default to using `Transfer-Encoding: chunked` or you have to - * explicitly pass in a matching `Content-Length` request header like so: - * - * ```php - * $body = new React\Stream\ThroughStream(); - * Loop::addTimer(1.0, function () use ($body) { - * $body->end("hello world"); - * }); - * - * $browser->request('POST', $url, array('Content-Length' => '11'), $body); - * ``` - * - * @param string $method HTTP request method, e.g. GET/HEAD/POST etc. - * @param string $url URL for the request - * @param array $headers Additional request headers - * @param string|ReadableStreamInterface $body HTTP request body contents - * @return PromiseInterface - */ - public function request($method, $url, array $headers = array(), $body = '') - { - return $this->withOptions(array('streaming' => false))->requestMayBeStreaming($method, $url, $headers, $body); - } - - /** - * Sends an arbitrary HTTP request and receives a streaming response without buffering the response body. - * - * The preferred way to send an HTTP request is by using the above - * [request methods](#request-methods), for example the [`get()`](#get) - * method to send an HTTP `GET` request. Each of these methods will buffer - * the whole response body in memory by default. This is easy to get started - * and works reasonably well for smaller responses. - * - * In some situations, it's a better idea to use a streaming approach, where - * only small chunks have to be kept in memory. You can use this method to - * send an arbitrary HTTP request and receive a streaming response. It uses - * the same HTTP message API, but does not buffer the response body in - * memory. It only processes the response body in small chunks as data is - * received and forwards this data through [ReactPHP's Stream API](https://github.com/reactphp/stream). - * This works for (any number of) responses of arbitrary sizes. - * - * ```php - * $browser->requestStreaming('GET', $url)->then(function (Psr\Http\Message\ResponseInterface $response) { - * $body = $response->getBody(); - * assert($body instanceof Psr\Http\Message\StreamInterface); - * assert($body instanceof React\Stream\ReadableStreamInterface); - * - * $body->on('data', function ($chunk) { - * echo $chunk; - * }); - * - * $body->on('error', function (Exception $e) { - * echo 'Error: ' . $e->getMessage() . PHP_EOL; - * }); - * - * $body->on('close', function () { - * echo '[DONE]' . PHP_EOL; - * }); - * }, function (Exception $e) { - * echo 'Error: ' . $e->getMessage() . PHP_EOL; - * }); - * ``` - * - * See also [`ReadableStreamInterface`](https://github.com/reactphp/stream#readablestreaminterface) - * and the [streaming response](#streaming-response) for more details, - * examples and possible use-cases. - * - * This method will automatically add a matching `Content-Length` request - * header if the size of the outgoing request body is known and non-empty. - * For an empty request body, if will only include a `Content-Length: 0` - * request header if the request method usually expects a request body (only - * applies to `POST`, `PUT` and `PATCH`). - * - * If you're using a streaming request body (`ReadableStreamInterface`), it - * will default to using `Transfer-Encoding: chunked` or you have to - * explicitly pass in a matching `Content-Length` request header like so: - * - * ```php - * $body = new React\Stream\ThroughStream(); - * Loop::addTimer(1.0, function () use ($body) { - * $body->end("hello world"); - * }); - * - * $browser->requestStreaming('POST', $url, array('Content-Length' => '11'), $body); - * ``` - * - * @param string $method HTTP request method, e.g. GET/HEAD/POST etc. - * @param string $url URL for the request - * @param array $headers Additional request headers - * @param string|ReadableStreamInterface $body HTTP request body contents - * @return PromiseInterface - */ - public function requestStreaming($method, $url, $headers = array(), $body = '') - { - return $this->withOptions(array('streaming' => true))->requestMayBeStreaming($method, $url, $headers, $body); - } - - /** - * Changes the maximum timeout used for waiting for pending requests. - * - * You can pass in the number of seconds to use as a new timeout value: - * - * ```php - * $browser = $browser->withTimeout(10.0); - * ``` - * - * You can pass in a bool `false` to disable any timeouts. In this case, - * requests can stay pending forever: - * - * ```php - * $browser = $browser->withTimeout(false); - * ``` - * - * You can pass in a bool `true` to re-enable default timeout handling. This - * will respects PHP's `default_socket_timeout` setting (default 60s): - * - * ```php - * $browser = $browser->withTimeout(true); - * ``` - * - * See also [timeouts](#timeouts) for more details about timeout handling. - * - * Notice that the [`Browser`](#browser) is an immutable object, i.e. this - * method actually returns a *new* [`Browser`](#browser) instance with the - * given timeout value applied. - * - * @param bool|number $timeout - * @return self - */ - public function withTimeout($timeout) - { - if ($timeout === true) { - $timeout = null; - } elseif ($timeout === false) { - $timeout = -1; - } elseif ($timeout < 0) { - $timeout = 0; - } - - return $this->withOptions(array( - 'timeout' => $timeout, - )); - } - - /** - * Changes how HTTP redirects will be followed. - * - * You can pass in the maximum number of redirects to follow: - * - * ```php - * $browser = $browser->withFollowRedirects(5); - * ``` - * - * The request will automatically be rejected when the number of redirects - * is exceeded. You can pass in a `0` to reject the request for any - * redirects encountered: - * - * ```php - * $browser = $browser->withFollowRedirects(0); - * - * $browser->get($url)->then(function (Psr\Http\Message\ResponseInterface $response) { - * // only non-redirected responses will now end up here - * var_dump($response->getHeaders()); - * }, function (Exception $e) { - * echo 'Error: ' . $e->getMessage() . PHP_EOL; - * }); - * ``` - * - * You can pass in a bool `false` to disable following any redirects. In - * this case, requests will resolve with the redirection response instead - * of following the `Location` response header: - * - * ```php - * $browser = $browser->withFollowRedirects(false); - * - * $browser->get($url)->then(function (Psr\Http\Message\ResponseInterface $response) { - * // any redirects will now end up here - * var_dump($response->getHeaderLine('Location')); - * }, function (Exception $e) { - * echo 'Error: ' . $e->getMessage() . PHP_EOL; - * }); - * ``` - * - * You can pass in a bool `true` to re-enable default redirect handling. - * This defaults to following a maximum of 10 redirects: - * - * ```php - * $browser = $browser->withFollowRedirects(true); - * ``` - * - * See also [redirects](#redirects) for more details about redirect handling. - * - * Notice that the [`Browser`](#browser) is an immutable object, i.e. this - * method actually returns a *new* [`Browser`](#browser) instance with the - * given redirect setting applied. - * - * @param bool|int $followRedirects - * @return self - */ - public function withFollowRedirects($followRedirects) - { - return $this->withOptions(array( - 'followRedirects' => $followRedirects !== false, - 'maxRedirects' => \is_bool($followRedirects) ? null : $followRedirects - )); - } - - /** - * Changes whether non-successful HTTP response status codes (4xx and 5xx) will be rejected. - * - * You can pass in a bool `false` to disable rejecting incoming responses - * that use a 4xx or 5xx response status code. In this case, requests will - * resolve with the response message indicating an error condition: - * - * ```php - * $browser = $browser->withRejectErrorResponse(false); - * - * $browser->get($url)->then(function (Psr\Http\Message\ResponseInterface $response) { - * // any HTTP response will now end up here - * var_dump($response->getStatusCode(), $response->getReasonPhrase()); - * }, function (Exception $e) { - * echo 'Error: ' . $e->getMessage() . PHP_EOL; - * }); - * ``` - * - * You can pass in a bool `true` to re-enable default status code handling. - * This defaults to rejecting any response status codes in the 4xx or 5xx - * range: - * - * ```php - * $browser = $browser->withRejectErrorResponse(true); - * - * $browser->get($url)->then(function (Psr\Http\Message\ResponseInterface $response) { - * // any successful HTTP response will now end up here - * var_dump($response->getStatusCode(), $response->getReasonPhrase()); - * }, function (Exception $e) { - * if ($e instanceof React\Http\Message\ResponseException) { - * // any HTTP response error message will now end up here - * $response = $e->getResponse(); - * var_dump($response->getStatusCode(), $response->getReasonPhrase()); - * } else { - * echo 'Error: ' . $e->getMessage() . PHP_EOL; - * } - * }); - * ``` - * - * Notice that the [`Browser`](#browser) is an immutable object, i.e. this - * method actually returns a *new* [`Browser`](#browser) instance with the - * given setting applied. - * - * @param bool $obeySuccessCode - * @return self - */ - public function withRejectErrorResponse($obeySuccessCode) - { - return $this->withOptions(array( - 'obeySuccessCode' => $obeySuccessCode, - )); - } - - /** - * Changes the base URL used to resolve relative URLs to. - * - * If you configure a base URL, any requests to relative URLs will be - * processed by first resolving this relative to the given absolute base - * URL. This supports resolving relative path references (like `../` etc.). - * This is particularly useful for (RESTful) API calls where all endpoints - * (URLs) are located under a common base URL. - * - * ```php - * $browser = $browser->withBase('http://api.example.com/v3/'); - * - * // will request http://api.example.com/v3/users - * $browser->get('users')->then(…); - * ``` - * - * You can pass in a `null` base URL to return a new instance that does not - * use a base URL: - * - * ```php - * $browser = $browser->withBase(null); - * ``` - * - * Accordingly, any requests using relative URLs to a browser that does not - * use a base URL can not be completed and will be rejected without sending - * a request. - * - * This method will throw an `InvalidArgumentException` if the given - * `$baseUrl` argument is not a valid URL. - * - * Notice that the [`Browser`](#browser) is an immutable object, i.e. the `withBase()` method - * actually returns a *new* [`Browser`](#browser) instance with the given base URL applied. - * - * @param string|null $baseUrl absolute base URL - * @return self - * @throws InvalidArgumentException if the given $baseUrl is not a valid absolute URL - * @see self::withoutBase() - */ - public function withBase($baseUrl) - { - $browser = clone $this; - if ($baseUrl === null) { - $browser->baseUrl = null; - return $browser; - } - - $browser->baseUrl = new Uri($baseUrl); - if (!\in_array($browser->baseUrl->getScheme(), array('http', 'https')) || $browser->baseUrl->getHost() === '') { - throw new \InvalidArgumentException('Base URL must be absolute'); - } - - return $browser; - } - - /** - * Changes the HTTP protocol version that will be used for all subsequent requests. - * - * All the above [request methods](#request-methods) default to sending - * requests as HTTP/1.1. This is the preferred HTTP protocol version which - * also provides decent backwards-compatibility with legacy HTTP/1.0 - * servers. As such, there should rarely be a need to explicitly change this - * protocol version. - * - * If you want to explicitly use the legacy HTTP/1.0 protocol version, you - * can use this method: - * - * ```php - * $browser = $browser->withProtocolVersion('1.0'); - * - * $browser->get($url)->then(…); - * ``` - * - * Notice that the [`Browser`](#browser) is an immutable object, i.e. this - * method actually returns a *new* [`Browser`](#browser) instance with the - * new protocol version applied. - * - * @param string $protocolVersion HTTP protocol version to use, must be one of "1.1" or "1.0" - * @return self - * @throws InvalidArgumentException - */ - public function withProtocolVersion($protocolVersion) - { - if (!\in_array($protocolVersion, array('1.0', '1.1'), true)) { - throw new InvalidArgumentException('Invalid HTTP protocol version, must be one of "1.1" or "1.0"'); - } - - $browser = clone $this; - $browser->protocolVersion = (string) $protocolVersion; - - return $browser; - } - - /** - * Changes the maximum size for buffering a response body. - * - * The preferred way to send an HTTP request is by using the above - * [request methods](#request-methods), for example the [`get()`](#get) - * method to send an HTTP `GET` request. Each of these methods will buffer - * the whole response body in memory by default. This is easy to get started - * and works reasonably well for smaller responses. - * - * By default, the response body buffer will be limited to 16 MiB. If the - * response body exceeds this maximum size, the request will be rejected. - * - * You can pass in the maximum number of bytes to buffer: - * - * ```php - * $browser = $browser->withResponseBuffer(1024 * 1024); - * - * $browser->get($url)->then(function (Psr\Http\Message\ResponseInterface $response) { - * // response body will not exceed 1 MiB - * var_dump($response->getHeaders(), (string) $response->getBody()); - * }, function (Exception $e) { - * echo 'Error: ' . $e->getMessage() . PHP_EOL; - * }); - * ``` - * - * Note that the response body buffer has to be kept in memory for each - * pending request until its transfer is completed and it will only be freed - * after a pending request is fulfilled. As such, increasing this maximum - * buffer size to allow larger response bodies is usually not recommended. - * Instead, you can use the [`requestStreaming()` method](#requeststreaming) - * to receive responses with arbitrary sizes without buffering. Accordingly, - * this maximum buffer size setting has no effect on streaming responses. - * - * Notice that the [`Browser`](#browser) is an immutable object, i.e. this - * method actually returns a *new* [`Browser`](#browser) instance with the - * given setting applied. - * - * @param int $maximumSize - * @return self - * @see self::requestStreaming() - */ - public function withResponseBuffer($maximumSize) - { - return $this->withOptions(array( - 'maximumSize' => $maximumSize - )); - } - - /** - * Add a request header for all following requests. - * - * ```php - * $browser = $browser->withHeader('User-Agent', 'ACME'); - * - * $browser->get($url)->then(…); - * ``` - * - * Note that the new header will overwrite any headers previously set with - * the same name (case-insensitive). Following requests will use these headers - * by default unless they are explicitly set for any requests. - * - * @param string $header - * @param string $value - * @return Browser - */ - public function withHeader($header, $value) - { - $browser = $this->withoutHeader($header); - $browser->defaultHeaders[$header] = $value; - - return $browser; - } - - /** - * Remove any default request headers previously set via - * the [`withHeader()` method](#withheader). - * - * ```php - * $browser = $browser->withoutHeader('User-Agent'); - * - * $browser->get($url)->then(…); - * ``` - * - * Note that this method only affects the headers which were set with the - * method `withHeader(string $header, string $value): Browser` - * - * @param string $header - * @return Browser - */ - public function withoutHeader($header) - { - $browser = clone $this; - - /** @var string|int $key */ - foreach (\array_keys($browser->defaultHeaders) as $key) { - if (\strcasecmp($key, $header) === 0) { - unset($browser->defaultHeaders[$key]); - break; - } - } - - return $browser; - } - - /** - * Changes the [options](#options) to use: - * - * The [`Browser`](#browser) class exposes several options for the handling of - * HTTP transactions. These options resemble some of PHP's - * [HTTP context options](http://php.net/manual/en/context.http.php) and - * can be controlled via the following API (and their defaults): - * - * ```php - * // deprecated - * $newBrowser = $browser->withOptions(array( - * 'timeout' => null, // see withTimeout() instead - * 'followRedirects' => true, // see withFollowRedirects() instead - * 'maxRedirects' => 10, // see withFollowRedirects() instead - * 'obeySuccessCode' => true, // see withRejectErrorResponse() instead - * 'streaming' => false, // deprecated, see requestStreaming() instead - * )); - * ``` - * - * See also [timeouts](#timeouts), [redirects](#redirects) and - * [streaming](#streaming) for more details. - * - * Notice that the [`Browser`](#browser) is an immutable object, i.e. this - * method actually returns a *new* [`Browser`](#browser) instance with the - * options applied. - * - * @param array $options - * @return self - * @see self::withTimeout() - * @see self::withFollowRedirects() - * @see self::withRejectErrorResponse() - */ - private function withOptions(array $options) - { - $browser = clone $this; - $browser->transaction = $this->transaction->withOptions($options); - - return $browser; - } - - /** - * @param string $method - * @param string $url - * @param array $headers - * @param string|ReadableStreamInterface $body - * @return PromiseInterface - */ - private function requestMayBeStreaming($method, $url, array $headers = array(), $body = '') - { - if ($this->baseUrl !== null) { - // ensure we're actually below the base URL - $url = Uri::resolve($this->baseUrl, new Uri($url)); - } - - foreach ($this->defaultHeaders as $key => $value) { - $explicitHeaderExists = false; - foreach (\array_keys($headers) as $headerKey) { - if (\strcasecmp($headerKey, $key) === 0) { - $explicitHeaderExists = true; - break; - } - } - if (!$explicitHeaderExists) { - $headers[$key] = $value; - } - } - - return $this->transaction->send( - new Request($method, $url, $headers, $body, $this->protocolVersion) - ); - } -} diff --git a/digital_doctor/vendor/react/http/src/Client/Client.php b/digital_doctor/vendor/react/http/src/Client/Client.php deleted file mode 100644 index 7a5180a..0000000 --- a/digital_doctor/vendor/react/http/src/Client/Client.php +++ /dev/null @@ -1,27 +0,0 @@ -connectionManager = $connectionManager; - } - - /** @return ClientRequestStream */ - public function request(RequestInterface $request) - { - return new ClientRequestStream($this->connectionManager, $request); - } -} diff --git a/digital_doctor/vendor/react/http/src/HttpServer.php b/digital_doctor/vendor/react/http/src/HttpServer.php deleted file mode 100644 index f233473..0000000 --- a/digital_doctor/vendor/react/http/src/HttpServer.php +++ /dev/null @@ -1,351 +0,0 @@ - 'text/plain' - * ), - * "Hello World!\n" - * ); - * }); - * ``` - * - * Each incoming HTTP request message is always represented by the - * [PSR-7 `ServerRequestInterface`](https://www.php-fig.org/psr/psr-7/#321-psrhttpmessageserverrequestinterface), - * see also following [request](#server-request) chapter for more details. - * - * Each outgoing HTTP response message is always represented by the - * [PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface), - * see also following [response](#server-response) chapter for more details. - * - * This class takes an optional `LoopInterface|null $loop` parameter that can be used to - * pass the event loop instance to use for this object. You can use a `null` value - * here in order to use the [default loop](https://github.com/reactphp/event-loop#loop). - * This value SHOULD NOT be given unless you're sure you want to explicitly use a - * given event loop instance. - * - * In order to start listening for any incoming connections, the `HttpServer` needs - * to be attached to an instance of - * [`React\Socket\ServerInterface`](https://github.com/reactphp/socket#serverinterface) - * through the [`listen()`](#listen) method as described in the following - * chapter. In its most simple form, you can attach this to a - * [`React\Socket\SocketServer`](https://github.com/reactphp/socket#socketserver) - * in order to start a plaintext HTTP server like this: - * - * ```php - * $http = new React\Http\HttpServer($handler); - * - * $socket = new React\Socket\SocketServer('0.0.0.0:8080'); - * $http->listen($socket); - * ``` - * - * See also the [`listen()`](#listen) method and - * [hello world server example](../examples/51-server-hello-world.php) - * for more details. - * - * By default, the `HttpServer` buffers and parses the complete incoming HTTP - * request in memory. It will invoke the given request handler function when the - * complete request headers and request body has been received. This means the - * [request](#server-request) object passed to your request handler function will be - * fully compatible with PSR-7 (http-message). This provides sane defaults for - * 80% of the use cases and is the recommended way to use this library unless - * you're sure you know what you're doing. - * - * On the other hand, buffering complete HTTP requests in memory until they can - * be processed by your request handler function means that this class has to - * employ a number of limits to avoid consuming too much memory. In order to - * take the more advanced configuration out your hand, it respects setting from - * your [`php.ini`](https://www.php.net/manual/en/ini.core.php) to apply its - * default settings. This is a list of PHP settings this class respects with - * their respective default values: - * - * ``` - * memory_limit 128M - * post_max_size 8M // capped at 64K - * - * enable_post_data_reading 1 - * max_input_nesting_level 64 - * max_input_vars 1000 - * - * file_uploads 1 - * upload_max_filesize 2M - * max_file_uploads 20 - * ``` - * - * In particular, the `post_max_size` setting limits how much memory a single - * HTTP request is allowed to consume while buffering its request body. This - * needs to be limited because the server can process a large number of requests - * concurrently, so the server may potentially consume a large amount of memory - * otherwise. To support higher concurrency by default, this value is capped - * at `64K`. If you assign a higher value, it will only allow `64K` by default. - * If a request exceeds this limit, its request body will be ignored and it will - * be processed like a request with no request body at all. See below for - * explicit configuration to override this setting. - * - * By default, this class will try to avoid consuming more than half of your - * `memory_limit` for buffering multiple concurrent HTTP requests. As such, with - * the above default settings of `128M` max, it will try to consume no more than - * `64M` for buffering multiple concurrent HTTP requests. As a consequence, it - * will limit the concurrency to `1024` HTTP requests with the above defaults. - * - * It is imperative that you assign reasonable values to your PHP ini settings. - * It is usually recommended to not support buffering incoming HTTP requests - * with a large HTTP request body (e.g. large file uploads). If you want to - * increase this buffer size, you will have to also increase the total memory - * limit to allow for more concurrent requests (set `memory_limit 512M` or more) - * or explicitly limit concurrency. - * - * In order to override the above buffering defaults, you can configure the - * `HttpServer` explicitly. You can use the - * [`LimitConcurrentRequestsMiddleware`](#limitconcurrentrequestsmiddleware) and - * [`RequestBodyBufferMiddleware`](#requestbodybuffermiddleware) (see below) - * to explicitly configure the total number of requests that can be handled at - * once like this: - * - * ```php - * $http = new React\Http\HttpServer( - * new React\Http\Middleware\StreamingRequestMiddleware(), - * new React\Http\Middleware\LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers - * new React\Http\Middleware\RequestBodyBufferMiddleware(2 * 1024 * 1024), // 2 MiB per request - * new React\Http\Middleware\RequestBodyParserMiddleware(), - * $handler - * )); - * ``` - * - * In this example, we allow processing up to 100 concurrent requests at once - * and each request can buffer up to `2M`. This means you may have to keep a - * maximum of `200M` of memory for incoming request body buffers. Accordingly, - * you need to adjust the `memory_limit` ini setting to allow for these buffers - * plus your actual application logic memory requirements (think `512M` or more). - * - * > Internally, this class automatically assigns these middleware handlers - * automatically when no [`StreamingRequestMiddleware`](#streamingrequestmiddleware) - * is given. Accordingly, you can use this example to override all default - * settings to implement custom limits. - * - * As an alternative to buffering the complete request body in memory, you can - * also use a streaming approach where only small chunks of data have to be kept - * in memory: - * - * ```php - * $http = new React\Http\HttpServer( - * new React\Http\Middleware\StreamingRequestMiddleware(), - * $handler - * ); - * ``` - * - * In this case, it will invoke the request handler function once the HTTP - * request headers have been received, i.e. before receiving the potentially - * much larger HTTP request body. This means the [request](#server-request) passed to - * your request handler function may not be fully compatible with PSR-7. This is - * specifically designed to help with more advanced use cases where you want to - * have full control over consuming the incoming HTTP request body and - * concurrency settings. See also [streaming incoming request](#streaming-incoming-request) - * below for more details. - * - * > Changelog v1.5.0: This class has been renamed to `HttpServer` from the - * previous `Server` class in order to avoid any ambiguities. - * The previous name has been deprecated and should not be used anymore. - */ -final class HttpServer extends EventEmitter -{ - /** - * The maximum buffer size used for each request. - * - * This needs to be limited because the server can process a large number of - * requests concurrently, so the server may potentially consume a large - * amount of memory otherwise. - * - * See `RequestBodyBufferMiddleware` to override this setting. - * - * @internal - */ - const MAXIMUM_BUFFER_SIZE = 65536; // 64 KiB - - /** - * @var StreamingServer - */ - private $streamingServer; - - /** - * Creates an HTTP server that invokes the given callback for each incoming HTTP request - * - * In order to process any connections, the server needs to be attached to an - * instance of `React\Socket\ServerInterface` which emits underlying streaming - * connections in order to then parse incoming data as HTTP. - * See also [listen()](#listen) for more details. - * - * @param callable|LoopInterface $requestHandlerOrLoop - * @param callable[] ...$requestHandler - * @see self::listen() - */ - public function __construct($requestHandlerOrLoop) - { - $requestHandlers = \func_get_args(); - if (reset($requestHandlers) instanceof LoopInterface) { - $loop = \array_shift($requestHandlers); - } else { - $loop = Loop::get(); - } - - $requestHandlersCount = \count($requestHandlers); - if ($requestHandlersCount === 0 || \count(\array_filter($requestHandlers, 'is_callable')) < $requestHandlersCount) { - throw new \InvalidArgumentException('Invalid request handler given'); - } - - $streaming = false; - foreach ((array) $requestHandlers as $handler) { - if ($handler instanceof StreamingRequestMiddleware) { - $streaming = true; - break; - } - } - - $middleware = array(); - if (!$streaming) { - $maxSize = $this->getMaxRequestSize(); - $concurrency = $this->getConcurrentRequestsLimit(\ini_get('memory_limit'), $maxSize); - if ($concurrency !== null) { - $middleware[] = new LimitConcurrentRequestsMiddleware($concurrency); - } - $middleware[] = new RequestBodyBufferMiddleware($maxSize); - // Checking for an empty string because that is what a boolean - // false is returned as by ini_get depending on the PHP version. - // @link http://php.net/manual/en/ini.core.php#ini.enable-post-data-reading - // @link http://php.net/manual/en/function.ini-get.php#refsect1-function.ini-get-notes - // @link https://3v4l.org/qJtsa - $enablePostDataReading = \ini_get('enable_post_data_reading'); - if ($enablePostDataReading !== '') { - $middleware[] = new RequestBodyParserMiddleware(); - } - } - - $middleware = \array_merge($middleware, $requestHandlers); - - /** - * Filter out any configuration middleware, no need to run requests through something that isn't - * doing anything with the request. - */ - $middleware = \array_filter($middleware, function ($handler) { - return !($handler instanceof StreamingRequestMiddleware); - }); - - $this->streamingServer = new StreamingServer($loop, new MiddlewareRunner($middleware)); - - $that = $this; - $this->streamingServer->on('error', function ($error) use ($that) { - $that->emit('error', array($error)); - }); - } - - /** - * Starts listening for HTTP requests on the given socket server instance - * - * The given [`React\Socket\ServerInterface`](https://github.com/reactphp/socket#serverinterface) - * is responsible for emitting the underlying streaming connections. This - * HTTP server needs to be attached to it in order to process any - * connections and pase incoming streaming data as incoming HTTP request - * messages. In its most common form, you can attach this to a - * [`React\Socket\SocketServer`](https://github.com/reactphp/socket#socketserver) - * in order to start a plaintext HTTP server like this: - * - * ```php - * $http = new React\Http\HttpServer($handler); - * - * $socket = new React\Socket\SocketServer('0.0.0.0:8080'); - * $http->listen($socket); - * ``` - * - * See also [hello world server example](../examples/51-server-hello-world.php) - * for more details. - * - * This example will start listening for HTTP requests on the alternative - * HTTP port `8080` on all interfaces (publicly). As an alternative, it is - * very common to use a reverse proxy and let this HTTP server listen on the - * localhost (loopback) interface only by using the listen address - * `127.0.0.1:8080` instead. This way, you host your application(s) on the - * default HTTP port `80` and only route specific requests to this HTTP - * server. - * - * Likewise, it's usually recommended to use a reverse proxy setup to accept - * secure HTTPS requests on default HTTPS port `443` (TLS termination) and - * only route plaintext requests to this HTTP server. As an alternative, you - * can also accept secure HTTPS requests with this HTTP server by attaching - * this to a [`React\Socket\SocketServer`](https://github.com/reactphp/socket#socketserver) - * using a secure TLS listen address, a certificate file and optional - * `passphrase` like this: - * - * ```php - * $http = new React\Http\HttpServer($handler); - * - * $socket = new React\Socket\SocketServer('tls://0.0.0.0:8443', array( - * 'tls' => array( - * 'local_cert' => __DIR__ . '/localhost.pem' - * ) - * )); - * $http->listen($socket); - * ``` - * - * See also [hello world HTTPS example](../examples/61-server-hello-world-https.php) - * for more details. - * - * @param ServerInterface $socket - */ - public function listen(ServerInterface $socket) - { - $this->streamingServer->listen($socket); - } - - /** - * @param string $memory_limit - * @param string $post_max_size - * @return ?int - */ - private function getConcurrentRequestsLimit($memory_limit, $post_max_size) - { - if ($memory_limit == -1) { - return null; - } - - $availableMemory = IniUtil::iniSizeToBytes($memory_limit) / 2; - $concurrentRequests = (int) \ceil($availableMemory / IniUtil::iniSizeToBytes($post_max_size)); - - return $concurrentRequests; - } - - /** - * @param ?string $post_max_size - * @return int - */ - private function getMaxRequestSize($post_max_size = null) - { - $maxSize = IniUtil::iniSizeToBytes($post_max_size === null ? \ini_get('post_max_size') : $post_max_size); - - return ($maxSize === 0 || $maxSize >= self::MAXIMUM_BUFFER_SIZE) ? self::MAXIMUM_BUFFER_SIZE : $maxSize; - } -} diff --git a/digital_doctor/vendor/react/http/src/Io/AbstractMessage.php b/digital_doctor/vendor/react/http/src/Io/AbstractMessage.php deleted file mode 100644 index a0706bb..0000000 --- a/digital_doctor/vendor/react/http/src/Io/AbstractMessage.php +++ /dev/null @@ -1,172 +0,0 @@ -@,;:\\\"\/\[\]?={}\x00-\x20\x7F]++):[\x20\x09]*+((?:[\x20\x09]*+[\x21-\x7E\x80-\xFF]++)*+)[\x20\x09]*+[\r]?+\n/m'; - - /** @var array */ - private $headers = array(); - - /** @var array */ - private $headerNamesLowerCase = array(); - - /** @var string */ - private $protocolVersion; - - /** @var StreamInterface */ - private $body; - - /** - * @param string $protocolVersion - * @param array $headers - * @param StreamInterface $body - */ - protected function __construct($protocolVersion, array $headers, StreamInterface $body) - { - foreach ($headers as $name => $value) { - if ($value !== array()) { - if (\is_array($value)) { - foreach ($value as &$one) { - $one = (string) $one; - } - } else { - $value = array((string) $value); - } - - $lower = \strtolower($name); - if (isset($this->headerNamesLowerCase[$lower])) { - $value = \array_merge($this->headers[$this->headerNamesLowerCase[$lower]], $value); - unset($this->headers[$this->headerNamesLowerCase[$lower]]); - } - - $this->headers[$name] = $value; - $this->headerNamesLowerCase[$lower] = $name; - } - } - - $this->protocolVersion = (string) $protocolVersion; - $this->body = $body; - } - - public function getProtocolVersion() - { - return $this->protocolVersion; - } - - public function withProtocolVersion($version) - { - if ((string) $version === $this->protocolVersion) { - return $this; - } - - $message = clone $this; - $message->protocolVersion = (string) $version; - - return $message; - } - - public function getHeaders() - { - return $this->headers; - } - - public function hasHeader($name) - { - return isset($this->headerNamesLowerCase[\strtolower($name)]); - } - - public function getHeader($name) - { - $lower = \strtolower($name); - return isset($this->headerNamesLowerCase[$lower]) ? $this->headers[$this->headerNamesLowerCase[$lower]] : array(); - } - - public function getHeaderLine($name) - { - return \implode(', ', $this->getHeader($name)); - } - - public function withHeader($name, $value) - { - if ($value === array()) { - return $this->withoutHeader($name); - } elseif (\is_array($value)) { - foreach ($value as &$one) { - $one = (string) $one; - } - } else { - $value = array((string) $value); - } - - $lower = \strtolower($name); - if (isset($this->headerNamesLowerCase[$lower]) && $this->headerNamesLowerCase[$lower] === (string) $name && $this->headers[$this->headerNamesLowerCase[$lower]] === $value) { - return $this; - } - - $message = clone $this; - if (isset($message->headerNamesLowerCase[$lower])) { - unset($message->headers[$message->headerNamesLowerCase[$lower]]); - } - - $message->headers[$name] = $value; - $message->headerNamesLowerCase[$lower] = $name; - - return $message; - } - - public function withAddedHeader($name, $value) - { - if ($value === array()) { - return $this; - } - - return $this->withHeader($name, \array_merge($this->getHeader($name), \is_array($value) ? $value : array($value))); - } - - public function withoutHeader($name) - { - $lower = \strtolower($name); - if (!isset($this->headerNamesLowerCase[$lower])) { - return $this; - } - - $message = clone $this; - unset($message->headers[$message->headerNamesLowerCase[$lower]], $message->headerNamesLowerCase[$lower]); - - return $message; - } - - public function getBody() - { - return $this->body; - } - - public function withBody(StreamInterface $body) - { - if ($body === $this->body) { - return $this; - } - - $message = clone $this; - $message->body = $body; - - return $message; - } -} diff --git a/digital_doctor/vendor/react/http/src/Io/AbstractRequest.php b/digital_doctor/vendor/react/http/src/Io/AbstractRequest.php deleted file mode 100644 index f32307f..0000000 --- a/digital_doctor/vendor/react/http/src/Io/AbstractRequest.php +++ /dev/null @@ -1,156 +0,0 @@ - $headers - * @param StreamInterface $body - * @param string unknown $protocolVersion - */ - protected function __construct( - $method, - $uri, - array $headers, - StreamInterface $body, - $protocolVersion - ) { - if (\is_string($uri)) { - $uri = new Uri($uri); - } elseif (!$uri instanceof UriInterface) { - throw new \InvalidArgumentException( - 'Argument #2 ($uri) expected string|Psr\Http\Message\UriInterface' - ); - } - - // assign default `Host` request header from URI unless already given explicitly - $host = $uri->getHost(); - if ($host !== '') { - foreach ($headers as $name => $value) { - if (\strtolower($name) === 'host' && $value !== array()) { - $host = ''; - break; - } - } - if ($host !== '') { - $port = $uri->getPort(); - if ($port !== null && (!($port === 80 && $uri->getScheme() === 'http') || !($port === 443 && $uri->getScheme() === 'https'))) { - $host .= ':' . $port; - } - - $headers = array('Host' => $host) + $headers; - } - } - - parent::__construct($protocolVersion, $headers, $body); - - $this->method = $method; - $this->uri = $uri; - } - - public function getRequestTarget() - { - if ($this->requestTarget !== null) { - return $this->requestTarget; - } - - $target = $this->uri->getPath(); - if ($target === '') { - $target = '/'; - } - if (($query = $this->uri->getQuery()) !== '') { - $target .= '?' . $query; - } - - return $target; - } - - public function withRequestTarget($requestTarget) - { - if ((string) $requestTarget === $this->requestTarget) { - return $this; - } - - $request = clone $this; - $request->requestTarget = (string) $requestTarget; - - return $request; - } - - public function getMethod() - { - return $this->method; - } - - public function withMethod($method) - { - if ((string) $method === $this->method) { - return $this; - } - - $request = clone $this; - $request->method = (string) $method; - - return $request; - } - - public function getUri() - { - return $this->uri; - } - - public function withUri(UriInterface $uri, $preserveHost = false) - { - if ($uri === $this->uri) { - return $this; - } - - $request = clone $this; - $request->uri = $uri; - - $host = $uri->getHost(); - $port = $uri->getPort(); - if ($port !== null && $host !== '' && (!($port === 80 && $uri->getScheme() === 'http') || !($port === 443 && $uri->getScheme() === 'https'))) { - $host .= ':' . $port; - } - - // update `Host` request header if URI contains a new host and `$preserveHost` is false - if ($host !== '' && (!$preserveHost || $request->getHeaderLine('Host') === '')) { - // first remove all headers before assigning `Host` header to ensure it always comes first - foreach (\array_keys($request->getHeaders()) as $name) { - $request = $request->withoutHeader($name); - } - - // add `Host` header first, then all other original headers - $request = $request->withHeader('Host', $host); - foreach ($this->withoutHeader('Host')->getHeaders() as $name => $value) { - $request = $request->withHeader($name, $value); - } - } - - return $request; - } -} diff --git a/digital_doctor/vendor/react/http/src/Io/BufferedBody.php b/digital_doctor/vendor/react/http/src/Io/BufferedBody.php deleted file mode 100644 index 4a4d839..0000000 --- a/digital_doctor/vendor/react/http/src/Io/BufferedBody.php +++ /dev/null @@ -1,179 +0,0 @@ -buffer = $buffer; - } - - public function __toString() - { - if ($this->closed) { - return ''; - } - - $this->seek(0); - - return $this->getContents(); - } - - public function close() - { - $this->buffer = ''; - $this->position = 0; - $this->closed = true; - } - - public function detach() - { - $this->close(); - - return null; - } - - public function getSize() - { - return $this->closed ? null : \strlen($this->buffer); - } - - public function tell() - { - if ($this->closed) { - throw new \RuntimeException('Unable to tell position of closed stream'); - } - - return $this->position; - } - - public function eof() - { - return $this->position >= \strlen($this->buffer); - } - - public function isSeekable() - { - return !$this->closed; - } - - public function seek($offset, $whence = \SEEK_SET) - { - if ($this->closed) { - throw new \RuntimeException('Unable to seek on closed stream'); - } - - $old = $this->position; - - if ($whence === \SEEK_SET) { - $this->position = $offset; - } elseif ($whence === \SEEK_CUR) { - $this->position += $offset; - } elseif ($whence === \SEEK_END) { - $this->position = \strlen($this->buffer) + $offset; - } else { - throw new \InvalidArgumentException('Invalid seek mode given'); - } - - if (!\is_int($this->position) || $this->position < 0) { - $this->position = $old; - throw new \RuntimeException('Unable to seek to position'); - } - } - - public function rewind() - { - $this->seek(0); - } - - public function isWritable() - { - return !$this->closed; - } - - public function write($string) - { - if ($this->closed) { - throw new \RuntimeException('Unable to write to closed stream'); - } - - if ($string === '') { - return 0; - } - - if ($this->position > 0 && !isset($this->buffer[$this->position - 1])) { - $this->buffer = \str_pad($this->buffer, $this->position, "\0"); - } - - $len = \strlen($string); - $this->buffer = \substr($this->buffer, 0, $this->position) . $string . \substr($this->buffer, $this->position + $len); - $this->position += $len; - - return $len; - } - - public function isReadable() - { - return !$this->closed; - } - - public function read($length) - { - if ($this->closed) { - throw new \RuntimeException('Unable to read from closed stream'); - } - - if ($length < 1) { - throw new \InvalidArgumentException('Invalid read length given'); - } - - if ($this->position + $length > \strlen($this->buffer)) { - $length = \strlen($this->buffer) - $this->position; - } - - if (!isset($this->buffer[$this->position])) { - return ''; - } - - $pos = $this->position; - $this->position += $length; - - return \substr($this->buffer, $pos, $length); - } - - public function getContents() - { - if ($this->closed) { - throw new \RuntimeException('Unable to read from closed stream'); - } - - if (!isset($this->buffer[$this->position])) { - return ''; - } - - $pos = $this->position; - $this->position = \strlen($this->buffer); - - return \substr($this->buffer, $pos); - } - - public function getMetadata($key = null) - { - return $key === null ? array() : null; - } -} diff --git a/digital_doctor/vendor/react/http/src/Io/ChunkedDecoder.php b/digital_doctor/vendor/react/http/src/Io/ChunkedDecoder.php deleted file mode 100644 index 2f58f42..0000000 --- a/digital_doctor/vendor/react/http/src/Io/ChunkedDecoder.php +++ /dev/null @@ -1,175 +0,0 @@ -input = $input; - - $this->input->on('data', array($this, 'handleData')); - $this->input->on('end', array($this, 'handleEnd')); - $this->input->on('error', array($this, 'handleError')); - $this->input->on('close', array($this, 'close')); - } - - public function isReadable() - { - return !$this->closed && $this->input->isReadable(); - } - - public function pause() - { - $this->input->pause(); - } - - public function resume() - { - $this->input->resume(); - } - - public function pipe(WritableStreamInterface $dest, array $options = array()) - { - Util::pipe($this, $dest, $options); - - return $dest; - } - - public function close() - { - if ($this->closed) { - return; - } - - $this->buffer = ''; - - $this->closed = true; - - $this->input->close(); - - $this->emit('close'); - $this->removeAllListeners(); - } - - /** @internal */ - public function handleEnd() - { - if (!$this->closed) { - $this->handleError(new Exception('Unexpected end event')); - } - } - - /** @internal */ - public function handleError(Exception $e) - { - $this->emit('error', array($e)); - $this->close(); - } - - /** @internal */ - public function handleData($data) - { - $this->buffer .= $data; - - while ($this->buffer !== '') { - if (!$this->headerCompleted) { - $positionCrlf = \strpos($this->buffer, static::CRLF); - - if ($positionCrlf === false) { - // Header shouldn't be bigger than 1024 bytes - if (isset($this->buffer[static::MAX_CHUNK_HEADER_SIZE])) { - $this->handleError(new Exception('Chunk header size inclusive extension bigger than' . static::MAX_CHUNK_HEADER_SIZE. ' bytes')); - } - return; - } - - $header = \strtolower((string)\substr($this->buffer, 0, $positionCrlf)); - $hexValue = $header; - - if (\strpos($header, ';') !== false) { - $array = \explode(';', $header); - $hexValue = $array[0]; - } - - if ($hexValue !== '') { - $hexValue = \ltrim(\trim($hexValue), "0"); - if ($hexValue === '') { - $hexValue = "0"; - } - } - - $this->chunkSize = @\hexdec($hexValue); - if (!\is_int($this->chunkSize) || \dechex($this->chunkSize) !== $hexValue) { - $this->handleError(new Exception($hexValue . ' is not a valid hexadecimal number')); - return; - } - - $this->buffer = (string)\substr($this->buffer, $positionCrlf + 2); - $this->headerCompleted = true; - if ($this->buffer === '') { - return; - } - } - - $chunk = (string)\substr($this->buffer, 0, $this->chunkSize - $this->transferredSize); - - if ($chunk !== '') { - $this->transferredSize += \strlen($chunk); - $this->emit('data', array($chunk)); - $this->buffer = (string)\substr($this->buffer, \strlen($chunk)); - } - - $positionCrlf = \strpos($this->buffer, static::CRLF); - - if ($positionCrlf === 0) { - if ($this->chunkSize === 0) { - $this->emit('end'); - $this->close(); - return; - } - $this->chunkSize = 0; - $this->headerCompleted = false; - $this->transferredSize = 0; - $this->buffer = (string)\substr($this->buffer, 2); - } elseif ($this->chunkSize === 0) { - // end chunk received, skip all trailer data - $this->buffer = (string)\substr($this->buffer, $positionCrlf); - } - - if ($positionCrlf !== 0 && $this->chunkSize !== 0 && $this->chunkSize === $this->transferredSize && \strlen($this->buffer) > 2) { - // the first 2 characters are not CRLF, send error event - $this->handleError(new Exception('Chunk does not end with a CRLF')); - return; - } - - if ($positionCrlf !== 0 && \strlen($this->buffer) < 2) { - // No CRLF found, wait for additional data which could be a CRLF - return; - } - } - } -} diff --git a/digital_doctor/vendor/react/http/src/Io/ChunkedEncoder.php b/digital_doctor/vendor/react/http/src/Io/ChunkedEncoder.php deleted file mode 100644 index c84ef54..0000000 --- a/digital_doctor/vendor/react/http/src/Io/ChunkedEncoder.php +++ /dev/null @@ -1,92 +0,0 @@ -input = $input; - - $this->input->on('data', array($this, 'handleData')); - $this->input->on('end', array($this, 'handleEnd')); - $this->input->on('error', array($this, 'handleError')); - $this->input->on('close', array($this, 'close')); - } - - public function isReadable() - { - return !$this->closed && $this->input->isReadable(); - } - - public function pause() - { - $this->input->pause(); - } - - public function resume() - { - $this->input->resume(); - } - - public function pipe(WritableStreamInterface $dest, array $options = array()) - { - return Util::pipe($this, $dest, $options); - } - - public function close() - { - if ($this->closed) { - return; - } - - $this->closed = true; - $this->input->close(); - - $this->emit('close'); - $this->removeAllListeners(); - } - - /** @internal */ - public function handleData($data) - { - if ($data !== '') { - $this->emit('data', array( - \dechex(\strlen($data)) . "\r\n" . $data . "\r\n" - )); - } - } - - /** @internal */ - public function handleError(\Exception $e) - { - $this->emit('error', array($e)); - $this->close(); - } - - /** @internal */ - public function handleEnd() - { - $this->emit('data', array("0\r\n\r\n")); - - if (!$this->closed) { - $this->emit('end'); - $this->close(); - } - } -} diff --git a/digital_doctor/vendor/react/http/src/Io/ClientConnectionManager.php b/digital_doctor/vendor/react/http/src/Io/ClientConnectionManager.php deleted file mode 100644 index faac98b..0000000 --- a/digital_doctor/vendor/react/http/src/Io/ClientConnectionManager.php +++ /dev/null @@ -1,137 +0,0 @@ -connector = $connector; - $this->loop = $loop; - } - - /** - * @return PromiseInterface - */ - public function connect(UriInterface $uri) - { - $scheme = $uri->getScheme(); - if ($scheme !== 'https' && $scheme !== 'http') { - return \React\Promise\reject(new \InvalidArgumentException( - 'Invalid request URL given' - )); - } - - $port = $uri->getPort(); - if ($port === null) { - $port = $scheme === 'https' ? 443 : 80; - } - $uri = ($scheme === 'https' ? 'tls://' : '') . $uri->getHost() . ':' . $port; - - // Reuse idle connection for same URI if available - foreach ($this->idleConnections as $id => $connection) { - if ($this->idleUris[$id] === $uri) { - assert($this->idleStreamHandlers[$id] instanceof \Closure); - $connection->removeListener('close', $this->idleStreamHandlers[$id]); - $connection->removeListener('data', $this->idleStreamHandlers[$id]); - $connection->removeListener('error', $this->idleStreamHandlers[$id]); - - assert($this->idleTimers[$id] instanceof TimerInterface); - $this->loop->cancelTimer($this->idleTimers[$id]); - unset($this->idleUris[$id], $this->idleConnections[$id], $this->idleTimers[$id], $this->idleStreamHandlers[$id]); - - return \React\Promise\resolve($connection); - } - } - - // Create new connection if no idle connection to same URI is available - return $this->connector->connect($uri); - } - - /** - * Hands back an idle connection to the connection manager for possible future reuse. - * - * @return void - */ - public function keepAlive(UriInterface $uri, ConnectionInterface $connection) - { - $scheme = $uri->getScheme(); - assert($scheme === 'https' || $scheme === 'http'); - - $port = $uri->getPort(); - if ($port === null) { - $port = $scheme === 'https' ? 443 : 80; - } - - $this->idleUris[] = ($scheme === 'https' ? 'tls://' : '') . $uri->getHost() . ':' . $port; - $this->idleConnections[] = $connection; - - $that = $this; - $cleanUp = function () use ($connection, $that) { - // call public method to support legacy PHP 5.3 - $that->cleanUpConnection($connection); - }; - - // clean up and close connection when maximum time to keep-alive idle connection has passed - $this->idleTimers[] = $this->loop->addTimer($this->maximumTimeToKeepAliveIdleConnection, $cleanUp); - - // clean up and close connection when unexpected close/data/error event happens during idle time - $this->idleStreamHandlers[] = $cleanUp; - $connection->on('close', $cleanUp); - $connection->on('data', $cleanUp); - $connection->on('error', $cleanUp); - } - - /** - * @internal - * @return void - */ - public function cleanUpConnection(ConnectionInterface $connection) // private (PHP 5.4+) - { - $id = \array_search($connection, $this->idleConnections, true); - if ($id === false) { - return; - } - - assert(\is_int($id)); - assert($this->idleTimers[$id] instanceof TimerInterface); - $this->loop->cancelTimer($this->idleTimers[$id]); - unset($this->idleUris[$id], $this->idleConnections[$id], $this->idleTimers[$id], $this->idleStreamHandlers[$id]); - - $connection->close(); - } -} diff --git a/digital_doctor/vendor/react/http/src/Io/ClientRequestState.php b/digital_doctor/vendor/react/http/src/Io/ClientRequestState.php deleted file mode 100644 index 73a63a1..0000000 --- a/digital_doctor/vendor/react/http/src/Io/ClientRequestState.php +++ /dev/null @@ -1,16 +0,0 @@ -connectionManager = $connectionManager; - $this->request = $request; - } - - public function isWritable() - { - return self::STATE_END > $this->state && !$this->ended; - } - - private function writeHead() - { - $this->state = self::STATE_WRITING_HEAD; - - $expected = 0; - $headers = "{$this->request->getMethod()} {$this->request->getRequestTarget()} HTTP/{$this->request->getProtocolVersion()}\r\n"; - foreach ($this->request->getHeaders() as $name => $values) { - if (\strpos($name, ':') !== false) { - $expected = -1; - break; - } - foreach ($values as $value) { - $headers .= "$name: $value\r\n"; - ++$expected; - } - } - - /** @var array $m legacy PHP 5.3 only */ - if (!\preg_match('#^\S+ \S+ HTTP/1\.[01]\r\n#m', $headers) || \substr_count($headers, "\n") !== ($expected + 1) || (\PHP_VERSION_ID >= 50400 ? \preg_match_all(AbstractMessage::REGEX_HEADERS, $headers) : \preg_match_all(AbstractMessage::REGEX_HEADERS, $headers, $m)) !== $expected) { - $this->closeError(new \InvalidArgumentException('Unable to send request with invalid request headers')); - return; - } - - $connectionRef = &$this->connection; - $stateRef = &$this->state; - $pendingWrites = &$this->pendingWrites; - $that = $this; - - $promise = $this->connectionManager->connect($this->request->getUri()); - $promise->then( - function (ConnectionInterface $connection) use ($headers, &$connectionRef, &$stateRef, &$pendingWrites, $that) { - $connectionRef = $connection; - assert($connectionRef instanceof ConnectionInterface); - - $connection->on('drain', array($that, 'handleDrain')); - $connection->on('data', array($that, 'handleData')); - $connection->on('end', array($that, 'handleEnd')); - $connection->on('error', array($that, 'handleError')); - $connection->on('close', array($that, 'close')); - - $more = $connection->write($headers . "\r\n" . $pendingWrites); - - assert($stateRef === ClientRequestStream::STATE_WRITING_HEAD); - $stateRef = ClientRequestStream::STATE_HEAD_WRITTEN; - - // clear pending writes if non-empty - if ($pendingWrites !== '') { - $pendingWrites = ''; - - if ($more) { - $that->emit('drain'); - } - } - }, - array($this, 'closeError') - ); - - $this->on('close', function() use ($promise) { - $promise->cancel(); - }); - } - - public function write($data) - { - if (!$this->isWritable()) { - return false; - } - - // write directly to connection stream if already available - if (self::STATE_HEAD_WRITTEN <= $this->state) { - return $this->connection->write($data); - } - - // otherwise buffer and try to establish connection - $this->pendingWrites .= $data; - if (self::STATE_WRITING_HEAD > $this->state) { - $this->writeHead(); - } - - return false; - } - - public function end($data = null) - { - if (!$this->isWritable()) { - return; - } - - if (null !== $data) { - $this->write($data); - } else if (self::STATE_WRITING_HEAD > $this->state) { - $this->writeHead(); - } - - $this->ended = true; - } - - /** @internal */ - public function handleDrain() - { - $this->emit('drain'); - } - - /** @internal */ - public function handleData($data) - { - $this->buffer .= $data; - - // buffer until double CRLF (or double LF for compatibility with legacy servers) - $eom = \strpos($this->buffer, "\r\n\r\n"); - $eomLegacy = \strpos($this->buffer, "\n\n"); - if ($eom !== false || $eomLegacy !== false) { - try { - if ($eom !== false && ($eomLegacy === false || $eom < $eomLegacy)) { - $response = Response::parseMessage(\substr($this->buffer, 0, $eom + 2)); - $bodyChunk = (string) \substr($this->buffer, $eom + 4); - } else { - $response = Response::parseMessage(\substr($this->buffer, 0, $eomLegacy + 1)); - $bodyChunk = (string) \substr($this->buffer, $eomLegacy + 2); - } - } catch (\InvalidArgumentException $exception) { - $this->closeError($exception); - return; - } - - // response headers successfully received => remove listeners for connection events - $connection = $this->connection; - assert($connection instanceof ConnectionInterface); - $connection->removeListener('drain', array($this, 'handleDrain')); - $connection->removeListener('data', array($this, 'handleData')); - $connection->removeListener('end', array($this, 'handleEnd')); - $connection->removeListener('error', array($this, 'handleError')); - $connection->removeListener('close', array($this, 'close')); - $this->connection = null; - $this->buffer = ''; - - // take control over connection handling and check if we can reuse the connection once response body closes - $that = $this; - $request = $this->request; - $connectionManager = $this->connectionManager; - $successfulEndReceived = false; - $input = $body = new CloseProtectionStream($connection); - $input->on('close', function () use ($connection, $that, $connectionManager, $request, $response, &$successfulEndReceived) { - // only reuse connection after successful response and both request and response allow keep alive - if ($successfulEndReceived && $connection->isReadable() && $that->hasMessageKeepAliveEnabled($response) && $that->hasMessageKeepAliveEnabled($request)) { - $connectionManager->keepAlive($request->getUri(), $connection); - } else { - $connection->close(); - } - - $that->close(); - }); - - // determine length of response body - $length = null; - $code = $response->getStatusCode(); - if ($this->request->getMethod() === 'HEAD' || ($code >= 100 && $code < 200) || $code == Response::STATUS_NO_CONTENT || $code == Response::STATUS_NOT_MODIFIED) { - $length = 0; - } elseif (\strtolower($response->getHeaderLine('Transfer-Encoding')) === 'chunked') { - $body = new ChunkedDecoder($body); - } elseif ($response->hasHeader('Content-Length')) { - $length = (int) $response->getHeaderLine('Content-Length'); - } - $response = $response->withBody($body = new ReadableBodyStream($body, $length)); - $body->on('end', function () use (&$successfulEndReceived) { - $successfulEndReceived = true; - }); - - // emit response with streaming response body (see `Sender`) - $this->emit('response', array($response, $body)); - - // re-emit HTTP response body to trigger body parsing if parts of it are buffered - if ($bodyChunk !== '') { - $input->handleData($bodyChunk); - } elseif ($length === 0) { - $input->handleEnd(); - } - } - } - - /** @internal */ - public function handleEnd() - { - $this->closeError(new \RuntimeException( - "Connection ended before receiving response" - )); - } - - /** @internal */ - public function handleError(\Exception $error) - { - $this->closeError(new \RuntimeException( - "An error occurred in the underlying stream", - 0, - $error - )); - } - - /** @internal */ - public function closeError(\Exception $error) - { - if (self::STATE_END <= $this->state) { - return; - } - $this->emit('error', array($error)); - $this->close(); - } - - public function close() - { - if (self::STATE_END <= $this->state) { - return; - } - - $this->state = self::STATE_END; - $this->pendingWrites = ''; - $this->buffer = ''; - - if ($this->connection instanceof ConnectionInterface) { - $this->connection->close(); - $this->connection = null; - } - - $this->emit('close'); - $this->removeAllListeners(); - } - - /** - * @internal - * @return bool - * @link https://www.rfc-editor.org/rfc/rfc9112#section-9.3 - * @link https://www.rfc-editor.org/rfc/rfc7230#section-6.1 - */ - public function hasMessageKeepAliveEnabled(MessageInterface $message) - { - // @link https://www.rfc-editor.org/rfc/rfc9110#section-7.6.1 - $connectionOptions = \array_map('trim', \explode(',', \strtolower($message->getHeaderLine('Connection')))); - - if (\in_array('close', $connectionOptions, true)) { - return false; - } - - if ($message->getProtocolVersion() === '1.1') { - return true; - } - - if (\in_array('keep-alive', $connectionOptions, true)) { - return true; - } - - return false; - } -} diff --git a/digital_doctor/vendor/react/http/src/Io/Clock.php b/digital_doctor/vendor/react/http/src/Io/Clock.php deleted file mode 100644 index 92c1cb0..0000000 --- a/digital_doctor/vendor/react/http/src/Io/Clock.php +++ /dev/null @@ -1,54 +0,0 @@ -loop = $loop; - } - - /** @return float */ - public function now() - { - if ($this->now === null) { - $this->now = \microtime(true); - - // remember clock for current loop tick only and update on next tick - $now =& $this->now; - $this->loop->futureTick(function () use (&$now) { - assert($now !== null); - $now = null; - }); - } - - return $this->now; - } -} diff --git a/digital_doctor/vendor/react/http/src/Io/CloseProtectionStream.php b/digital_doctor/vendor/react/http/src/Io/CloseProtectionStream.php deleted file mode 100644 index 2e1ed6e..0000000 --- a/digital_doctor/vendor/react/http/src/Io/CloseProtectionStream.php +++ /dev/null @@ -1,111 +0,0 @@ -input = $input; - - $this->input->on('data', array($this, 'handleData')); - $this->input->on('end', array($this, 'handleEnd')); - $this->input->on('error', array($this, 'handleError')); - $this->input->on('close', array($this, 'close')); - } - - public function isReadable() - { - return !$this->closed && $this->input->isReadable(); - } - - public function pause() - { - if ($this->closed) { - return; - } - - $this->paused = true; - $this->input->pause(); - } - - public function resume() - { - if ($this->closed) { - return; - } - - $this->paused = false; - $this->input->resume(); - } - - public function pipe(WritableStreamInterface $dest, array $options = array()) - { - Util::pipe($this, $dest, $options); - - return $dest; - } - - public function close() - { - if ($this->closed) { - return; - } - - $this->closed = true; - - // stop listening for incoming events - $this->input->removeListener('data', array($this, 'handleData')); - $this->input->removeListener('error', array($this, 'handleError')); - $this->input->removeListener('end', array($this, 'handleEnd')); - $this->input->removeListener('close', array($this, 'close')); - - // resume the stream to ensure we discard everything from incoming connection - if ($this->paused) { - $this->paused = false; - $this->input->resume(); - } - - $this->emit('close'); - $this->removeAllListeners(); - } - - /** @internal */ - public function handleData($data) - { - $this->emit('data', array($data)); - } - - /** @internal */ - public function handleEnd() - { - $this->emit('end'); - $this->close(); - } - - /** @internal */ - public function handleError(\Exception $e) - { - $this->emit('error', array($e)); - } -} diff --git a/digital_doctor/vendor/react/http/src/Io/EmptyBodyStream.php b/digital_doctor/vendor/react/http/src/Io/EmptyBodyStream.php deleted file mode 100644 index 5056219..0000000 --- a/digital_doctor/vendor/react/http/src/Io/EmptyBodyStream.php +++ /dev/null @@ -1,142 +0,0 @@ -closed; - } - - public function pause() - { - // NOOP - } - - public function resume() - { - // NOOP - } - - public function pipe(WritableStreamInterface $dest, array $options = array()) - { - Util::pipe($this, $dest, $options); - - return $dest; - } - - public function close() - { - if ($this->closed) { - return; - } - - $this->closed = true; - - $this->emit('close'); - $this->removeAllListeners(); - } - - public function getSize() - { - return 0; - } - - /** @ignore */ - public function __toString() - { - return ''; - } - - /** @ignore */ - public function detach() - { - return null; - } - - /** @ignore */ - public function tell() - { - throw new \BadMethodCallException(); - } - - /** @ignore */ - public function eof() - { - throw new \BadMethodCallException(); - } - - /** @ignore */ - public function isSeekable() - { - return false; - } - - /** @ignore */ - public function seek($offset, $whence = SEEK_SET) - { - throw new \BadMethodCallException(); - } - - /** @ignore */ - public function rewind() - { - throw new \BadMethodCallException(); - } - - /** @ignore */ - public function isWritable() - { - return false; - } - - /** @ignore */ - public function write($string) - { - throw new \BadMethodCallException(); - } - - /** @ignore */ - public function read($length) - { - throw new \BadMethodCallException(); - } - - /** @ignore */ - public function getContents() - { - return ''; - } - - /** @ignore */ - public function getMetadata($key = null) - { - return ($key === null) ? array() : null; - } -} diff --git a/digital_doctor/vendor/react/http/src/Io/HttpBodyStream.php b/digital_doctor/vendor/react/http/src/Io/HttpBodyStream.php deleted file mode 100644 index 25d15a1..0000000 --- a/digital_doctor/vendor/react/http/src/Io/HttpBodyStream.php +++ /dev/null @@ -1,182 +0,0 @@ -input = $input; - $this->size = $size; - - $this->input->on('data', array($this, 'handleData')); - $this->input->on('end', array($this, 'handleEnd')); - $this->input->on('error', array($this, 'handleError')); - $this->input->on('close', array($this, 'close')); - } - - public function isReadable() - { - return !$this->closed && $this->input->isReadable(); - } - - public function pause() - { - $this->input->pause(); - } - - public function resume() - { - $this->input->resume(); - } - - public function pipe(WritableStreamInterface $dest, array $options = array()) - { - Util::pipe($this, $dest, $options); - - return $dest; - } - - public function close() - { - if ($this->closed) { - return; - } - - $this->closed = true; - - $this->input->close(); - - $this->emit('close'); - $this->removeAllListeners(); - } - - public function getSize() - { - return $this->size; - } - - /** @ignore */ - public function __toString() - { - return ''; - } - - /** @ignore */ - public function detach() - { - return null; - } - - /** @ignore */ - public function tell() - { - throw new \BadMethodCallException(); - } - - /** @ignore */ - public function eof() - { - throw new \BadMethodCallException(); - } - - /** @ignore */ - public function isSeekable() - { - return false; - } - - /** @ignore */ - public function seek($offset, $whence = SEEK_SET) - { - throw new \BadMethodCallException(); - } - - /** @ignore */ - public function rewind() - { - throw new \BadMethodCallException(); - } - - /** @ignore */ - public function isWritable() - { - return false; - } - - /** @ignore */ - public function write($string) - { - throw new \BadMethodCallException(); - } - - /** @ignore */ - public function read($length) - { - throw new \BadMethodCallException(); - } - - /** @ignore */ - public function getContents() - { - return ''; - } - - /** @ignore */ - public function getMetadata($key = null) - { - return null; - } - - /** @internal */ - public function handleData($data) - { - $this->emit('data', array($data)); - } - - /** @internal */ - public function handleError(\Exception $e) - { - $this->emit('error', array($e)); - $this->close(); - } - - /** @internal */ - public function handleEnd() - { - if (!$this->closed) { - $this->emit('end'); - $this->close(); - } - } -} diff --git a/digital_doctor/vendor/react/http/src/Io/IniUtil.php b/digital_doctor/vendor/react/http/src/Io/IniUtil.php deleted file mode 100644 index 612aae2..0000000 --- a/digital_doctor/vendor/react/http/src/Io/IniUtil.php +++ /dev/null @@ -1,48 +0,0 @@ -stream = $stream; - $this->maxLength = $maxLength; - - $this->stream->on('data', array($this, 'handleData')); - $this->stream->on('end', array($this, 'handleEnd')); - $this->stream->on('error', array($this, 'handleError')); - $this->stream->on('close', array($this, 'close')); - } - - public function isReadable() - { - return !$this->closed && $this->stream->isReadable(); - } - - public function pause() - { - $this->stream->pause(); - } - - public function resume() - { - $this->stream->resume(); - } - - public function pipe(WritableStreamInterface $dest, array $options = array()) - { - Util::pipe($this, $dest, $options); - - return $dest; - } - - public function close() - { - if ($this->closed) { - return; - } - - $this->closed = true; - - $this->stream->close(); - - $this->emit('close'); - $this->removeAllListeners(); - } - - /** @internal */ - public function handleData($data) - { - if (($this->transferredLength + \strlen($data)) > $this->maxLength) { - // Only emit data until the value of 'Content-Length' is reached, the rest will be ignored - $data = (string)\substr($data, 0, $this->maxLength - $this->transferredLength); - } - - if ($data !== '') { - $this->transferredLength += \strlen($data); - $this->emit('data', array($data)); - } - - if ($this->transferredLength === $this->maxLength) { - // 'Content-Length' reached, stream will end - $this->emit('end'); - $this->close(); - $this->stream->removeListener('data', array($this, 'handleData')); - } - } - - /** @internal */ - public function handleError(\Exception $e) - { - $this->emit('error', array($e)); - $this->close(); - } - - /** @internal */ - public function handleEnd() - { - if (!$this->closed) { - $this->handleError(new \Exception('Unexpected end event')); - } - } - -} diff --git a/digital_doctor/vendor/react/http/src/Io/MiddlewareRunner.php b/digital_doctor/vendor/react/http/src/Io/MiddlewareRunner.php deleted file mode 100644 index dedf6ff..0000000 --- a/digital_doctor/vendor/react/http/src/Io/MiddlewareRunner.php +++ /dev/null @@ -1,61 +0,0 @@ -middleware = \array_values($middleware); - } - - /** - * @param ServerRequestInterface $request - * @return ResponseInterface|PromiseInterface - * @throws \Exception - */ - public function __invoke(ServerRequestInterface $request) - { - if (empty($this->middleware)) { - throw new \RuntimeException('No middleware to run'); - } - - return $this->call($request, 0); - } - - /** @internal */ - public function call(ServerRequestInterface $request, $position) - { - // final request handler will be invoked without a next handler - if (!isset($this->middleware[$position + 1])) { - $handler = $this->middleware[$position]; - return $handler($request); - } - - $that = $this; - $next = function (ServerRequestInterface $request) use ($that, $position) { - return $that->call($request, $position + 1); - }; - - // invoke middleware request handler with next handler - $handler = $this->middleware[$position]; - return $handler($request, $next); - } -} diff --git a/digital_doctor/vendor/react/http/src/Io/MultipartParser.php b/digital_doctor/vendor/react/http/src/Io/MultipartParser.php deleted file mode 100644 index 539107a..0000000 --- a/digital_doctor/vendor/react/http/src/Io/MultipartParser.php +++ /dev/null @@ -1,345 +0,0 @@ -maxInputVars = (int)$var; - } - $var = \ini_get('max_input_nesting_level'); - if ($var !== false) { - $this->maxInputNestingLevel = (int)$var; - } - - if ($uploadMaxFilesize === null) { - $uploadMaxFilesize = \ini_get('upload_max_filesize'); - } - - $this->uploadMaxFilesize = IniUtil::iniSizeToBytes($uploadMaxFilesize); - $this->maxFileUploads = $maxFileUploads === null ? (\ini_get('file_uploads') === '' ? 0 : (int)\ini_get('max_file_uploads')) : (int)$maxFileUploads; - - $this->maxMultipartBodyParts = $this->maxInputVars + $this->maxFileUploads; - } - - public function parse(ServerRequestInterface $request) - { - $contentType = $request->getHeaderLine('content-type'); - if(!\preg_match('/boundary="?(.*?)"?$/', $contentType, $matches)) { - return $request; - } - - $this->request = $request; - $this->parseBody('--' . $matches[1], (string)$request->getBody()); - - $request = $this->request; - $this->request = null; - $this->multipartBodyPartCount = 0; - $this->cursor = 0; - $this->postCount = 0; - $this->filesCount = 0; - $this->emptyCount = 0; - $this->maxFileSize = null; - - return $request; - } - - private function parseBody($boundary, $buffer) - { - $len = \strlen($boundary); - - // ignore everything before initial boundary (SHOULD be empty) - $this->cursor = \strpos($buffer, $boundary . "\r\n"); - - while ($this->cursor !== false) { - // search following boundary (preceded by newline) - // ignore last if not followed by boundary (SHOULD end with "--") - $this->cursor += $len + 2; - $end = \strpos($buffer, "\r\n" . $boundary, $this->cursor); - if ($end === false) { - break; - } - - // parse one part and continue searching for next - $this->parsePart(\substr($buffer, $this->cursor, $end - $this->cursor)); - $this->cursor = $end; - - if (++$this->multipartBodyPartCount > $this->maxMultipartBodyParts) { - break; - } - } - } - - private function parsePart($chunk) - { - $pos = \strpos($chunk, "\r\n\r\n"); - if ($pos === false) { - return; - } - - $headers = $this->parseHeaders((string)substr($chunk, 0, $pos)); - $body = (string)\substr($chunk, $pos + 4); - - if (!isset($headers['content-disposition'])) { - return; - } - - $name = $this->getParameterFromHeader($headers['content-disposition'], 'name'); - if ($name === null) { - return; - } - - $filename = $this->getParameterFromHeader($headers['content-disposition'], 'filename'); - if ($filename !== null) { - $this->parseFile( - $name, - $filename, - isset($headers['content-type'][0]) ? $headers['content-type'][0] : null, - $body - ); - } else { - $this->parsePost($name, $body); - } - } - - private function parseFile($name, $filename, $contentType, $contents) - { - $file = $this->parseUploadedFile($filename, $contentType, $contents); - if ($file === null) { - return; - } - - $this->request = $this->request->withUploadedFiles($this->extractPost( - $this->request->getUploadedFiles(), - $name, - $file - )); - } - - private function parseUploadedFile($filename, $contentType, $contents) - { - $size = \strlen($contents); - - // no file selected (zero size and empty filename) - if ($size === 0 && $filename === '') { - // ignore excessive number of empty file uploads - if (++$this->emptyCount + $this->filesCount > $this->maxInputVars) { - return; - } - - return new UploadedFile( - new BufferedBody(''), - $size, - \UPLOAD_ERR_NO_FILE, - $filename, - $contentType - ); - } - - // ignore excessive number of file uploads - if (++$this->filesCount > $this->maxFileUploads) { - return; - } - - // file exceeds "upload_max_filesize" ini setting - if ($size > $this->uploadMaxFilesize) { - return new UploadedFile( - new BufferedBody(''), - $size, - \UPLOAD_ERR_INI_SIZE, - $filename, - $contentType - ); - } - - // file exceeds MAX_FILE_SIZE value - if ($this->maxFileSize !== null && $size > $this->maxFileSize) { - return new UploadedFile( - new BufferedBody(''), - $size, - \UPLOAD_ERR_FORM_SIZE, - $filename, - $contentType - ); - } - - return new UploadedFile( - new BufferedBody($contents), - $size, - \UPLOAD_ERR_OK, - $filename, - $contentType - ); - } - - private function parsePost($name, $value) - { - // ignore excessive number of post fields - if (++$this->postCount > $this->maxInputVars) { - return; - } - - $this->request = $this->request->withParsedBody($this->extractPost( - $this->request->getParsedBody(), - $name, - $value - )); - - if (\strtoupper($name) === 'MAX_FILE_SIZE') { - $this->maxFileSize = (int)$value; - - if ($this->maxFileSize === 0) { - $this->maxFileSize = null; - } - } - } - - private function parseHeaders($header) - { - $headers = array(); - - foreach (\explode("\r\n", \trim($header)) as $line) { - $parts = \explode(':', $line, 2); - if (!isset($parts[1])) { - continue; - } - - $key = \strtolower(trim($parts[0])); - $values = \explode(';', $parts[1]); - $values = \array_map('trim', $values); - $headers[$key] = $values; - } - - return $headers; - } - - private function getParameterFromHeader(array $header, $parameter) - { - foreach ($header as $part) { - if (\preg_match('/' . $parameter . '="?(.*?)"?$/', $part, $matches)) { - return $matches[1]; - } - } - - return null; - } - - private function extractPost($postFields, $key, $value) - { - $chunks = \explode('[', $key); - if (\count($chunks) == 1) { - $postFields[$key] = $value; - return $postFields; - } - - // ignore this key if maximum nesting level is exceeded - if (isset($chunks[$this->maxInputNestingLevel])) { - return $postFields; - } - - $chunkKey = \rtrim($chunks[0], ']'); - $parent = &$postFields; - for ($i = 1; isset($chunks[$i]); $i++) { - $previousChunkKey = $chunkKey; - - if ($previousChunkKey === '') { - $parent[] = array(); - \end($parent); - $parent = &$parent[\key($parent)]; - } else { - if (!isset($parent[$previousChunkKey]) || !\is_array($parent[$previousChunkKey])) { - $parent[$previousChunkKey] = array(); - } - $parent = &$parent[$previousChunkKey]; - } - - $chunkKey = \rtrim($chunks[$i], ']'); - } - - if ($chunkKey === '') { - $parent[] = $value; - } else { - $parent[$chunkKey] = $value; - } - - return $postFields; - } -} diff --git a/digital_doctor/vendor/react/http/src/Io/PauseBufferStream.php b/digital_doctor/vendor/react/http/src/Io/PauseBufferStream.php deleted file mode 100644 index fb5ed45..0000000 --- a/digital_doctor/vendor/react/http/src/Io/PauseBufferStream.php +++ /dev/null @@ -1,188 +0,0 @@ -input = $input; - - $this->input->on('data', array($this, 'handleData')); - $this->input->on('end', array($this, 'handleEnd')); - $this->input->on('error', array($this, 'handleError')); - $this->input->on('close', array($this, 'handleClose')); - } - - /** - * pause and remember this was not explicitly from user control - * - * @internal - */ - public function pauseImplicit() - { - $this->pause(); - $this->implicit = true; - } - - /** - * resume only if this was previously paused implicitly and not explicitly from user control - * - * @internal - */ - public function resumeImplicit() - { - if ($this->implicit) { - $this->resume(); - } - } - - public function isReadable() - { - return !$this->closed; - } - - public function pause() - { - if ($this->closed) { - return; - } - - $this->input->pause(); - $this->paused = true; - $this->implicit = false; - } - - public function resume() - { - if ($this->closed) { - return; - } - - $this->paused = false; - $this->implicit = false; - - if ($this->dataPaused !== '') { - $this->emit('data', array($this->dataPaused)); - $this->dataPaused = ''; - } - - if ($this->errorPaused) { - $this->emit('error', array($this->errorPaused)); - return $this->close(); - } - - if ($this->endPaused) { - $this->endPaused = false; - $this->emit('end'); - return $this->close(); - } - - if ($this->closePaused) { - $this->closePaused = false; - return $this->close(); - } - - $this->input->resume(); - } - - public function pipe(WritableStreamInterface $dest, array $options = array()) - { - Util::pipe($this, $dest, $options); - - return $dest; - } - - public function close() - { - if ($this->closed) { - return; - } - - $this->closed = true; - $this->dataPaused = ''; - $this->endPaused = $this->closePaused = false; - $this->errorPaused = null; - - $this->input->close(); - - $this->emit('close'); - $this->removeAllListeners(); - } - - /** @internal */ - public function handleData($data) - { - if ($this->paused) { - $this->dataPaused .= $data; - return; - } - - $this->emit('data', array($data)); - } - - /** @internal */ - public function handleError(\Exception $e) - { - if ($this->paused) { - $this->errorPaused = $e; - return; - } - - $this->emit('error', array($e)); - $this->close(); - } - - /** @internal */ - public function handleEnd() - { - if ($this->paused) { - $this->endPaused = true; - return; - } - - if (!$this->closed) { - $this->emit('end'); - $this->close(); - } - } - - /** @internal */ - public function handleClose() - { - if ($this->paused) { - $this->closePaused = true; - return; - } - - $this->close(); - } -} diff --git a/digital_doctor/vendor/react/http/src/Io/ReadableBodyStream.php b/digital_doctor/vendor/react/http/src/Io/ReadableBodyStream.php deleted file mode 100644 index daef45f..0000000 --- a/digital_doctor/vendor/react/http/src/Io/ReadableBodyStream.php +++ /dev/null @@ -1,153 +0,0 @@ -input = $input; - $this->size = $size; - - $that = $this; - $pos =& $this->position; - $input->on('data', function ($data) use ($that, &$pos, $size) { - $that->emit('data', array($data)); - - $pos += \strlen($data); - if ($size !== null && $pos >= $size) { - $that->handleEnd(); - } - }); - $input->on('error', function ($error) use ($that) { - $that->emit('error', array($error)); - $that->close(); - }); - $input->on('end', array($that, 'handleEnd')); - $input->on('close', array($that, 'close')); - } - - public function close() - { - if (!$this->closed) { - $this->closed = true; - $this->input->close(); - - $this->emit('close'); - $this->removeAllListeners(); - } - } - - public function isReadable() - { - return $this->input->isReadable(); - } - - public function pause() - { - $this->input->pause(); - } - - public function resume() - { - $this->input->resume(); - } - - public function pipe(WritableStreamInterface $dest, array $options = array()) - { - Util::pipe($this, $dest, $options); - - return $dest; - } - - public function eof() - { - return !$this->isReadable(); - } - - public function __toString() - { - return ''; - } - - public function detach() - { - throw new \BadMethodCallException(); - } - - public function getSize() - { - return $this->size; - } - - public function tell() - { - throw new \BadMethodCallException(); - } - - public function isSeekable() - { - return false; - } - - public function seek($offset, $whence = SEEK_SET) - { - throw new \BadMethodCallException(); - } - - public function rewind() - { - throw new \BadMethodCallException(); - } - - public function isWritable() - { - return false; - } - - public function write($string) - { - throw new \BadMethodCallException(); - } - - public function read($length) - { - throw new \BadMethodCallException(); - } - - public function getContents() - { - throw new \BadMethodCallException(); - } - - public function getMetadata($key = null) - { - return ($key === null) ? array() : null; - } - - /** @internal */ - public function handleEnd() - { - if ($this->position !== $this->size && $this->size !== null) { - $this->emit('error', array(new \UnderflowException('Unexpected end of response body after ' . $this->position . '/' . $this->size . ' bytes'))); - } else { - $this->emit('end'); - } - - $this->close(); - } -} diff --git a/digital_doctor/vendor/react/http/src/Io/RequestHeaderParser.php b/digital_doctor/vendor/react/http/src/Io/RequestHeaderParser.php deleted file mode 100644 index 8975ce5..0000000 --- a/digital_doctor/vendor/react/http/src/Io/RequestHeaderParser.php +++ /dev/null @@ -1,179 +0,0 @@ -> */ - private $connectionParams = array(); - - public function __construct(Clock $clock) - { - $this->clock = $clock; - } - - public function handle(ConnectionInterface $conn) - { - $buffer = ''; - $maxSize = $this->maxSize; - $that = $this; - $conn->on('data', $fn = function ($data) use (&$buffer, &$fn, $conn, $maxSize, $that) { - // append chunk of data to buffer and look for end of request headers - $buffer .= $data; - $endOfHeader = \strpos($buffer, "\r\n\r\n"); - - // reject request if buffer size is exceeded - if ($endOfHeader > $maxSize || ($endOfHeader === false && isset($buffer[$maxSize]))) { - $conn->removeListener('data', $fn); - $fn = null; - - $that->emit('error', array( - new \OverflowException("Maximum header size of {$maxSize} exceeded.", Response::STATUS_REQUEST_HEADER_FIELDS_TOO_LARGE), - $conn - )); - return; - } - - // ignore incomplete requests - if ($endOfHeader === false) { - return; - } - - // request headers received => try to parse request - $conn->removeListener('data', $fn); - $fn = null; - - try { - $request = $that->parseRequest( - (string)\substr($buffer, 0, $endOfHeader + 2), - $conn - ); - } catch (Exception $exception) { - $buffer = ''; - $that->emit('error', array( - $exception, - $conn - )); - return; - } - - $contentLength = 0; - if ($request->hasHeader('Transfer-Encoding')) { - $contentLength = null; - } elseif ($request->hasHeader('Content-Length')) { - $contentLength = (int)$request->getHeaderLine('Content-Length'); - } - - if ($contentLength === 0) { - // happy path: request body is known to be empty - $stream = new EmptyBodyStream(); - $request = $request->withBody($stream); - } else { - // otherwise body is present => delimit using Content-Length or ChunkedDecoder - $stream = new CloseProtectionStream($conn); - if ($contentLength !== null) { - $stream = new LengthLimitedStream($stream, $contentLength); - } else { - $stream = new ChunkedDecoder($stream); - } - - $request = $request->withBody(new HttpBodyStream($stream, $contentLength)); - } - - $bodyBuffer = isset($buffer[$endOfHeader + 4]) ? \substr($buffer, $endOfHeader + 4) : ''; - $buffer = ''; - $that->emit('headers', array($request, $conn)); - - if ($bodyBuffer !== '') { - $conn->emit('data', array($bodyBuffer)); - } - - // happy path: request body is known to be empty => immediately end stream - if ($contentLength === 0) { - $stream->emit('end'); - $stream->close(); - } - }); - } - - /** - * @param string $headers buffer string containing request headers only - * @param ConnectionInterface $connection - * @return ServerRequestInterface - * @throws \InvalidArgumentException - * @internal - */ - public function parseRequest($headers, ConnectionInterface $connection) - { - // reuse same connection params for all server params for this connection - $cid = \PHP_VERSION_ID < 70200 ? \spl_object_hash($connection) : \spl_object_id($connection); - if (isset($this->connectionParams[$cid])) { - $serverParams = $this->connectionParams[$cid]; - } else { - // assign new server params for new connection - $serverParams = array(); - - // scheme is `http` unless TLS is used - $localSocketUri = $connection->getLocalAddress(); - $localParts = $localSocketUri === null ? array() : \parse_url($localSocketUri); - if (isset($localParts['scheme']) && $localParts['scheme'] === 'tls') { - $serverParams['HTTPS'] = 'on'; - } - - // apply SERVER_ADDR and SERVER_PORT if server address is known - // address should always be known, even for Unix domain sockets (UDS) - // but skip UDS as it doesn't have a concept of host/port. - if ($localSocketUri !== null && isset($localParts['host'], $localParts['port'])) { - $serverParams['SERVER_ADDR'] = $localParts['host']; - $serverParams['SERVER_PORT'] = $localParts['port']; - } - - // apply REMOTE_ADDR and REMOTE_PORT if source address is known - // address should always be known, unless this is over Unix domain sockets (UDS) - $remoteSocketUri = $connection->getRemoteAddress(); - if ($remoteSocketUri !== null) { - $remoteAddress = \parse_url($remoteSocketUri); - $serverParams['REMOTE_ADDR'] = $remoteAddress['host']; - $serverParams['REMOTE_PORT'] = $remoteAddress['port']; - } - - // remember server params for all requests from this connection, reset on connection close - $this->connectionParams[$cid] = $serverParams; - $params =& $this->connectionParams; - $connection->on('close', function () use (&$params, $cid) { - assert(\is_array($params)); - unset($params[$cid]); - }); - } - - // create new obj implementing ServerRequestInterface by preserving all - // previous properties and restoring original request-target - $serverParams['REQUEST_TIME'] = (int) ($now = $this->clock->now()); - $serverParams['REQUEST_TIME_FLOAT'] = $now; - - return ServerRequest::parseMessage($headers, $serverParams); - } -} diff --git a/digital_doctor/vendor/react/http/src/Io/Sender.php b/digital_doctor/vendor/react/http/src/Io/Sender.php deleted file mode 100644 index 1d56389..0000000 --- a/digital_doctor/vendor/react/http/src/Io/Sender.php +++ /dev/null @@ -1,157 +0,0 @@ -http = $http; - } - - /** - * - * @internal - * @param RequestInterface $request - * @return PromiseInterface Promise - */ - public function send(RequestInterface $request) - { - // support HTTP/1.1 and HTTP/1.0 only, ensured by `Browser` already - assert(\in_array($request->getProtocolVersion(), array('1.0', '1.1'), true)); - - $body = $request->getBody(); - $size = $body->getSize(); - - if ($size !== null && $size !== 0) { - // automatically assign a "Content-Length" request header if the body size is known and non-empty - $request = $request->withHeader('Content-Length', (string)$size); - } elseif ($size === 0 && \in_array($request->getMethod(), array('POST', 'PUT', 'PATCH'))) { - // only assign a "Content-Length: 0" request header if the body is expected for certain methods - $request = $request->withHeader('Content-Length', '0'); - } elseif ($body instanceof ReadableStreamInterface && $size !== 0 && $body->isReadable() && !$request->hasHeader('Content-Length')) { - // use "Transfer-Encoding: chunked" when this is a streaming body and body size is unknown - $request = $request->withHeader('Transfer-Encoding', 'chunked'); - } else { - // do not use chunked encoding if size is known or if this is an empty request body - $size = 0; - } - - // automatically add `Authorization: Basic …` request header if URL includes `user:pass@host` - if ($request->getUri()->getUserInfo() !== '' && !$request->hasHeader('Authorization')) { - $request = $request->withHeader('Authorization', 'Basic ' . \base64_encode($request->getUri()->getUserInfo())); - } - - $requestStream = $this->http->request($request); - - $deferred = new Deferred(function ($_, $reject) use ($requestStream) { - // close request stream if request is cancelled - $reject(new \RuntimeException('Request cancelled')); - $requestStream->close(); - }); - - $requestStream->on('error', function($error) use ($deferred) { - $deferred->reject($error); - }); - - $requestStream->on('response', function (ResponseInterface $response) use ($deferred, $request) { - $deferred->resolve($response); - }); - - if ($body instanceof ReadableStreamInterface) { - if ($body->isReadable()) { - // length unknown => apply chunked transfer-encoding - if ($size === null) { - $body = new ChunkedEncoder($body); - } - - // pipe body into request stream - // add dummy write to immediately start request even if body does not emit any data yet - $body->pipe($requestStream); - $requestStream->write(''); - - $body->on('close', $close = function () use ($deferred, $requestStream) { - $deferred->reject(new \RuntimeException('Request failed because request body closed unexpectedly')); - $requestStream->close(); - }); - $body->on('error', function ($e) use ($deferred, $requestStream, $close, $body) { - $body->removeListener('close', $close); - $deferred->reject(new \RuntimeException('Request failed because request body reported an error', 0, $e)); - $requestStream->close(); - }); - $body->on('end', function () use ($close, $body) { - $body->removeListener('close', $close); - }); - } else { - // stream is not readable => end request without body - $requestStream->end(); - } - } else { - // body is fully buffered => write as one chunk - $requestStream->end((string)$body); - } - - return $deferred->promise(); - } -} diff --git a/digital_doctor/vendor/react/http/src/Io/StreamingServer.php b/digital_doctor/vendor/react/http/src/Io/StreamingServer.php deleted file mode 100644 index 143edaa..0000000 --- a/digital_doctor/vendor/react/http/src/Io/StreamingServer.php +++ /dev/null @@ -1,405 +0,0 @@ - 'text/plain' - * ), - * "Hello World!\n" - * ); - * }); - * ``` - * - * Each incoming HTTP request message is always represented by the - * [PSR-7 `ServerRequestInterface`](https://www.php-fig.org/psr/psr-7/#321-psrhttpmessageserverrequestinterface), - * see also following [request](#request) chapter for more details. - * Each outgoing HTTP response message is always represented by the - * [PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface), - * see also following [response](#response) chapter for more details. - * - * In order to process any connections, the server needs to be attached to an - * instance of `React\Socket\ServerInterface` through the [`listen()`](#listen) method - * as described in the following chapter. In its most simple form, you can attach - * this to a [`React\Socket\SocketServer`](https://github.com/reactphp/socket#socketserver) - * in order to start a plaintext HTTP server like this: - * - * ```php - * $server = new StreamingServer($loop, $handler); - * - * $socket = new React\Socket\SocketServer('0.0.0.0:8080', array(), $loop); - * $server->listen($socket); - * ``` - * - * See also the [`listen()`](#listen) method and the [first example](examples) for more details. - * - * The `StreamingServer` class is considered advanced usage and unless you know - * what you're doing, you're recommended to use the [`HttpServer`](#httpserver) class - * instead. The `StreamingServer` class is specifically designed to help with - * more advanced use cases where you want to have full control over consuming - * the incoming HTTP request body and concurrency settings. - * - * In particular, this class does not buffer and parse the incoming HTTP request - * in memory. It will invoke the request handler function once the HTTP request - * headers have been received, i.e. before receiving the potentially much larger - * HTTP request body. This means the [request](#request) passed to your request - * handler function may not be fully compatible with PSR-7. See also - * [streaming request](#streaming-request) below for more details. - * - * @see \React\Http\HttpServer - * @see \React\Http\Message\Response - * @see self::listen() - * @internal - */ -final class StreamingServer extends EventEmitter -{ - private $callback; - private $parser; - - /** @var Clock */ - private $clock; - - /** - * Creates an HTTP server that invokes the given callback for each incoming HTTP request - * - * In order to process any connections, the server needs to be attached to an - * instance of `React\Socket\ServerInterface` which emits underlying streaming - * connections in order to then parse incoming data as HTTP. - * See also [listen()](#listen) for more details. - * - * @param LoopInterface $loop - * @param callable $requestHandler - * @see self::listen() - */ - public function __construct(LoopInterface $loop, $requestHandler) - { - if (!\is_callable($requestHandler)) { - throw new \InvalidArgumentException('Invalid request handler given'); - } - - $this->callback = $requestHandler; - $this->clock = new Clock($loop); - $this->parser = new RequestHeaderParser($this->clock); - - $that = $this; - $this->parser->on('headers', function (ServerRequestInterface $request, ConnectionInterface $conn) use ($that) { - $that->handleRequest($conn, $request); - }); - - $this->parser->on('error', function(\Exception $e, ConnectionInterface $conn) use ($that) { - $that->emit('error', array($e)); - - // parsing failed => assume dummy request and send appropriate error - $that->writeError( - $conn, - $e->getCode() !== 0 ? $e->getCode() : Response::STATUS_BAD_REQUEST, - new ServerRequest('GET', '/') - ); - }); - } - - /** - * Starts listening for HTTP requests on the given socket server instance - * - * @param ServerInterface $socket - * @see \React\Http\HttpServer::listen() - */ - public function listen(ServerInterface $socket) - { - $socket->on('connection', array($this->parser, 'handle')); - } - - /** @internal */ - public function handleRequest(ConnectionInterface $conn, ServerRequestInterface $request) - { - if ($request->getProtocolVersion() !== '1.0' && '100-continue' === \strtolower($request->getHeaderLine('Expect'))) { - $conn->write("HTTP/1.1 100 Continue\r\n\r\n"); - } - - // execute request handler callback - $callback = $this->callback; - try { - $response = $callback($request); - } catch (\Exception $error) { - // request handler callback throws an Exception - $response = Promise\reject($error); - } catch (\Throwable $error) { // @codeCoverageIgnoreStart - // request handler callback throws a PHP7+ Error - $response = Promise\reject($error); // @codeCoverageIgnoreEnd - } - - // cancel pending promise once connection closes - $connectionOnCloseResponseCancelerHandler = function () {}; - if ($response instanceof PromiseInterface && \method_exists($response, 'cancel')) { - $connectionOnCloseResponseCanceler = function () use ($response) { - $response->cancel(); - }; - $connectionOnCloseResponseCancelerHandler = function () use ($connectionOnCloseResponseCanceler, $conn) { - if ($connectionOnCloseResponseCanceler !== null) { - $conn->removeListener('close', $connectionOnCloseResponseCanceler); - } - }; - $conn->on('close', $connectionOnCloseResponseCanceler); - } - - // happy path: response returned, handle and return immediately - if ($response instanceof ResponseInterface) { - return $this->handleResponse($conn, $request, $response); - } - - // did not return a promise? this is an error, convert into one for rejection below. - if (!$response instanceof PromiseInterface) { - $response = Promise\resolve($response); - } - - $that = $this; - $response->then( - function ($response) use ($that, $conn, $request) { - if (!$response instanceof ResponseInterface) { - $message = 'The response callback is expected to resolve with an object implementing Psr\Http\Message\ResponseInterface, but resolved with "%s" instead.'; - $message = \sprintf($message, \is_object($response) ? \get_class($response) : \gettype($response)); - $exception = new \RuntimeException($message); - - $that->emit('error', array($exception)); - return $that->writeError($conn, Response::STATUS_INTERNAL_SERVER_ERROR, $request); - } - $that->handleResponse($conn, $request, $response); - }, - function ($error) use ($that, $conn, $request) { - $message = 'The response callback is expected to resolve with an object implementing Psr\Http\Message\ResponseInterface, but rejected with "%s" instead.'; - $message = \sprintf($message, \is_object($error) ? \get_class($error) : \gettype($error)); - - $previous = null; - - if ($error instanceof \Throwable || $error instanceof \Exception) { - $previous = $error; - } - - $exception = new \RuntimeException($message, 0, $previous); - - $that->emit('error', array($exception)); - return $that->writeError($conn, Response::STATUS_INTERNAL_SERVER_ERROR, $request); - } - )->then($connectionOnCloseResponseCancelerHandler, $connectionOnCloseResponseCancelerHandler); - } - - /** @internal */ - public function writeError(ConnectionInterface $conn, $code, ServerRequestInterface $request) - { - $response = new Response( - $code, - array( - 'Content-Type' => 'text/plain', - 'Connection' => 'close' // we do not want to keep the connection open after an error - ), - 'Error ' . $code - ); - - // append reason phrase to response body if known - $reason = $response->getReasonPhrase(); - if ($reason !== '') { - $body = $response->getBody(); - $body->seek(0, SEEK_END); - $body->write(': ' . $reason); - } - - $this->handleResponse($conn, $request, $response); - } - - - /** @internal */ - public function handleResponse(ConnectionInterface $connection, ServerRequestInterface $request, ResponseInterface $response) - { - // return early and close response body if connection is already closed - $body = $response->getBody(); - if (!$connection->isWritable()) { - $body->close(); - return; - } - - $code = $response->getStatusCode(); - $method = $request->getMethod(); - - // assign HTTP protocol version from request automatically - $version = $request->getProtocolVersion(); - $response = $response->withProtocolVersion($version); - - // assign default "Server" header automatically - if (!$response->hasHeader('Server')) { - $response = $response->withHeader('Server', 'ReactPHP/1'); - } elseif ($response->getHeaderLine('Server') === ''){ - $response = $response->withoutHeader('Server'); - } - - // assign default "Date" header from current time automatically - if (!$response->hasHeader('Date')) { - // IMF-fixdate = day-name "," SP date1 SP time-of-day SP GMT - $response = $response->withHeader('Date', gmdate('D, d M Y H:i:s', (int) $this->clock->now()) . ' GMT'); - } elseif ($response->getHeaderLine('Date') === ''){ - $response = $response->withoutHeader('Date'); - } - - // assign "Content-Length" header automatically - $chunked = false; - if (($method === 'CONNECT' && $code >= 200 && $code < 300) || ($code >= 100 && $code < 200) || $code === Response::STATUS_NO_CONTENT) { - // 2xx response to CONNECT and 1xx and 204 MUST NOT include Content-Length or Transfer-Encoding header - $response = $response->withoutHeader('Content-Length'); - } elseif ($method === 'HEAD' && $response->hasHeader('Content-Length')) { - // HEAD Request: preserve explicit Content-Length - } elseif ($code === Response::STATUS_NOT_MODIFIED && ($response->hasHeader('Content-Length') || $body->getSize() === 0)) { - // 304 Not Modified: preserve explicit Content-Length and preserve missing header if body is empty - } elseif ($body->getSize() !== null) { - // assign Content-Length header when using a "normal" buffered body string - $response = $response->withHeader('Content-Length', (string)$body->getSize()); - } elseif (!$response->hasHeader('Content-Length') && $version === '1.1') { - // assign chunked transfer-encoding if no 'content-length' is given for HTTP/1.1 responses - $chunked = true; - } - - // assign "Transfer-Encoding" header automatically - if ($chunked) { - $response = $response->withHeader('Transfer-Encoding', 'chunked'); - } else { - // remove any Transfer-Encoding headers unless automatically enabled above - $response = $response->withoutHeader('Transfer-Encoding'); - } - - // assign "Connection" header automatically - $persist = false; - if ($code === Response::STATUS_SWITCHING_PROTOCOLS) { - // 101 (Switching Protocols) response uses Connection: upgrade header - // This implies that this stream now uses another protocol and we - // may not persist this connection for additional requests. - $response = $response->withHeader('Connection', 'upgrade'); - } elseif (\strtolower($request->getHeaderLine('Connection')) === 'close' || \strtolower($response->getHeaderLine('Connection')) === 'close') { - // obey explicit "Connection: close" request header or response header if present - $response = $response->withHeader('Connection', 'close'); - } elseif ($version === '1.1') { - // HTTP/1.1 assumes persistent connection support by default, so we don't need to inform client - $persist = true; - } elseif (strtolower($request->getHeaderLine('Connection')) === 'keep-alive') { - // obey explicit "Connection: keep-alive" request header and inform client - $persist = true; - $response = $response->withHeader('Connection', 'keep-alive'); - } else { - // remove any Connection headers unless automatically enabled above - $response = $response->withoutHeader('Connection'); - } - - // 101 (Switching Protocols) response (for Upgrade request) forwards upgraded data through duplex stream - // 2xx (Successful) response to CONNECT forwards tunneled application data through duplex stream - if (($code === Response::STATUS_SWITCHING_PROTOCOLS || ($method === 'CONNECT' && $code >= 200 && $code < 300)) && $body instanceof HttpBodyStream && $body->input instanceof WritableStreamInterface) { - if ($request->getBody()->isReadable()) { - // request is still streaming => wait for request close before forwarding following data from connection - $request->getBody()->on('close', function () use ($connection, $body) { - if ($body->input->isWritable()) { - $connection->pipe($body->input); - $connection->resume(); - } - }); - } elseif ($body->input->isWritable()) { - // request already closed => forward following data from connection - $connection->pipe($body->input); - $connection->resume(); - } - } - - // build HTTP response header by appending status line and header fields - $expected = 0; - $headers = "HTTP/" . $version . " " . $code . " " . $response->getReasonPhrase() . "\r\n"; - foreach ($response->getHeaders() as $name => $values) { - if (\strpos($name, ':') !== false) { - $expected = -1; - break; - } - foreach ($values as $value) { - $headers .= $name . ": " . $value . "\r\n"; - ++$expected; - } - } - - /** @var array $m legacy PHP 5.3 only */ - if ($code < 100 || $code > 999 || \substr_count($headers, "\n") !== ($expected + 1) || (\PHP_VERSION_ID >= 50400 ? \preg_match_all(AbstractMessage::REGEX_HEADERS, $headers) : \preg_match_all(AbstractMessage::REGEX_HEADERS, $headers, $m)) !== $expected) { - $this->emit('error', array(new \InvalidArgumentException('Unable to send response with invalid response headers'))); - $this->writeError($connection, Response::STATUS_INTERNAL_SERVER_ERROR, $request); - return; - } - - // response to HEAD and 1xx, 204 and 304 responses MUST NOT include a body - // exclude status 101 (Switching Protocols) here for Upgrade request handling above - if ($method === 'HEAD' || ($code >= 100 && $code < 200 && $code !== Response::STATUS_SWITCHING_PROTOCOLS) || $code === Response::STATUS_NO_CONTENT || $code === Response::STATUS_NOT_MODIFIED) { - $body->close(); - $body = ''; - } - - // this is a non-streaming response body or the body stream already closed? - if (!$body instanceof ReadableStreamInterface || !$body->isReadable()) { - // add final chunk if a streaming body is already closed and uses `Transfer-Encoding: chunked` - if ($body instanceof ReadableStreamInterface && $chunked) { - $body = "0\r\n\r\n"; - } - - // write response headers and body - $connection->write($headers . "\r\n" . $body); - - // either wait for next request over persistent connection or end connection - if ($persist) { - $this->parser->handle($connection); - } else { - $connection->end(); - } - return; - } - - $connection->write($headers . "\r\n"); - - if ($chunked) { - $body = new ChunkedEncoder($body); - } - - // Close response stream once connection closes. - // Note that this TCP/IP close detection may take some time, - // in particular this may only fire on a later read/write attempt. - $connection->on('close', array($body, 'close')); - - // write streaming body and then wait for next request over persistent connection - if ($persist) { - $body->pipe($connection, array('end' => false)); - $parser = $this->parser; - $body->on('end', function () use ($connection, $parser, $body) { - $connection->removeListener('close', array($body, 'close')); - $parser->handle($connection); - }); - } else { - $body->pipe($connection); - } - } -} diff --git a/digital_doctor/vendor/react/http/src/Io/Transaction.php b/digital_doctor/vendor/react/http/src/Io/Transaction.php deleted file mode 100644 index 64738f5..0000000 --- a/digital_doctor/vendor/react/http/src/Io/Transaction.php +++ /dev/null @@ -1,330 +0,0 @@ -sender = $sender; - $this->loop = $loop; - } - - /** - * @param array $options - * @return self returns new instance, without modifying existing instance - */ - public function withOptions(array $options) - { - $transaction = clone $this; - foreach ($options as $name => $value) { - if (property_exists($transaction, $name)) { - // restore default value if null is given - if ($value === null) { - $default = new self($this->sender, $this->loop); - $value = $default->$name; - } - - $transaction->$name = $value; - } - } - - return $transaction; - } - - public function send(RequestInterface $request) - { - $state = new ClientRequestState(); - $deferred = new Deferred(function () use ($state) { - if ($state->pending !== null) { - $state->pending->cancel(); - $state->pending = null; - } - }); - - // use timeout from options or default to PHP's default_socket_timeout (60) - $timeout = (float)($this->timeout !== null ? $this->timeout : ini_get("default_socket_timeout")); - - $loop = $this->loop; - $this->next($request, $deferred, $state)->then( - function (ResponseInterface $response) use ($state, $deferred, $loop, &$timeout) { - if ($state->timeout !== null) { - $loop->cancelTimer($state->timeout); - $state->timeout = null; - } - $timeout = -1; - $deferred->resolve($response); - }, - function ($e) use ($state, $deferred, $loop, &$timeout) { - if ($state->timeout !== null) { - $loop->cancelTimer($state->timeout); - $state->timeout = null; - } - $timeout = -1; - $deferred->reject($e); - } - ); - - if ($timeout < 0) { - return $deferred->promise(); - } - - $body = $request->getBody(); - if ($body instanceof ReadableStreamInterface && $body->isReadable()) { - $that = $this; - $body->on('close', function () use ($that, $deferred, $state, &$timeout) { - if ($timeout >= 0) { - $that->applyTimeout($deferred, $state, $timeout); - } - }); - } else { - $this->applyTimeout($deferred, $state, $timeout); - } - - return $deferred->promise(); - } - - /** - * @internal - * @param number $timeout - * @return void - */ - public function applyTimeout(Deferred $deferred, ClientRequestState $state, $timeout) - { - $state->timeout = $this->loop->addTimer($timeout, function () use ($timeout, $deferred, $state) { - $deferred->reject(new \RuntimeException( - 'Request timed out after ' . $timeout . ' seconds' - )); - if ($state->pending !== null) { - $state->pending->cancel(); - $state->pending = null; - } - }); - } - - private function next(RequestInterface $request, Deferred $deferred, ClientRequestState $state) - { - $this->progress('request', array($request)); - - $that = $this; - ++$state->numRequests; - - $promise = $this->sender->send($request); - - if (!$this->streaming) { - $promise = $promise->then(function ($response) use ($deferred, $state, $that) { - return $that->bufferResponse($response, $deferred, $state); - }); - } - - $state->pending = $promise; - - return $promise->then( - function (ResponseInterface $response) use ($request, $that, $deferred, $state) { - return $that->onResponse($response, $request, $deferred, $state); - } - ); - } - - /** - * @internal - * @return PromiseInterface Promise - */ - public function bufferResponse(ResponseInterface $response, Deferred $deferred, ClientRequestState $state) - { - $body = $response->getBody(); - $size = $body->getSize(); - - if ($size !== null && $size > $this->maximumSize) { - $body->close(); - return \React\Promise\reject(new \OverflowException( - 'Response body size of ' . $size . ' bytes exceeds maximum of ' . $this->maximumSize . ' bytes', - \defined('SOCKET_EMSGSIZE') ? \SOCKET_EMSGSIZE : 90 - )); - } - - // body is not streaming => already buffered - if (!$body instanceof ReadableStreamInterface) { - return \React\Promise\resolve($response); - } - - /** @var ?\Closure $closer */ - $closer = null; - $maximumSize = $this->maximumSize; - - return $state->pending = new Promise(function ($resolve, $reject) use ($body, $maximumSize, $response, &$closer) { - // resolve with current buffer when stream closes successfully - $buffer = ''; - $body->on('close', $closer = function () use (&$buffer, $response, $maximumSize, $resolve, $reject) { - $resolve($response->withBody(new BufferedBody($buffer))); - }); - - // buffer response body data in memory - $body->on('data', function ($data) use (&$buffer, $maximumSize, $body, $closer, $reject) { - $buffer .= $data; - - // close stream and reject promise if limit is exceeded - if (isset($buffer[$maximumSize])) { - $buffer = ''; - assert($closer instanceof \Closure); - $body->removeListener('close', $closer); - $body->close(); - - $reject(new \OverflowException( - 'Response body size exceeds maximum of ' . $maximumSize . ' bytes', - \defined('SOCKET_EMSGSIZE') ? \SOCKET_EMSGSIZE : 90 - )); - } - }); - - // reject buffering if body emits error - $body->on('error', function (\Exception $e) use ($reject) { - $reject(new \RuntimeException( - 'Error while buffering response body: ' . $e->getMessage(), - $e->getCode(), - $e - )); - }); - }, function () use ($body, &$closer) { - // cancelled buffering: remove close handler to avoid resolving, then close and reject - assert($closer instanceof \Closure); - $body->removeListener('close', $closer); - $body->close(); - - throw new \RuntimeException('Cancelled buffering response body'); - }); - } - - /** - * @internal - * @throws ResponseException - * @return ResponseInterface|PromiseInterface - */ - public function onResponse(ResponseInterface $response, RequestInterface $request, Deferred $deferred, ClientRequestState $state) - { - $this->progress('response', array($response, $request)); - - // follow 3xx (Redirection) response status codes if Location header is present and not explicitly disabled - // @link https://tools.ietf.org/html/rfc7231#section-6.4 - if ($this->followRedirects && ($response->getStatusCode() >= 300 && $response->getStatusCode() < 400) && $response->hasHeader('Location')) { - return $this->onResponseRedirect($response, $request, $deferred, $state); - } - - // only status codes 200-399 are considered to be valid, reject otherwise - if ($this->obeySuccessCode && ($response->getStatusCode() < 200 || $response->getStatusCode() >= 400)) { - throw new ResponseException($response); - } - - // resolve our initial promise - return $response; - } - - /** - * @param ResponseInterface $response - * @param RequestInterface $request - * @param Deferred $deferred - * @param ClientRequestState $state - * @return PromiseInterface - * @throws \RuntimeException - */ - private function onResponseRedirect(ResponseInterface $response, RequestInterface $request, Deferred $deferred, ClientRequestState $state) - { - // resolve location relative to last request URI - $location = Uri::resolve($request->getUri(), new Uri($response->getHeaderLine('Location'))); - - $request = $this->makeRedirectRequest($request, $location, $response->getStatusCode()); - $this->progress('redirect', array($request)); - - if ($state->numRequests >= $this->maxRedirects) { - throw new \RuntimeException('Maximum number of redirects (' . $this->maxRedirects . ') exceeded'); - } - - return $this->next($request, $deferred, $state); - } - - /** - * @param RequestInterface $request - * @param UriInterface $location - * @param int $statusCode - * @return RequestInterface - * @throws \RuntimeException - */ - private function makeRedirectRequest(RequestInterface $request, UriInterface $location, $statusCode) - { - // Remove authorization if changing hostnames (but not if just changing ports or protocols). - $originalHost = $request->getUri()->getHost(); - if ($location->getHost() !== $originalHost) { - $request = $request->withoutHeader('Authorization'); - } - - $request = $request->withoutHeader('Host')->withUri($location); - - if ($statusCode === Response::STATUS_TEMPORARY_REDIRECT || $statusCode === Response::STATUS_PERMANENT_REDIRECT) { - if ($request->getBody() instanceof ReadableStreamInterface) { - throw new \RuntimeException('Unable to redirect request with streaming body'); - } - } else { - $request = $request - ->withMethod($request->getMethod() === 'HEAD' ? 'HEAD' : 'GET') - ->withoutHeader('Content-Type') - ->withoutHeader('Content-Length') - ->withBody(new BufferedBody('')); - } - - return $request; - } - - private function progress($name, array $args = array()) - { - return; - - echo $name; - - foreach ($args as $arg) { - echo ' '; - if ($arg instanceof ResponseInterface) { - echo 'HTTP/' . $arg->getProtocolVersion() . ' ' . $arg->getStatusCode() . ' ' . $arg->getReasonPhrase(); - } elseif ($arg instanceof RequestInterface) { - echo $arg->getMethod() . ' ' . $arg->getRequestTarget() . ' HTTP/' . $arg->getProtocolVersion(); - } else { - echo $arg; - } - } - - echo PHP_EOL; - } -} diff --git a/digital_doctor/vendor/react/http/src/Io/UploadedFile.php b/digital_doctor/vendor/react/http/src/Io/UploadedFile.php deleted file mode 100644 index f2a6c9e..0000000 --- a/digital_doctor/vendor/react/http/src/Io/UploadedFile.php +++ /dev/null @@ -1,130 +0,0 @@ -stream = $stream; - $this->size = $size; - - if (!\is_int($error) || !\in_array($error, array( - \UPLOAD_ERR_OK, - \UPLOAD_ERR_INI_SIZE, - \UPLOAD_ERR_FORM_SIZE, - \UPLOAD_ERR_PARTIAL, - \UPLOAD_ERR_NO_FILE, - \UPLOAD_ERR_NO_TMP_DIR, - \UPLOAD_ERR_CANT_WRITE, - \UPLOAD_ERR_EXTENSION, - ))) { - throw new InvalidArgumentException( - 'Invalid error code, must be an UPLOAD_ERR_* constant' - ); - } - $this->error = $error; - $this->filename = $filename; - $this->mediaType = $mediaType; - } - - /** - * {@inheritdoc} - */ - public function getStream() - { - if ($this->error !== \UPLOAD_ERR_OK) { - throw new RuntimeException('Cannot retrieve stream due to upload error'); - } - - return $this->stream; - } - - /** - * {@inheritdoc} - */ - public function moveTo($targetPath) - { - throw new RuntimeException('Not implemented'); - } - - /** - * {@inheritdoc} - */ - public function getSize() - { - return $this->size; - } - - /** - * {@inheritdoc} - */ - public function getError() - { - return $this->error; - } - - /** - * {@inheritdoc} - */ - public function getClientFilename() - { - return $this->filename; - } - - /** - * {@inheritdoc} - */ - public function getClientMediaType() - { - return $this->mediaType; - } -} diff --git a/digital_doctor/vendor/react/http/src/Message/Request.php b/digital_doctor/vendor/react/http/src/Message/Request.php deleted file mode 100644 index 3de8c1b..0000000 --- a/digital_doctor/vendor/react/http/src/Message/Request.php +++ /dev/null @@ -1,57 +0,0 @@ - Internally, this implementation builds on top of a base class which is - * considered an implementation detail that may change in the future. - * - * @see RequestInterface - */ -final class Request extends AbstractRequest implements RequestInterface -{ - /** - * @param string $method HTTP method for the request. - * @param string|UriInterface $url URL for the request. - * @param array $headers Headers for the message. - * @param string|ReadableStreamInterface|StreamInterface $body Message body. - * @param string $version HTTP protocol version. - * @throws \InvalidArgumentException for an invalid URL or body - */ - public function __construct( - $method, - $url, - array $headers = array(), - $body = '', - $version = '1.1' - ) { - if (\is_string($body)) { - $body = new BufferedBody($body); - } elseif ($body instanceof ReadableStreamInterface && !$body instanceof StreamInterface) { - $body = new ReadableBodyStream($body); - } elseif (!$body instanceof StreamInterface) { - throw new \InvalidArgumentException('Invalid request body given'); - } - - parent::__construct($method, $url, $headers, $body, $version); - } -} diff --git a/digital_doctor/vendor/react/http/src/Message/Response.php b/digital_doctor/vendor/react/http/src/Message/Response.php deleted file mode 100644 index fa6366e..0000000 --- a/digital_doctor/vendor/react/http/src/Message/Response.php +++ /dev/null @@ -1,414 +0,0 @@ - 'text/html' - * ), - * "Hello world!\n" - * ); - * ``` - * - * This class implements the - * [PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface) - * which in turn extends the - * [PSR-7 `MessageInterface`](https://www.php-fig.org/psr/psr-7/#31-psrhttpmessagemessageinterface). - * - * On top of this, this class implements the - * [PSR-7 Message Util `StatusCodeInterface`](https://github.com/php-fig/http-message-util/blob/master/src/StatusCodeInterface.php) - * which means that most common HTTP status codes are available as class - * constants with the `STATUS_*` prefix. For instance, the `200 OK` and - * `404 Not Found` status codes can used as `Response::STATUS_OK` and - * `Response::STATUS_NOT_FOUND` respectively. - * - * > Internally, this implementation builds on top a base class which is - * considered an implementation detail that may change in the future. - * - * @see \Psr\Http\Message\ResponseInterface - */ -final class Response extends AbstractMessage implements ResponseInterface, StatusCodeInterface -{ - /** - * Create an HTML response - * - * ```php - * $html = << - * - * Hello wörld! - * - * - * HTML; - * - * $response = React\Http\Message\Response::html($html); - * ``` - * - * This is a convenient shortcut method that returns the equivalent of this: - * - * ``` - * $response = new React\Http\Message\Response( - * React\Http\Message\Response::STATUS_OK, - * [ - * 'Content-Type' => 'text/html; charset=utf-8' - * ], - * $html - * ); - * ``` - * - * This method always returns a response with a `200 OK` status code and - * the appropriate `Content-Type` response header for the given HTTP source - * string encoded in UTF-8 (Unicode). It's generally recommended to end the - * given plaintext string with a trailing newline. - * - * If you want to use a different status code or custom HTTP response - * headers, you can manipulate the returned response object using the - * provided PSR-7 methods or directly instantiate a custom HTTP response - * object using the `Response` constructor: - * - * ```php - * $response = React\Http\Message\Response::html( - * "

Error

\n

Invalid user name given.

\n" - * )->withStatus(React\Http\Message\Response::STATUS_BAD_REQUEST); - * ``` - * - * @param string $html - * @return self - */ - public static function html($html) - { - return new self(self::STATUS_OK, array('Content-Type' => 'text/html; charset=utf-8'), $html); - } - - /** - * Create a JSON response - * - * ```php - * $response = React\Http\Message\Response::json(['name' => 'Alice']); - * ``` - * - * This is a convenient shortcut method that returns the equivalent of this: - * - * ``` - * $response = new React\Http\Message\Response( - * React\Http\Message\Response::STATUS_OK, - * [ - * 'Content-Type' => 'application/json' - * ], - * json_encode( - * ['name' => 'Alice'], - * JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRESERVE_ZERO_FRACTION - * ) . "\n" - * ); - * ``` - * - * This method always returns a response with a `200 OK` status code and - * the appropriate `Content-Type` response header for the given structured - * data encoded as a JSON text. - * - * The given structured data will be encoded as a JSON text. Any `string` - * values in the data must be encoded in UTF-8 (Unicode). If the encoding - * fails, this method will throw an `InvalidArgumentException`. - * - * By default, the given structured data will be encoded with the flags as - * shown above. This includes pretty printing (PHP 5.4+) and preserving - * zero fractions for `float` values (PHP 5.6.6+) to ease debugging. It is - * assumed any additional data overhead is usually compensated by using HTTP - * response compression. - * - * If you want to use a different status code or custom HTTP response - * headers, you can manipulate the returned response object using the - * provided PSR-7 methods or directly instantiate a custom HTTP response - * object using the `Response` constructor: - * - * ```php - * $response = React\Http\Message\Response::json( - * ['error' => 'Invalid user name given'] - * )->withStatus(React\Http\Message\Response::STATUS_BAD_REQUEST); - * ``` - * - * @param mixed $data - * @return self - * @throws \InvalidArgumentException when encoding fails - */ - public static function json($data) - { - $json = @\json_encode( - $data, - (\defined('JSON_PRETTY_PRINT') ? \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE : 0) | (\defined('JSON_PRESERVE_ZERO_FRACTION') ? \JSON_PRESERVE_ZERO_FRACTION : 0) - ); - - // throw on error, now `false` but used to be `(string) "null"` before PHP 5.5 - if ($json === false || (\PHP_VERSION_ID < 50500 && \json_last_error() !== \JSON_ERROR_NONE)) { - throw new \InvalidArgumentException( - 'Unable to encode given data as JSON' . (\function_exists('json_last_error_msg') ? ': ' . \json_last_error_msg() : ''), - \json_last_error() - ); - } - - return new self(self::STATUS_OK, array('Content-Type' => 'application/json'), $json . "\n"); - } - - /** - * Create a plaintext response - * - * ```php - * $response = React\Http\Message\Response::plaintext("Hello wörld!\n"); - * ``` - * - * This is a convenient shortcut method that returns the equivalent of this: - * - * ``` - * $response = new React\Http\Message\Response( - * React\Http\Message\Response::STATUS_OK, - * [ - * 'Content-Type' => 'text/plain; charset=utf-8' - * ], - * "Hello wörld!\n" - * ); - * ``` - * - * This method always returns a response with a `200 OK` status code and - * the appropriate `Content-Type` response header for the given plaintext - * string encoded in UTF-8 (Unicode). It's generally recommended to end the - * given plaintext string with a trailing newline. - * - * If you want to use a different status code or custom HTTP response - * headers, you can manipulate the returned response object using the - * provided PSR-7 methods or directly instantiate a custom HTTP response - * object using the `Response` constructor: - * - * ```php - * $response = React\Http\Message\Response::plaintext( - * "Error: Invalid user name given.\n" - * )->withStatus(React\Http\Message\Response::STATUS_BAD_REQUEST); - * ``` - * - * @param string $text - * @return self - */ - public static function plaintext($text) - { - return new self(self::STATUS_OK, array('Content-Type' => 'text/plain; charset=utf-8'), $text); - } - - /** - * Create an XML response - * - * ```php - * $xml = << - * - * Hello wörld! - * - * - * XML; - * - * $response = React\Http\Message\Response::xml($xml); - * ``` - * - * This is a convenient shortcut method that returns the equivalent of this: - * - * ``` - * $response = new React\Http\Message\Response( - * React\Http\Message\Response::STATUS_OK, - * [ - * 'Content-Type' => 'application/xml' - * ], - * $xml - * ); - * ``` - * - * This method always returns a response with a `200 OK` status code and - * the appropriate `Content-Type` response header for the given XML source - * string. It's generally recommended to use UTF-8 (Unicode) and specify - * this as part of the leading XML declaration and to end the given XML - * source string with a trailing newline. - * - * If you want to use a different status code or custom HTTP response - * headers, you can manipulate the returned response object using the - * provided PSR-7 methods or directly instantiate a custom HTTP response - * object using the `Response` constructor: - * - * ```php - * $response = React\Http\Message\Response::xml( - * "Invalid user name given.\n" - * )->withStatus(React\Http\Message\Response::STATUS_BAD_REQUEST); - * ``` - * - * @param string $xml - * @return self - */ - public static function xml($xml) - { - return new self(self::STATUS_OK, array('Content-Type' => 'application/xml'), $xml); - } - - /** - * @var bool - * @see self::$phrasesMap - */ - private static $phrasesInitialized = false; - - /** - * Map of standard HTTP status codes to standard reason phrases. - * - * This map will be fully populated with all standard reason phrases on - * first access. By default, it only contains a subset of HTTP status codes - * that have a custom mapping to reason phrases (such as those with dashes - * and all caps words). See `self::STATUS_*` for all possible status code - * constants. - * - * @var array - * @see self::STATUS_* - * @see self::getReasonPhraseForStatusCode() - */ - private static $phrasesMap = array( - 200 => 'OK', - 203 => 'Non-Authoritative Information', - 207 => 'Multi-Status', - 226 => 'IM Used', - 414 => 'URI Too Large', - 418 => 'I\'m a teapot', - 505 => 'HTTP Version Not Supported' - ); - - /** @var int */ - private $statusCode; - - /** @var string */ - private $reasonPhrase; - - /** - * @param int $status HTTP status code (e.g. 200/404), see `self::STATUS_*` constants - * @param array $headers additional response headers - * @param string|ReadableStreamInterface|StreamInterface $body response body - * @param string $version HTTP protocol version (e.g. 1.1/1.0) - * @param ?string $reason custom HTTP response phrase - * @throws \InvalidArgumentException for an invalid body - */ - public function __construct( - $status = self::STATUS_OK, - array $headers = array(), - $body = '', - $version = '1.1', - $reason = null - ) { - if (\is_string($body)) { - $body = new BufferedBody($body); - } elseif ($body instanceof ReadableStreamInterface && !$body instanceof StreamInterface) { - $body = new HttpBodyStream($body, null); - } elseif (!$body instanceof StreamInterface) { - throw new \InvalidArgumentException('Invalid response body given'); - } - - parent::__construct($version, $headers, $body); - - $this->statusCode = (int) $status; - $this->reasonPhrase = ($reason !== '' && $reason !== null) ? (string) $reason : self::getReasonPhraseForStatusCode($status); - } - - public function getStatusCode() - { - return $this->statusCode; - } - - public function withStatus($code, $reasonPhrase = '') - { - if ((string) $reasonPhrase === '') { - $reasonPhrase = self::getReasonPhraseForStatusCode($code); - } - - if ($this->statusCode === (int) $code && $this->reasonPhrase === (string) $reasonPhrase) { - return $this; - } - - $response = clone $this; - $response->statusCode = (int) $code; - $response->reasonPhrase = (string) $reasonPhrase; - - return $response; - } - - public function getReasonPhrase() - { - return $this->reasonPhrase; - } - - /** - * @param int $code - * @return string default reason phrase for given status code or empty string if unknown - */ - private static function getReasonPhraseForStatusCode($code) - { - if (!self::$phrasesInitialized) { - self::$phrasesInitialized = true; - - // map all `self::STATUS_` constants from status code to reason phrase - // e.g. `self::STATUS_NOT_FOUND = 404` will be mapped to `404 Not Found` - $ref = new \ReflectionClass(__CLASS__); - foreach ($ref->getConstants() as $name => $value) { - if (!isset(self::$phrasesMap[$value]) && \strpos($name, 'STATUS_') === 0) { - self::$phrasesMap[$value] = \ucwords(\strtolower(\str_replace('_', ' ', \substr($name, 7)))); - } - } - } - - return isset(self::$phrasesMap[$code]) ? self::$phrasesMap[$code] : ''; - } - - /** - * [Internal] Parse incoming HTTP protocol message - * - * @internal - * @param string $message - * @return self - * @throws \InvalidArgumentException if given $message is not a valid HTTP response message - */ - public static function parseMessage($message) - { - $start = array(); - if (!\preg_match('#^HTTP/(?\d\.\d) (?\d{3})(?: (?[^\r\n]*+))?[\r]?+\n#m', $message, $start)) { - throw new \InvalidArgumentException('Unable to parse invalid status-line'); - } - - // only support HTTP/1.1 and HTTP/1.0 requests - if ($start['version'] !== '1.1' && $start['version'] !== '1.0') { - throw new \InvalidArgumentException('Received response with invalid protocol version'); - } - - // check number of valid header fields matches number of lines + status line - $matches = array(); - $n = \preg_match_all(self::REGEX_HEADERS, $message, $matches, \PREG_SET_ORDER); - if (\substr_count($message, "\n") !== $n + 1) { - throw new \InvalidArgumentException('Unable to parse invalid response header fields'); - } - - // format all header fields into associative array - $headers = array(); - foreach ($matches as $match) { - $headers[$match[1]][] = $match[2]; - } - - return new self( - (int) $start['status'], - $headers, - '', - $start['version'], - isset($start['reason']) ? $start['reason'] : '' - ); - } -} diff --git a/digital_doctor/vendor/react/http/src/Message/ResponseException.php b/digital_doctor/vendor/react/http/src/Message/ResponseException.php deleted file mode 100644 index f4912c9..0000000 --- a/digital_doctor/vendor/react/http/src/Message/ResponseException.php +++ /dev/null @@ -1,43 +0,0 @@ -getStatusCode() . ' (' . $response->getReasonPhrase() . ')'; - } - if ($code === null) { - $code = $response->getStatusCode(); - } - parent::__construct($message, $code, $previous); - - $this->response = $response; - } - - /** - * Access its underlying response object. - * - * @return ResponseInterface - */ - public function getResponse() - { - return $this->response; - } -} diff --git a/digital_doctor/vendor/react/http/src/Message/ServerRequest.php b/digital_doctor/vendor/react/http/src/Message/ServerRequest.php deleted file mode 100644 index 32a0f62..0000000 --- a/digital_doctor/vendor/react/http/src/Message/ServerRequest.php +++ /dev/null @@ -1,331 +0,0 @@ - Internally, this implementation builds on top of a base class which is - * considered an implementation detail that may change in the future. - * - * @see ServerRequestInterface - */ -final class ServerRequest extends AbstractRequest implements ServerRequestInterface -{ - private $attributes = array(); - - private $serverParams; - private $fileParams = array(); - private $cookies = array(); - private $queryParams = array(); - private $parsedBody; - - /** - * @param string $method HTTP method for the request. - * @param string|UriInterface $url URL for the request. - * @param array $headers Headers for the message. - * @param string|ReadableStreamInterface|StreamInterface $body Message body. - * @param string $version HTTP protocol version. - * @param array $serverParams server-side parameters - * @throws \InvalidArgumentException for an invalid URL or body - */ - public function __construct( - $method, - $url, - array $headers = array(), - $body = '', - $version = '1.1', - $serverParams = array() - ) { - if (\is_string($body)) { - $body = new BufferedBody($body); - } elseif ($body instanceof ReadableStreamInterface && !$body instanceof StreamInterface) { - $temp = new self($method, '', $headers); - $size = (int) $temp->getHeaderLine('Content-Length'); - if (\strtolower($temp->getHeaderLine('Transfer-Encoding')) === 'chunked') { - $size = null; - } - $body = new HttpBodyStream($body, $size); - } elseif (!$body instanceof StreamInterface) { - throw new \InvalidArgumentException('Invalid server request body given'); - } - - parent::__construct($method, $url, $headers, $body, $version); - - $this->serverParams = $serverParams; - - $query = $this->getUri()->getQuery(); - if ($query !== '') { - \parse_str($query, $this->queryParams); - } - - // Multiple cookie headers are not allowed according - // to https://tools.ietf.org/html/rfc6265#section-5.4 - $cookieHeaders = $this->getHeader("Cookie"); - - if (count($cookieHeaders) === 1) { - $this->cookies = $this->parseCookie($cookieHeaders[0]); - } - } - - public function getServerParams() - { - return $this->serverParams; - } - - public function getCookieParams() - { - return $this->cookies; - } - - public function withCookieParams(array $cookies) - { - $new = clone $this; - $new->cookies = $cookies; - return $new; - } - - public function getQueryParams() - { - return $this->queryParams; - } - - public function withQueryParams(array $query) - { - $new = clone $this; - $new->queryParams = $query; - return $new; - } - - public function getUploadedFiles() - { - return $this->fileParams; - } - - public function withUploadedFiles(array $uploadedFiles) - { - $new = clone $this; - $new->fileParams = $uploadedFiles; - return $new; - } - - public function getParsedBody() - { - return $this->parsedBody; - } - - public function withParsedBody($data) - { - $new = clone $this; - $new->parsedBody = $data; - return $new; - } - - public function getAttributes() - { - return $this->attributes; - } - - public function getAttribute($name, $default = null) - { - if (!\array_key_exists($name, $this->attributes)) { - return $default; - } - return $this->attributes[$name]; - } - - public function withAttribute($name, $value) - { - $new = clone $this; - $new->attributes[$name] = $value; - return $new; - } - - public function withoutAttribute($name) - { - $new = clone $this; - unset($new->attributes[$name]); - return $new; - } - - /** - * @param string $cookie - * @return array - */ - private function parseCookie($cookie) - { - $cookieArray = \explode(';', $cookie); - $result = array(); - - foreach ($cookieArray as $pair) { - $pair = \trim($pair); - $nameValuePair = \explode('=', $pair, 2); - - if (\count($nameValuePair) === 2) { - $key = $nameValuePair[0]; - $value = \urldecode($nameValuePair[1]); - $result[$key] = $value; - } - } - - return $result; - } - - /** - * [Internal] Parse incoming HTTP protocol message - * - * @internal - * @param string $message - * @param array $serverParams - * @return self - * @throws \InvalidArgumentException if given $message is not a valid HTTP request message - */ - public static function parseMessage($message, array $serverParams) - { - // parse request line like "GET /path HTTP/1.1" - $start = array(); - if (!\preg_match('#^(?[^ ]+) (?[^ ]+) HTTP/(?\d\.\d)#m', $message, $start)) { - throw new \InvalidArgumentException('Unable to parse invalid request-line'); - } - - // only support HTTP/1.1 and HTTP/1.0 requests - if ($start['version'] !== '1.1' && $start['version'] !== '1.0') { - throw new \InvalidArgumentException('Received request with invalid protocol version', Response::STATUS_VERSION_NOT_SUPPORTED); - } - - // check number of valid header fields matches number of lines + request line - $matches = array(); - $n = \preg_match_all(self::REGEX_HEADERS, $message, $matches, \PREG_SET_ORDER); - if (\substr_count($message, "\n") !== $n + 1) { - throw new \InvalidArgumentException('Unable to parse invalid request header fields'); - } - - // format all header fields into associative array - $host = null; - $headers = array(); - foreach ($matches as $match) { - $headers[$match[1]][] = $match[2]; - - // match `Host` request header - if ($host === null && \strtolower($match[1]) === 'host') { - $host = $match[2]; - } - } - - // scheme is `http` unless TLS is used - $scheme = isset($serverParams['HTTPS']) ? 'https://' : 'http://'; - - // default host if unset comes from local socket address or defaults to localhost - $hasHost = $host !== null; - if ($host === null) { - $host = isset($serverParams['SERVER_ADDR'], $serverParams['SERVER_PORT']) ? $serverParams['SERVER_ADDR'] . ':' . $serverParams['SERVER_PORT'] : '127.0.0.1'; - } - - if ($start['method'] === 'OPTIONS' && $start['target'] === '*') { - // support asterisk-form for `OPTIONS *` request line only - $uri = $scheme . $host; - } elseif ($start['method'] === 'CONNECT') { - $parts = \parse_url('tcp://' . $start['target']); - - // check this is a valid authority-form request-target (host:port) - if (!isset($parts['scheme'], $parts['host'], $parts['port']) || \count($parts) !== 3) { - throw new \InvalidArgumentException('CONNECT method MUST use authority-form request target'); - } - $uri = $scheme . $start['target']; - } else { - // support absolute-form or origin-form for proxy requests - if ($start['target'][0] === '/') { - $uri = $scheme . $host . $start['target']; - } else { - // ensure absolute-form request-target contains a valid URI - $parts = \parse_url($start['target']); - - // make sure value contains valid host component (IP or hostname), but no fragment - if (!isset($parts['scheme'], $parts['host']) || $parts['scheme'] !== 'http' || isset($parts['fragment'])) { - throw new \InvalidArgumentException('Invalid absolute-form request-target'); - } - - $uri = $start['target']; - } - } - - $request = new self( - $start['method'], - $uri, - $headers, - '', - $start['version'], - $serverParams - ); - - // only assign request target if it is not in origin-form (happy path for most normal requests) - if ($start['target'][0] !== '/') { - $request = $request->withRequestTarget($start['target']); - } - - if ($hasHost) { - // Optional Host request header value MUST be valid (host and optional port) - $parts = \parse_url('http://' . $request->getHeaderLine('Host')); - - // make sure value contains valid host component (IP or hostname) - if (!$parts || !isset($parts['scheme'], $parts['host'])) { - $parts = false; - } - - // make sure value does not contain any other URI component - if (\is_array($parts)) { - unset($parts['scheme'], $parts['host'], $parts['port']); - } - if ($parts === false || $parts) { - throw new \InvalidArgumentException('Invalid Host header value'); - } - } elseif (!$hasHost && $start['version'] === '1.1' && $start['method'] !== 'CONNECT') { - // require Host request header for HTTP/1.1 (except for CONNECT method) - throw new \InvalidArgumentException('Missing required Host request header'); - } elseif (!$hasHost) { - // remove default Host request header for HTTP/1.0 when not explicitly given - $request = $request->withoutHeader('Host'); - } - - // ensure message boundaries are valid according to Content-Length and Transfer-Encoding request headers - if ($request->hasHeader('Transfer-Encoding')) { - if (\strtolower($request->getHeaderLine('Transfer-Encoding')) !== 'chunked') { - throw new \InvalidArgumentException('Only chunked-encoding is allowed for Transfer-Encoding', Response::STATUS_NOT_IMPLEMENTED); - } - - // Transfer-Encoding: chunked and Content-Length header MUST NOT be used at the same time - // as per https://tools.ietf.org/html/rfc7230#section-3.3.3 - if ($request->hasHeader('Content-Length')) { - throw new \InvalidArgumentException('Using both `Transfer-Encoding: chunked` and `Content-Length` is not allowed', Response::STATUS_BAD_REQUEST); - } - } elseif ($request->hasHeader('Content-Length')) { - $string = $request->getHeaderLine('Content-Length'); - - if ((string)(int)$string !== $string) { - // Content-Length value is not an integer or not a single integer - throw new \InvalidArgumentException('The value of `Content-Length` is not valid', Response::STATUS_BAD_REQUEST); - } - } - - return $request; - } -} diff --git a/digital_doctor/vendor/react/http/src/Message/Uri.php b/digital_doctor/vendor/react/http/src/Message/Uri.php deleted file mode 100644 index 4309bbe..0000000 --- a/digital_doctor/vendor/react/http/src/Message/Uri.php +++ /dev/null @@ -1,356 +0,0 @@ -scheme = \strtolower($parts['scheme']); - } - - if (isset($parts['user']) || isset($parts['pass'])) { - $this->userInfo = $this->encode(isset($parts['user']) ? $parts['user'] : '', \PHP_URL_USER) . (isset($parts['pass']) ? ':' . $this->encode($parts['pass'], \PHP_URL_PASS) : ''); - } - - if (isset($parts['host'])) { - $this->host = \strtolower($parts['host']); - } - - if (isset($parts['port']) && !(($parts['port'] === 80 && $this->scheme === 'http') || ($parts['port'] === 443 && $this->scheme === 'https'))) { - $this->port = $parts['port']; - } - - if (isset($parts['path'])) { - $this->path = $this->encode($parts['path'], \PHP_URL_PATH); - } - - if (isset($parts['query'])) { - $this->query = $this->encode($parts['query'], \PHP_URL_QUERY); - } - - if (isset($parts['fragment'])) { - $this->fragment = $this->encode($parts['fragment'], \PHP_URL_FRAGMENT); - } - } - - public function getScheme() - { - return $this->scheme; - } - - public function getAuthority() - { - if ($this->host === '') { - return ''; - } - - return ($this->userInfo !== '' ? $this->userInfo . '@' : '') . $this->host . ($this->port !== null ? ':' . $this->port : ''); - } - - public function getUserInfo() - { - return $this->userInfo; - } - - public function getHost() - { - return $this->host; - } - - public function getPort() - { - return $this->port; - } - - public function getPath() - { - return $this->path; - } - - public function getQuery() - { - return $this->query; - } - - public function getFragment() - { - return $this->fragment; - } - - public function withScheme($scheme) - { - $scheme = \strtolower($scheme); - if ($scheme === $this->scheme) { - return $this; - } - - if (!\preg_match('#^[a-z]*$#', $scheme)) { - throw new \InvalidArgumentException('Invalid URI scheme given'); - } - - $new = clone $this; - $new->scheme = $scheme; - - if (($this->port === 80 && $scheme === 'http') || ($this->port === 443 && $scheme === 'https')) { - $new->port = null; - } - - return $new; - } - - public function withUserInfo($user, $password = null) - { - $userInfo = $this->encode($user, \PHP_URL_USER) . ($password !== null ? ':' . $this->encode($password, \PHP_URL_PASS) : ''); - if ($userInfo === $this->userInfo) { - return $this; - } - - $new = clone $this; - $new->userInfo = $userInfo; - - return $new; - } - - public function withHost($host) - { - $host = \strtolower($host); - if ($host === $this->host) { - return $this; - } - - if (\preg_match('#[\s_%+]#', $host) || ($host !== '' && \parse_url('http://' . $host, \PHP_URL_HOST) !== $host)) { - throw new \InvalidArgumentException('Invalid URI host given'); - } - - $new = clone $this; - $new->host = $host; - - return $new; - } - - public function withPort($port) - { - $port = $port === null ? null : (int) $port; - if (($port === 80 && $this->scheme === 'http') || ($port === 443 && $this->scheme === 'https')) { - $port = null; - } - - if ($port === $this->port) { - return $this; - } - - if ($port !== null && ($port < 1 || $port > 0xffff)) { - throw new \InvalidArgumentException('Invalid URI port given'); - } - - $new = clone $this; - $new->port = $port; - - return $new; - } - - public function withPath($path) - { - $path = $this->encode($path, \PHP_URL_PATH); - if ($path === $this->path) { - return $this; - } - - $new = clone $this; - $new->path = $path; - - return $new; - } - - public function withQuery($query) - { - $query = $this->encode($query, \PHP_URL_QUERY); - if ($query === $this->query) { - return $this; - } - - $new = clone $this; - $new->query = $query; - - return $new; - } - - public function withFragment($fragment) - { - $fragment = $this->encode($fragment, \PHP_URL_FRAGMENT); - if ($fragment === $this->fragment) { - return $this; - } - - $new = clone $this; - $new->fragment = $fragment; - - return $new; - } - - public function __toString() - { - $uri = ''; - if ($this->scheme !== '') { - $uri .= $this->scheme . ':'; - } - - $authority = $this->getAuthority(); - if ($authority !== '') { - $uri .= '//' . $authority; - } - - if ($authority !== '' && isset($this->path[0]) && $this->path[0] !== '/') { - $uri .= '/' . $this->path; - } elseif ($authority === '' && isset($this->path[0]) && $this->path[0] === '/') { - $uri .= '/' . \ltrim($this->path, '/'); - } else { - $uri .= $this->path; - } - - if ($this->query !== '') { - $uri .= '?' . $this->query; - } - - if ($this->fragment !== '') { - $uri .= '#' . $this->fragment; - } - - return $uri; - } - - /** - * @param string $part - * @param int $component - * @return string - */ - private function encode($part, $component) - { - return \preg_replace_callback( - '/(?:[^a-z0-9_\-\.~!\$&\'\(\)\*\+,;=' . ($component === \PHP_URL_PATH ? ':@\/' : ($component === \PHP_URL_QUERY || $component === \PHP_URL_FRAGMENT ? ':@\/\?' : '')) . '%]++|%(?![a-f0-9]{2}))/i', - function (array $match) { - return \rawurlencode($match[0]); - }, - $part - ); - } - - /** - * [Internal] Resolve URI relative to base URI and return new absolute URI - * - * @internal - * @param UriInterface $base - * @param UriInterface $rel - * @return UriInterface - * @throws void - */ - public static function resolve(UriInterface $base, UriInterface $rel) - { - if ($rel->getScheme() !== '') { - return $rel->getPath() === '' ? $rel : $rel->withPath(self::removeDotSegments($rel->getPath())); - } - - $reset = false; - $new = $base; - if ($rel->getAuthority() !== '') { - $reset = true; - $userInfo = \explode(':', $rel->getUserInfo(), 2); - $new = $base->withUserInfo($userInfo[0], isset($userInfo[1]) ? $userInfo[1]: null)->withHost($rel->getHost())->withPort($rel->getPort()); - } - - if ($reset && $rel->getPath() === '') { - $new = $new->withPath(''); - } elseif (($path = $rel->getPath()) !== '') { - $start = ''; - if ($path === '' || $path[0] !== '/') { - $start = $base->getPath(); - if (\substr($start, -1) !== '/') { - $start .= '/../'; - } - } - $reset = true; - $new = $new->withPath(self::removeDotSegments($start . $path)); - } - if ($reset || $rel->getQuery() !== '') { - $reset = true; - $new = $new->withQuery($rel->getQuery()); - } - if ($reset || $rel->getFragment() !== '') { - $new = $new->withFragment($rel->getFragment()); - } - - return $new; - } - - /** - * @param string $path - * @return string - */ - private static function removeDotSegments($path) - { - $segments = array(); - foreach (\explode('/', $path) as $segment) { - if ($segment === '..') { - \array_pop($segments); - } elseif ($segment !== '.' && $segment !== '') { - $segments[] = $segment; - } - } - return '/' . \implode('/', $segments) . ($path !== '/' && \substr($path, -1) === '/' ? '/' : ''); - } -} diff --git a/digital_doctor/vendor/react/http/src/Middleware/LimitConcurrentRequestsMiddleware.php b/digital_doctor/vendor/react/http/src/Middleware/LimitConcurrentRequestsMiddleware.php deleted file mode 100644 index b1c00da..0000000 --- a/digital_doctor/vendor/react/http/src/Middleware/LimitConcurrentRequestsMiddleware.php +++ /dev/null @@ -1,211 +0,0 @@ -limit = $limit; - } - - public function __invoke(ServerRequestInterface $request, $next) - { - // happy path: simply invoke next request handler if we're below limit - if ($this->pending < $this->limit) { - ++$this->pending; - - try { - $response = $next($request); - } catch (\Exception $e) { - $this->processQueue(); - throw $e; - } catch (\Throwable $e) { // @codeCoverageIgnoreStart - // handle Errors just like Exceptions (PHP 7+ only) - $this->processQueue(); - throw $e; // @codeCoverageIgnoreEnd - } - - // happy path: if next request handler returned immediately, - // we can simply try to invoke the next queued request - if ($response instanceof ResponseInterface) { - $this->processQueue(); - return $response; - } - - // if the next handler returns a pending promise, we have to - // await its resolution before invoking next queued request - return $this->await(Promise\resolve($response)); - } - - // if we reach this point, then this request will need to be queued - // check if the body is streaming, in which case we need to buffer everything - $body = $request->getBody(); - if ($body instanceof ReadableStreamInterface) { - // pause actual body to stop emitting data until the handler is called - $size = $body->getSize(); - $body = new PauseBufferStream($body); - $body->pauseImplicit(); - - // replace with buffering body to ensure any readable events will be buffered - $request = $request->withBody(new HttpBodyStream( - $body, - $size - )); - } - - // get next queue position - $queue =& $this->queue; - $queue[] = null; - \end($queue); - $id = \key($queue); - - $deferred = new Deferred(function ($_, $reject) use (&$queue, $id) { - // queued promise cancelled before its next handler is invoked - // remove from queue and reject explicitly - unset($queue[$id]); - $reject(new \RuntimeException('Cancelled queued next handler')); - }); - - // queue request and process queue if pending does not exceed limit - $queue[$id] = $deferred; - - $pending = &$this->pending; - $that = $this; - return $deferred->promise()->then(function () use ($request, $next, $body, &$pending, $that) { - // invoke next request handler - ++$pending; - - try { - $response = $next($request); - } catch (\Exception $e) { - $that->processQueue(); - throw $e; - } catch (\Throwable $e) { // @codeCoverageIgnoreStart - // handle Errors just like Exceptions (PHP 7+ only) - $that->processQueue(); - throw $e; // @codeCoverageIgnoreEnd - } - - // resume readable stream and replay buffered events - if ($body instanceof PauseBufferStream) { - $body->resumeImplicit(); - } - - // if the next handler returns a pending promise, we have to - // await its resolution before invoking next queued request - return $that->await(Promise\resolve($response)); - }); - } - - /** - * @internal - * @param PromiseInterface $promise - * @return PromiseInterface - */ - public function await(PromiseInterface $promise) - { - $that = $this; - - return $promise->then(function ($response) use ($that) { - $that->processQueue(); - - return $response; - }, function ($error) use ($that) { - $that->processQueue(); - - return Promise\reject($error); - }); - } - - /** - * @internal - */ - public function processQueue() - { - // skip if we're still above concurrency limit or there's no queued request waiting - if (--$this->pending >= $this->limit || !$this->queue) { - return; - } - - $first = \reset($this->queue); - unset($this->queue[key($this->queue)]); - - $first->resolve(null); - } -} diff --git a/digital_doctor/vendor/react/http/src/Middleware/RequestBodyBufferMiddleware.php b/digital_doctor/vendor/react/http/src/Middleware/RequestBodyBufferMiddleware.php deleted file mode 100644 index ddb39f5..0000000 --- a/digital_doctor/vendor/react/http/src/Middleware/RequestBodyBufferMiddleware.php +++ /dev/null @@ -1,109 +0,0 @@ -sizeLimit = IniUtil::iniSizeToBytes($sizeLimit); - } - - public function __invoke(ServerRequestInterface $request, $next) - { - $body = $request->getBody(); - $size = $body->getSize(); - - // happy path: skip if body is known to be empty (or is already buffered) - if ($size === 0 || !$body instanceof ReadableStreamInterface || !$body->isReadable()) { - // replace with empty body if body is streaming (or buffered size exceeds limit) - if ($body instanceof ReadableStreamInterface || $size > $this->sizeLimit) { - $request = $request->withBody(new BufferedBody('')); - } - - return $next($request); - } - - // request body of known size exceeding limit - $sizeLimit = $this->sizeLimit; - if ($size > $this->sizeLimit) { - $sizeLimit = 0; - } - - /** @var ?\Closure $closer */ - $closer = null; - - return new Promise(function ($resolve, $reject) use ($body, &$closer, $sizeLimit, $request, $next) { - // buffer request body data in memory, discard but keep buffering if limit is reached - $buffer = ''; - $bufferer = null; - $body->on('data', $bufferer = function ($data) use (&$buffer, $sizeLimit, $body, &$bufferer) { - $buffer .= $data; - - // On buffer overflow keep the request body stream in, - // but ignore the contents and wait for the close event - // before passing the request on to the next middleware. - if (isset($buffer[$sizeLimit])) { - assert($bufferer instanceof \Closure); - $body->removeListener('data', $bufferer); - $bufferer = null; - $buffer = ''; - } - }); - - // call $next with current buffer and resolve or reject with its results - $body->on('close', $closer = function () use (&$buffer, $request, $resolve, $reject, $next) { - try { - // resolve with result of next handler - $resolve($next($request->withBody(new BufferedBody($buffer)))); - } catch (\Exception $e) { - $reject($e); - } catch (\Throwable $e) { // @codeCoverageIgnoreStart - // reject Errors just like Exceptions (PHP 7+) - $reject($e); // @codeCoverageIgnoreEnd - } - }); - - // reject buffering if body emits error - $body->on('error', function (\Exception $e) use ($reject, $body, $closer) { - // remove close handler to avoid resolving, then close and reject - assert($closer instanceof \Closure); - $body->removeListener('close', $closer); - $body->close(); - - $reject(new \RuntimeException( - 'Error while buffering request body: ' . $e->getMessage(), - $e->getCode(), - $e - )); - }); - }, function () use ($body, &$closer) { - // cancelled buffering: remove close handler to avoid resolving, then close and reject - assert($closer instanceof \Closure); - $body->removeListener('close', $closer); - $body->close(); - - throw new \RuntimeException('Cancelled buffering request body'); - }); - } -} diff --git a/digital_doctor/vendor/react/http/src/Middleware/RequestBodyParserMiddleware.php b/digital_doctor/vendor/react/http/src/Middleware/RequestBodyParserMiddleware.php deleted file mode 100644 index be5ba16..0000000 --- a/digital_doctor/vendor/react/http/src/Middleware/RequestBodyParserMiddleware.php +++ /dev/null @@ -1,46 +0,0 @@ -multipart = new MultipartParser($uploadMaxFilesize, $maxFileUploads); - } - - public function __invoke(ServerRequestInterface $request, $next) - { - $type = \strtolower($request->getHeaderLine('Content-Type')); - list ($type) = \explode(';', $type); - - if ($type === 'application/x-www-form-urlencoded') { - return $next($this->parseFormUrlencoded($request)); - } - - if ($type === 'multipart/form-data') { - return $next($this->multipart->parse($request)); - } - - return $next($request); - } - - private function parseFormUrlencoded(ServerRequestInterface $request) - { - // parse string into array structure - // ignore warnings due to excessive data structures (max_input_vars and max_input_nesting_level) - $ret = array(); - @\parse_str((string)$request->getBody(), $ret); - - return $request->withParsedBody($ret); - } -} diff --git a/digital_doctor/vendor/react/http/src/Middleware/StreamingRequestMiddleware.php b/digital_doctor/vendor/react/http/src/Middleware/StreamingRequestMiddleware.php deleted file mode 100644 index 6ab74b7..0000000 --- a/digital_doctor/vendor/react/http/src/Middleware/StreamingRequestMiddleware.php +++ /dev/null @@ -1,69 +0,0 @@ -getBody(); - * assert($body instanceof Psr\Http\Message\StreamInterface); - * assert($body instanceof React\Stream\ReadableStreamInterface); - * - * return new React\Promise\Promise(function ($resolve) use ($body) { - * $bytes = 0; - * $body->on('data', function ($chunk) use (&$bytes) { - * $bytes += \count($chunk); - * }); - * $body->on('close', function () use (&$bytes, $resolve) { - * $resolve(new React\Http\Response( - * 200, - * [], - * "Received $bytes bytes\n" - * )); - * }); - * }); - * } - * ); - * ``` - * - * See also [streaming incoming request](../../README.md#streaming-incoming-request) - * for more details. - * - * Additionally, this middleware can be used in combination with the - * [`LimitConcurrentRequestsMiddleware`](#limitconcurrentrequestsmiddleware) and - * [`RequestBodyBufferMiddleware`](#requestbodybuffermiddleware) (see below) - * to explicitly configure the total number of requests that can be handled at - * once: - * - * ```php - * $http = new React\Http\HttpServer( - * new React\Http\Middleware\StreamingRequestMiddleware(), - * new React\Http\Middleware\LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers - * new React\Http\Middleware\RequestBodyBufferMiddleware(2 * 1024 * 1024), // 2 MiB per request - * new React\Http\Middleware\RequestBodyParserMiddleware(), - * $handler - * ); - * ``` - * - * > Internally, this class is used as a "marker" to not trigger the default - * request buffering behavior in the `HttpServer`. It does not implement any logic - * on its own. - */ -final class StreamingRequestMiddleware -{ - public function __invoke(ServerRequestInterface $request, $next) - { - return $next($request); - } -} diff --git a/digital_doctor/vendor/react/http/src/Server.php b/digital_doctor/vendor/react/http/src/Server.php deleted file mode 100644 index 9bb9cf7..0000000 --- a/digital_doctor/vendor/react/http/src/Server.php +++ /dev/null @@ -1,18 +0,0 @@ -` and `reject(Throwable $reason): PromiseInterface`. - It is no longer possible to resolve a promise without a value (use `null` instead) or reject a promise without a reason (use `Throwable` instead). - (#93, #141 and #142 by @jsor, #138, #149 and #247 by @WyriHaximus and #213 and #246 by @clue) - - ```php - // old (arguments used to be optional) - $promise = resolve(); - $promise = reject(); - - // new (already supported before) - $promise = resolve(null); - $promise = reject(new RuntimeException()); - ``` - -* Feature / BC break: Report all unhandled rejections by default and remove ~~`done()`~~ method. - Add new `set_rejection_handler()` function to set the global rejection handler for unhandled promise rejections. - (#248, #249 and #224 by @clue) - - ```php - // Unhandled promise rejection with RuntimeException: Unhandled in example.php:2 - reject(new RuntimeException('Unhandled')); - ``` - -* BC break: Remove all deprecated APIs and reduce API surface. - Remove ~~`some()`~~, ~~`map()`~~, ~~`reduce()`~~ functions, use `any()` and `all()` functions instead. - Remove internal ~~`FulfilledPromise`~~ and ~~`RejectedPromise`~~ classes, use `resolve()` and `reject()` functions instead. - Remove legacy promise progress API (deprecated third argument to `then()` method) and deprecated ~~`LazyPromise`~~ class. - (#32 and #98 by @jsor and #164, #219 and #220 by @clue) - -* BC break: Make all classes final to encourage composition over inheritance. - (#80 by @jsor) - -* Feature / BC break: Require `array` (or `iterable`) type for `all()` + `race()` + `any()` functions and bring in line with ES6 specification. - These functions now require a single argument with a variable number of promises or values as input. - (#225 by @clue and #35 by @jsor) - -* Fix / BC break: Fix `race()` to return a forever pending promise when called with an empty `array` (or `iterable`) and bring in line with ES6 specification. - (#83 by @jsor and #225 by @clue) - -* Minor performance improvements by initializing `Deferred` in the constructor and avoiding `call_user_func()` calls. - (#151 by @WyriHaximus and #171 by @Kubo2) - -* Minor documentation improvements. - (#110 by @seregazhuk, #132 by @CharlotteDunois, #145 by @danielecr, #178 by @WyriHaximus, #189 by @srdante, #212 by @clue, #214, #239 and #243 by @SimonFrings and #231 by @nhedger) - -The following changes had to be ported to this release due to our branching -strategy, but also appeared in the [`2.x` branch](https://github.com/reactphp/promise/tree/2.x): - -* Feature: Support union types and address deprecation of `ReflectionType::getClass()` (PHP 8+). - (#197 by @cdosoftei and @SimonFrings) - -* Feature: Support intersection types (PHP 8.1+). - (#209 by @bzikarsky) - -* Feature: Support DNS types (PHP 8.2+). - (#236 by @nhedger) - -* Feature: Port all memory improvements from `2.x` to `3.x`. - (#150 by @clue and @WyriHaximus) - -* Fix: Fix checking whether cancellable promise is an object and avoid possible warning. - (#161 by @smscr) - -* Improve performance by prefixing all global functions calls with \ to skip the look up and resolve process and go straight to the global function. - (#134 by @WyriHaximus) - -* Improve test suite, update PHPUnit and PHP versions and add `.gitattributes` to exclude dev files from exports. - (#107 by @carusogabriel, #148 and #234 by @WyriHaximus, #153 by @reedy, #162, #230 and #240 by @clue, #173, #177, #185 and #199 by @SimonFrings, #193 by @woodongwong and #210 by @bzikarsky) - -The following changes were originally planned for this release but later reverted -and are not part of the final release: - -* Add iterative callback queue handler to avoid recursion (later removed to improve Fiber support). - (#28, #82 and #86 by @jsor, #158 by @WyriHaximus and #229 and #238 by @clue) - -* Trigger an `E_USER_ERROR` instead of throwing an exception from `done()` (later removed entire `done()` method to globally report unhandled rejections). - (#97 by @jsor and #224 and #248 by @clue) - -* Add type declarations for `some()` (later removed entire `some()` function). - (#172 by @WyriHaximus and #219 by @clue) - -## 2.0.0 (2013-12-10) - -See [`2.x` CHANGELOG](https://github.com/reactphp/promise/blob/2.x/CHANGELOG.md) for more details. - -## 1.0.0 (2012-11-07) - -See [`1.x` CHANGELOG](https://github.com/reactphp/promise/blob/1.x/CHANGELOG.md) for more details. diff --git a/digital_doctor/vendor/react/promise/LICENSE b/digital_doctor/vendor/react/promise/LICENSE deleted file mode 100644 index 21c1357..0000000 --- a/digital_doctor/vendor/react/promise/LICENSE +++ /dev/null @@ -1,24 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2012 Jan Sorgalla, Christian Lück, Cees-Jan Kiewiet, Chris Boden - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. diff --git a/digital_doctor/vendor/react/promise/README.md b/digital_doctor/vendor/react/promise/README.md deleted file mode 100644 index 2108d98..0000000 --- a/digital_doctor/vendor/react/promise/README.md +++ /dev/null @@ -1,722 +0,0 @@ -Promise -======= - -A lightweight implementation of -[CommonJS Promises/A](http://wiki.commonjs.org/wiki/Promises/A) for PHP. - -[![CI status](https://github.com/reactphp/promise/workflows/CI/badge.svg)](https://github.com/reactphp/promise/actions) -[![installs on Packagist](https://img.shields.io/packagist/dt/react/promise?color=blue&label=installs%20on%20Packagist)](https://packagist.org/packages/react/promise) - -Table of Contents ------------------ - -1. [Introduction](#introduction) -2. [Concepts](#concepts) - * [Deferred](#deferred) - * [Promise](#promise-1) -3. [API](#api) - * [Deferred](#deferred-1) - * [Deferred::promise()](#deferredpromise) - * [Deferred::resolve()](#deferredresolve) - * [Deferred::reject()](#deferredreject) - * [PromiseInterface](#promiseinterface) - * [PromiseInterface::then()](#promiseinterfacethen) - * [PromiseInterface::catch()](#promiseinterfacecatch) - * [PromiseInterface::finally()](#promiseinterfacefinally) - * [PromiseInterface::cancel()](#promiseinterfacecancel) - * [~~PromiseInterface::otherwise()~~](#promiseinterfaceotherwise) - * [~~PromiseInterface::always()~~](#promiseinterfacealways) - * [Promise](#promise-2) - * [Functions](#functions) - * [resolve()](#resolve) - * [reject()](#reject) - * [all()](#all) - * [race()](#race) - * [any()](#any) - * [set_rejection_handler()](#set_rejection_handler) -4. [Examples](#examples) - * [How to use Deferred](#how-to-use-deferred) - * [How promise forwarding works](#how-promise-forwarding-works) - * [Resolution forwarding](#resolution-forwarding) - * [Rejection forwarding](#rejection-forwarding) - * [Mixed resolution and rejection forwarding](#mixed-resolution-and-rejection-forwarding) -5. [Install](#install) -6. [Tests](#tests) -7. [Credits](#credits) -8. [License](#license) - -Introduction ------------- - -Promise is a library implementing -[CommonJS Promises/A](http://wiki.commonjs.org/wiki/Promises/A) for PHP. - -It also provides several other useful promise-related concepts, such as joining -multiple promises and mapping and reducing collections of promises. - -If you've never heard about promises before, -[read this first](https://gist.github.com/domenic/3889970). - -Concepts --------- - -### Deferred - -A **Deferred** represents a computation or unit of work that may not have -completed yet. Typically (but not always), that computation will be something -that executes asynchronously and completes at some point in the future. - -### Promise - -While a deferred represents the computation itself, a **Promise** represents -the result of that computation. Thus, each deferred has a promise that acts as -a placeholder for its actual result. - -API ---- - -### Deferred - -A deferred represents an operation whose resolution is pending. It has separate -promise and resolver parts. - -```php -$deferred = new React\Promise\Deferred(); - -$promise = $deferred->promise(); - -$deferred->resolve(mixed $value); -$deferred->reject(\Throwable $reason); -``` - -The `promise` method returns the promise of the deferred. - -The `resolve` and `reject` methods control the state of the deferred. - -The constructor of the `Deferred` accepts an optional `$canceller` argument. -See [Promise](#promise-2) for more information. - -#### Deferred::promise() - -```php -$promise = $deferred->promise(); -``` - -Returns the promise of the deferred, which you can hand out to others while -keeping the authority to modify its state to yourself. - -#### Deferred::resolve() - -```php -$deferred->resolve(mixed $value); -``` - -Resolves the promise returned by `promise()`. All consumers are notified by -having `$onFulfilled` (which they registered via `$promise->then()`) called with -`$value`. - -If `$value` itself is a promise, the promise will transition to the state of -this promise once it is resolved. - -See also the [`resolve()` function](#resolve). - -#### Deferred::reject() - -```php -$deferred->reject(\Throwable $reason); -``` - -Rejects the promise returned by `promise()`, signalling that the deferred's -computation failed. -All consumers are notified by having `$onRejected` (which they registered via -`$promise->then()`) called with `$reason`. - -See also the [`reject()` function](#reject). - -### PromiseInterface - -The promise interface provides the common interface for all promise -implementations. -See [Promise](#promise-2) for the only public implementation exposed by this -package. - -A promise represents an eventual outcome, which is either fulfillment (success) -and an associated value, or rejection (failure) and an associated reason. - -Once in the fulfilled or rejected state, a promise becomes immutable. -Neither its state nor its result (or error) can be modified. - -#### PromiseInterface::then() - -```php -$transformedPromise = $promise->then(callable $onFulfilled = null, callable $onRejected = null); -``` - -Transforms a promise's value by applying a function to the promise's fulfillment -or rejection value. Returns a new promise for the transformed result. - -The `then()` method registers new fulfilled and rejection handlers with a promise -(all parameters are optional): - - * `$onFulfilled` will be invoked once the promise is fulfilled and passed - the result as the first argument. - * `$onRejected` will be invoked once the promise is rejected and passed the - reason as the first argument. - -It returns a new promise that will fulfill with the return value of either -`$onFulfilled` or `$onRejected`, whichever is called, or will reject with -the thrown exception if either throws. - -A promise makes the following guarantees about handlers registered in -the same call to `then()`: - - 1. Only one of `$onFulfilled` or `$onRejected` will be called, - never both. - 2. `$onFulfilled` and `$onRejected` will never be called more - than once. - -#### See also - -* [resolve()](#resolve) - Creating a resolved promise -* [reject()](#reject) - Creating a rejected promise - -#### PromiseInterface::catch() - -```php -$promise->catch(callable $onRejected); -``` - -Registers a rejection handler for promise. It is a shortcut for: - -```php -$promise->then(null, $onRejected); -``` - -Additionally, you can type hint the `$reason` argument of `$onRejected` to catch -only specific errors. - -```php -$promise - ->catch(function (\RuntimeException $reason) { - // Only catch \RuntimeException instances - // All other types of errors will propagate automatically - }) - ->catch(function (\Throwable $reason) { - // Catch other errors - }); -``` - -#### PromiseInterface::finally() - -```php -$newPromise = $promise->finally(callable $onFulfilledOrRejected); -``` - -Allows you to execute "cleanup" type tasks in a promise chain. - -It arranges for `$onFulfilledOrRejected` to be called, with no arguments, -when the promise is either fulfilled or rejected. - -* If `$promise` fulfills, and `$onFulfilledOrRejected` returns successfully, - `$newPromise` will fulfill with the same value as `$promise`. -* If `$promise` fulfills, and `$onFulfilledOrRejected` throws or returns a - rejected promise, `$newPromise` will reject with the thrown exception or - rejected promise's reason. -* If `$promise` rejects, and `$onFulfilledOrRejected` returns successfully, - `$newPromise` will reject with the same reason as `$promise`. -* If `$promise` rejects, and `$onFulfilledOrRejected` throws or returns a - rejected promise, `$newPromise` will reject with the thrown exception or - rejected promise's reason. - -`finally()` behaves similarly to the synchronous finally statement. When combined -with `catch()`, `finally()` allows you to write code that is similar to the familiar -synchronous catch/finally pair. - -Consider the following synchronous code: - -```php -try { - return doSomething(); -} catch (\Throwable $e) { - return handleError($e); -} finally { - cleanup(); -} -``` - -Similar asynchronous code (with `doSomething()` that returns a promise) can be -written: - -```php -return doSomething() - ->catch('handleError') - ->finally('cleanup'); -``` - -#### PromiseInterface::cancel() - -``` php -$promise->cancel(); -``` - -The `cancel()` method notifies the creator of the promise that there is no -further interest in the results of the operation. - -Once a promise is settled (either fulfilled or rejected), calling `cancel()` on -a promise has no effect. - -#### ~~PromiseInterface::otherwise()~~ - -> Deprecated since v3.0.0, see [`catch()`](#promiseinterfacecatch) instead. - -The `otherwise()` method registers a rejection handler for a promise. - -This method continues to exist only for BC reasons and to ease upgrading -between versions. It is an alias for: - -```php -$promise->catch($onRejected); -``` - -#### ~~PromiseInterface::always()~~ - -> Deprecated since v3.0.0, see [`finally()`](#promiseinterfacefinally) instead. - -The `always()` method allows you to execute "cleanup" type tasks in a promise chain. - -This method continues to exist only for BC reasons and to ease upgrading -between versions. It is an alias for: - -```php -$promise->finally($onFulfilledOrRejected); -``` - -### Promise - -Creates a promise whose state is controlled by the functions passed to -`$resolver`. - -```php -$resolver = function (callable $resolve, callable $reject) { - // Do some work, possibly asynchronously, and then - // resolve or reject. - - $resolve($awesomeResult); - // or throw new Exception('Promise rejected'); - // or $resolve($anotherPromise); - // or $reject($nastyError); -}; - -$canceller = function () { - // Cancel/abort any running operations like network connections, streams etc. - - // Reject promise by throwing an exception - throw new Exception('Promise cancelled'); -}; - -$promise = new React\Promise\Promise($resolver, $canceller); -``` - -The promise constructor receives a resolver function and an optional canceller -function which both will be called with two arguments: - - * `$resolve($value)` - Primary function that seals the fate of the - returned promise. Accepts either a non-promise value, or another promise. - When called with a non-promise value, fulfills promise with that value. - When called with another promise, e.g. `$resolve($otherPromise)`, promise's - fate will be equivalent to that of `$otherPromise`. - * `$reject($reason)` - Function that rejects the promise. It is recommended to - just throw an exception instead of using `$reject()`. - -If the resolver or canceller throw an exception, the promise will be rejected -with that thrown exception as the rejection reason. - -The resolver function will be called immediately, the canceller function only -once all consumers called the `cancel()` method of the promise. - -### Functions - -Useful functions for creating and joining collections of promises. - -All functions working on promise collections (like `all()`, `race()`, -etc.) support cancellation. This means, if you call `cancel()` on the returned -promise, all promises in the collection are cancelled. - -#### resolve() - -```php -$promise = React\Promise\resolve(mixed $promiseOrValue); -``` - -Creates a promise for the supplied `$promiseOrValue`. - -If `$promiseOrValue` is a value, it will be the resolution value of the -returned promise. - -If `$promiseOrValue` is a thenable (any object that provides a `then()` method), -a trusted promise that follows the state of the thenable is returned. - -If `$promiseOrValue` is a promise, it will be returned as is. - -The resulting `$promise` implements the [`PromiseInterface`](#promiseinterface) -and can be consumed like any other promise: - -```php -$promise = React\Promise\resolve(42); - -$promise->then(function (int $result): void { - var_dump($result); -}, function (\Throwable $e): void { - echo 'Error: ' . $e->getMessage() . PHP_EOL; -}); -``` - -#### reject() - -```php -$promise = React\Promise\reject(\Throwable $reason); -``` - -Creates a rejected promise for the supplied `$reason`. - -Note that the [`\Throwable`](https://www.php.net/manual/en/class.throwable.php) interface introduced in PHP 7 covers -both user land [`\Exception`](https://www.php.net/manual/en/class.exception.php)'s and -[`\Error`](https://www.php.net/manual/en/class.error.php) internal PHP errors. By enforcing `\Throwable` as reason to -reject a promise, any language error or user land exception can be used to reject a promise. - -The resulting `$promise` implements the [`PromiseInterface`](#promiseinterface) -and can be consumed like any other promise: - -```php -$promise = React\Promise\reject(new RuntimeException('Request failed')); - -$promise->then(function (int $result): void { - var_dump($result); -}, function (\Throwable $e): void { - echo 'Error: ' . $e->getMessage() . PHP_EOL; -}); -``` - -Note that rejected promises should always be handled similar to how any -exceptions should always be caught in a `try` + `catch` block. If you remove the -last reference to a rejected promise that has not been handled, it will -report an unhandled promise rejection: - -```php -function incorrect(): int -{ - $promise = React\Promise\reject(new RuntimeException('Request failed')); - - // Commented out: No rejection handler registered here. - // $promise->then(null, function (\Throwable $e): void { /* ignore */ }); - - // Returning from a function will remove all local variable references, hence why - // this will report an unhandled promise rejection here. - return 42; -} - -// Calling this function will log an error message plus its stack trace: -// Unhandled promise rejection with RuntimeException: Request failed in example.php:10 -incorrect(); -``` - -A rejected promise will be considered "handled" if you catch the rejection -reason with either the [`then()` method](#promiseinterfacethen), the -[`catch()` method](#promiseinterfacecatch), or the -[`finally()` method](#promiseinterfacefinally). Note that each of these methods -return a new promise that may again be rejected if you re-throw an exception. - -A rejected promise will also be considered "handled" if you abort the operation -with the [`cancel()` method](#promiseinterfacecancel) (which in turn would -usually reject the promise if it is still pending). - -See also the [`set_rejection_handler()` function](#set_rejection_handler). - -#### all() - -```php -$promise = React\Promise\all(iterable $promisesOrValues); -``` - -Returns a promise that will resolve only once all the items in -`$promisesOrValues` have resolved. The resolution value of the returned promise -will be an array containing the resolution values of each of the items in -`$promisesOrValues`. - -#### race() - -```php -$promise = React\Promise\race(iterable $promisesOrValues); -``` - -Initiates a competitive race that allows one winner. Returns a promise which is -resolved in the same way the first settled promise resolves. - -The returned promise will become **infinitely pending** if `$promisesOrValues` -contains 0 items. - -#### any() - -```php -$promise = React\Promise\any(iterable $promisesOrValues); -``` - -Returns a promise that will resolve when any one of the items in -`$promisesOrValues` resolves. The resolution value of the returned promise -will be the resolution value of the triggering item. - -The returned promise will only reject if *all* items in `$promisesOrValues` are -rejected. The rejection value will be a `React\Promise\Exception\CompositeException` -which holds all rejection reasons. The rejection reasons can be obtained with -`CompositeException::getThrowables()`. - -The returned promise will also reject with a `React\Promise\Exception\LengthException` -if `$promisesOrValues` contains 0 items. - -#### set_rejection_handler() - -```php -React\Promise\set_rejection_handler(?callable $callback): ?callable; -``` - -Sets the global rejection handler for unhandled promise rejections. - -Note that rejected promises should always be handled similar to how any -exceptions should always be caught in a `try` + `catch` block. If you remove -the last reference to a rejected promise that has not been handled, it will -report an unhandled promise rejection. See also the [`reject()` function](#reject) -for more details. - -The `?callable $callback` argument MUST be a valid callback function that -accepts a single `Throwable` argument or a `null` value to restore the -default promise rejection handler. The return value of the callback function -will be ignored and has no effect, so you SHOULD return a `void` value. The -callback function MUST NOT throw or the program will be terminated with a -fatal error. - -The function returns the previous rejection handler or `null` if using the -default promise rejection handler. - -The default promise rejection handler will log an error message plus its stack -trace: - -```php -// Unhandled promise rejection with RuntimeException: Unhandled in example.php:2 -React\Promise\reject(new RuntimeException('Unhandled')); -``` - -The promise rejection handler may be used to use customize the log message or -write to custom log targets. As a rule of thumb, this function should only be -used as a last resort and promise rejections are best handled with either the -[`then()` method](#promiseinterfacethen), the -[`catch()` method](#promiseinterfacecatch), or the -[`finally()` method](#promiseinterfacefinally). -See also the [`reject()` function](#reject) for more details. - -Examples --------- - -### How to use Deferred - -```php -function getAwesomeResultPromise() -{ - $deferred = new React\Promise\Deferred(); - - // Execute a Node.js-style function using the callback pattern - computeAwesomeResultAsynchronously(function (\Throwable $error, $result) use ($deferred) { - if ($error) { - $deferred->reject($error); - } else { - $deferred->resolve($result); - } - }); - - // Return the promise - return $deferred->promise(); -} - -getAwesomeResultPromise() - ->then( - function ($value) { - // Deferred resolved, do something with $value - }, - function (\Throwable $reason) { - // Deferred rejected, do something with $reason - } - ); -``` - -### How promise forwarding works - -A few simple examples to show how the mechanics of Promises/A forwarding works. -These examples are contrived, of course, and in real usage, promise chains will -typically be spread across several function calls, or even several levels of -your application architecture. - -#### Resolution forwarding - -Resolved promises forward resolution values to the next promise. -The first promise, `$deferred->promise()`, will resolve with the value passed -to `$deferred->resolve()` below. - -Each call to `then()` returns a new promise that will resolve with the return -value of the previous handler. This creates a promise "pipeline". - -```php -$deferred = new React\Promise\Deferred(); - -$deferred->promise() - ->then(function ($x) { - // $x will be the value passed to $deferred->resolve() below - // and returns a *new promise* for $x + 1 - return $x + 1; - }) - ->then(function ($x) { - // $x === 2 - // This handler receives the return value of the - // previous handler. - return $x + 1; - }) - ->then(function ($x) { - // $x === 3 - // This handler receives the return value of the - // previous handler. - return $x + 1; - }) - ->then(function ($x) { - // $x === 4 - // This handler receives the return value of the - // previous handler. - echo 'Resolve ' . $x; - }); - -$deferred->resolve(1); // Prints "Resolve 4" -``` - -#### Rejection forwarding - -Rejected promises behave similarly, and also work similarly to try/catch: -When you catch an exception, you must rethrow for it to propagate. - -Similarly, when you handle a rejected promise, to propagate the rejection, -"rethrow" it by either returning a rejected promise, or actually throwing -(since promise translates thrown exceptions into rejections) - -```php -$deferred = new React\Promise\Deferred(); - -$deferred->promise() - ->then(function ($x) { - throw new \Exception($x + 1); - }) - ->catch(function (\Exception $x) { - // Propagate the rejection - throw $x; - }) - ->catch(function (\Exception $x) { - // Can also propagate by returning another rejection - return React\Promise\reject( - new \Exception($x->getMessage() + 1) - ); - }) - ->catch(function ($x) { - echo 'Reject ' . $x->getMessage(); // 3 - }); - -$deferred->resolve(1); // Prints "Reject 3" -``` - -#### Mixed resolution and rejection forwarding - -Just like try/catch, you can choose to propagate or not. Mixing resolutions and -rejections will still forward handler results in a predictable way. - -```php -$deferred = new React\Promise\Deferred(); - -$deferred->promise() - ->then(function ($x) { - return $x + 1; - }) - ->then(function ($x) { - throw new \Exception($x + 1); - }) - ->catch(function (\Exception $x) { - // Handle the rejection, and don't propagate. - // This is like catch without a rethrow - return $x->getMessage() + 1; - }) - ->then(function ($x) { - echo 'Mixed ' . $x; // 4 - }); - -$deferred->resolve(1); // Prints "Mixed 4" -``` - -Install -------- - -The recommended way to install this library is [through Composer](https://getcomposer.org/). -[New to Composer?](https://getcomposer.org/doc/00-intro.md) - -This project follows [SemVer](https://semver.org/). -This will install the latest supported version from this branch: - -```bash -composer require react/promise:^3.2 -``` - -See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades. - -This project aims to run on any platform and thus does not require any PHP -extensions and supports running on PHP 7.1 through current PHP 8+. -It's *highly recommended to use the latest supported PHP version* for this project. - -We're committed to providing long-term support (LTS) options and to provide a -smooth upgrade path. If you're using an older PHP version, you may use the -[`2.x` branch](https://github.com/reactphp/promise/tree/2.x) (PHP 5.4+) or -[`1.x` branch](https://github.com/reactphp/promise/tree/1.x) (PHP 5.3+) which both -provide a compatible API but do not take advantage of newer language features. -You may target multiple versions at the same time to support a wider range of -PHP versions like this: - -```bash -composer require "react/promise:^3 || ^2 || ^1" -``` - -## Tests - -To run the test suite, you first need to clone this repo and then install all -dependencies [through Composer](https://getcomposer.org/): - -```bash -composer install -``` - -To run the test suite, go to the project root and run: - -```bash -vendor/bin/phpunit -``` - -On top of this, we use PHPStan on max level to ensure type safety across the project: - -```bash -vendor/bin/phpstan -``` - -Credits -------- - -Promise is a port of [when.js](https://github.com/cujojs/when) -by [Brian Cavalier](https://github.com/briancavalier). - -Also, large parts of the documentation have been ported from the when.js -[Wiki](https://github.com/cujojs/when/wiki) and the -[API docs](https://github.com/cujojs/when/blob/master/docs/api.md). - -License -------- - -Released under the [MIT](LICENSE) license. diff --git a/digital_doctor/vendor/react/promise/composer.json b/digital_doctor/vendor/react/promise/composer.json deleted file mode 100644 index 5d1e277..0000000 --- a/digital_doctor/vendor/react/promise/composer.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "name": "react/promise", - "description": "A lightweight implementation of CommonJS Promises/A for PHP", - "license": "MIT", - "authors": [ - { - "name": "Jan Sorgalla", - "homepage": "https://sorgalla.com/", - "email": "jsorgalla@gmail.com" - }, - { - "name": "Christian Lück", - "homepage": "https://clue.engineering/", - "email": "christian@clue.engineering" - }, - { - "name": "Cees-Jan Kiewiet", - "homepage": "https://wyrihaximus.net/", - "email": "reactphp@ceesjankiewiet.nl" - }, - { - "name": "Chris Boden", - "homepage": "https://cboden.dev/", - "email": "cboden@gmail.com" - } - ], - "require": { - "php": ">=7.1.0" - }, - "require-dev": { - "phpstan/phpstan": "1.10.39 || 1.4.10", - "phpunit/phpunit": "^9.6 || ^7.5" - }, - "autoload": { - "psr-4": { - "React\\Promise\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] - }, - "autoload-dev": { - "psr-4": { - "React\\Promise\\": [ - "tests/fixtures/", - "tests/" - ] - }, - "files": [ - "tests/Fiber.php" - ] - }, - "keywords": [ - "promise", - "promises" - ] -} diff --git a/digital_doctor/vendor/react/promise/src/Deferred.php b/digital_doctor/vendor/react/promise/src/Deferred.php deleted file mode 100644 index 80b8fcf..0000000 --- a/digital_doctor/vendor/react/promise/src/Deferred.php +++ /dev/null @@ -1,52 +0,0 @@ - - */ - private $promise; - - /** @var callable(T):void */ - private $resolveCallback; - - /** @var callable(\Throwable):void */ - private $rejectCallback; - - /** - * @param (callable(callable(T):void,callable(\Throwable):void):void)|null $canceller - */ - public function __construct(?callable $canceller = null) - { - $this->promise = new Promise(function ($resolve, $reject): void { - $this->resolveCallback = $resolve; - $this->rejectCallback = $reject; - }, $canceller); - } - - /** - * @return PromiseInterface - */ - public function promise(): PromiseInterface - { - return $this->promise; - } - - /** - * @param T $value - */ - public function resolve($value): void - { - ($this->resolveCallback)($value); - } - - public function reject(\Throwable $reason): void - { - ($this->rejectCallback)($reason); - } -} diff --git a/digital_doctor/vendor/react/promise/src/Exception/CompositeException.php b/digital_doctor/vendor/react/promise/src/Exception/CompositeException.php deleted file mode 100644 index 2e672a0..0000000 --- a/digital_doctor/vendor/react/promise/src/Exception/CompositeException.php +++ /dev/null @@ -1,32 +0,0 @@ -throwables = $throwables; - } - - /** - * @return \Throwable[] - */ - public function getThrowables(): array - { - return $this->throwables; - } -} diff --git a/digital_doctor/vendor/react/promise/src/Exception/LengthException.php b/digital_doctor/vendor/react/promise/src/Exception/LengthException.php deleted file mode 100644 index 775c48d..0000000 --- a/digital_doctor/vendor/react/promise/src/Exception/LengthException.php +++ /dev/null @@ -1,7 +0,0 @@ -started) { - return; - } - - $this->started = true; - $this->drain(); - } - - /** - * @param mixed $cancellable - */ - public function enqueue($cancellable): void - { - if (!\is_object($cancellable) || !\method_exists($cancellable, 'then') || !\method_exists($cancellable, 'cancel')) { - return; - } - - $length = \array_push($this->queue, $cancellable); - - if ($this->started && 1 === $length) { - $this->drain(); - } - } - - private function drain(): void - { - for ($i = \key($this->queue); isset($this->queue[$i]); $i++) { - $cancellable = $this->queue[$i]; - assert(\method_exists($cancellable, 'cancel')); - - $exception = null; - - try { - $cancellable->cancel(); - } catch (\Throwable $exception) { - } - - unset($this->queue[$i]); - - if ($exception) { - throw $exception; - } - } - - $this->queue = []; - } -} diff --git a/digital_doctor/vendor/react/promise/src/Internal/FulfilledPromise.php b/digital_doctor/vendor/react/promise/src/Internal/FulfilledPromise.php deleted file mode 100644 index 8664ffd..0000000 --- a/digital_doctor/vendor/react/promise/src/Internal/FulfilledPromise.php +++ /dev/null @@ -1,89 +0,0 @@ - - */ -final class FulfilledPromise implements PromiseInterface -{ - /** @var T */ - private $value; - - /** - * @param T $value - * @throws \InvalidArgumentException - */ - public function __construct($value = null) - { - if ($value instanceof PromiseInterface) { - throw new \InvalidArgumentException('You cannot create React\Promise\FulfilledPromise with a promise. Use React\Promise\resolve($promiseOrValue) instead.'); - } - - $this->value = $value; - } - - /** - * @template TFulfilled - * @param ?(callable((T is void ? null : T)): (PromiseInterface|TFulfilled)) $onFulfilled - * @return PromiseInterface<($onFulfilled is null ? T : TFulfilled)> - */ - public function then(?callable $onFulfilled = null, ?callable $onRejected = null): PromiseInterface - { - if (null === $onFulfilled) { - return $this; - } - - try { - /** - * @var PromiseInterface|T $result - */ - $result = $onFulfilled($this->value); - return resolve($result); - } catch (\Throwable $exception) { - return new RejectedPromise($exception); - } - } - - public function catch(callable $onRejected): PromiseInterface - { - return $this; - } - - public function finally(callable $onFulfilledOrRejected): PromiseInterface - { - return $this->then(function ($value) use ($onFulfilledOrRejected): PromiseInterface { - return resolve($onFulfilledOrRejected())->then(function () use ($value) { - return $value; - }); - }); - } - - public function cancel(): void - { - } - - /** - * @deprecated 3.0.0 Use `catch()` instead - * @see self::catch() - */ - public function otherwise(callable $onRejected): PromiseInterface - { - return $this->catch($onRejected); - } - - /** - * @deprecated 3.0.0 Use `finally()` instead - * @see self::finally() - */ - public function always(callable $onFulfilledOrRejected): PromiseInterface - { - return $this->finally($onFulfilledOrRejected); - } -} diff --git a/digital_doctor/vendor/react/promise/src/Internal/RejectedPromise.php b/digital_doctor/vendor/react/promise/src/Internal/RejectedPromise.php deleted file mode 100644 index aa1dff3..0000000 --- a/digital_doctor/vendor/react/promise/src/Internal/RejectedPromise.php +++ /dev/null @@ -1,128 +0,0 @@ - - */ -final class RejectedPromise implements PromiseInterface -{ - /** @var \Throwable */ - private $reason; - - /** @var bool */ - private $handled = false; - - /** - * @param \Throwable $reason - */ - public function __construct(\Throwable $reason) - { - $this->reason = $reason; - } - - /** @throws void */ - public function __destruct() - { - if ($this->handled) { - return; - } - - $handler = set_rejection_handler(null); - if ($handler === null) { - $message = 'Unhandled promise rejection with ' . $this->reason; - - \error_log($message); - return; - } - - try { - $handler($this->reason); - } catch (\Throwable $e) { - \preg_match('/^([^:\s]++)(.*+)$/sm', (string) $e, $match); - \assert(isset($match[1], $match[2])); - $message = 'Fatal error: Uncaught ' . $match[1] . ' from unhandled promise rejection handler' . $match[2]; - - \error_log($message); - exit(255); - } - } - - /** - * @template TRejected - * @param ?callable $onFulfilled - * @param ?(callable(\Throwable): (PromiseInterface|TRejected)) $onRejected - * @return PromiseInterface<($onRejected is null ? never : TRejected)> - */ - public function then(?callable $onFulfilled = null, ?callable $onRejected = null): PromiseInterface - { - if (null === $onRejected) { - return $this; - } - - $this->handled = true; - - try { - return resolve($onRejected($this->reason)); - } catch (\Throwable $exception) { - return new RejectedPromise($exception); - } - } - - /** - * @template TThrowable of \Throwable - * @template TRejected - * @param callable(TThrowable): (PromiseInterface|TRejected) $onRejected - * @return PromiseInterface - */ - public function catch(callable $onRejected): PromiseInterface - { - if (!_checkTypehint($onRejected, $this->reason)) { - return $this; - } - - /** - * @var callable(\Throwable):(PromiseInterface|TRejected) $onRejected - */ - return $this->then(null, $onRejected); - } - - public function finally(callable $onFulfilledOrRejected): PromiseInterface - { - return $this->then(null, function (\Throwable $reason) use ($onFulfilledOrRejected): PromiseInterface { - return resolve($onFulfilledOrRejected())->then(function () use ($reason): PromiseInterface { - return new RejectedPromise($reason); - }); - }); - } - - public function cancel(): void - { - $this->handled = true; - } - - /** - * @deprecated 3.0.0 Use `catch()` instead - * @see self::catch() - */ - public function otherwise(callable $onRejected): PromiseInterface - { - return $this->catch($onRejected); - } - - /** - * @deprecated 3.0.0 Use `always()` instead - * @see self::always() - */ - public function always(callable $onFulfilledOrRejected): PromiseInterface - { - return $this->finally($onFulfilledOrRejected); - } -} diff --git a/digital_doctor/vendor/react/promise/src/Promise.php b/digital_doctor/vendor/react/promise/src/Promise.php deleted file mode 100644 index 4ac2700..0000000 --- a/digital_doctor/vendor/react/promise/src/Promise.php +++ /dev/null @@ -1,303 +0,0 @@ - - */ -final class Promise implements PromiseInterface -{ - /** @var (callable(callable(T):void,callable(\Throwable):void):void)|null */ - private $canceller; - - /** @var ?PromiseInterface */ - private $result; - - /** @var list):void> */ - private $handlers = []; - - /** @var int */ - private $requiredCancelRequests = 0; - - /** @var bool */ - private $cancelled = false; - - /** - * @param callable(callable(T):void,callable(\Throwable):void):void $resolver - * @param (callable(callable(T):void,callable(\Throwable):void):void)|null $canceller - */ - public function __construct(callable $resolver, ?callable $canceller = null) - { - $this->canceller = $canceller; - - // Explicitly overwrite arguments with null values before invoking - // resolver function. This ensure that these arguments do not show up - // in the stack trace in PHP 7+ only. - $cb = $resolver; - $resolver = $canceller = null; - $this->call($cb); - } - - public function then(?callable $onFulfilled = null, ?callable $onRejected = null): PromiseInterface - { - if (null !== $this->result) { - return $this->result->then($onFulfilled, $onRejected); - } - - if (null === $this->canceller) { - return new static($this->resolver($onFulfilled, $onRejected)); - } - - // This promise has a canceller, so we create a new child promise which - // has a canceller that invokes the parent canceller if all other - // followers are also cancelled. We keep a reference to this promise - // instance for the static canceller function and clear this to avoid - // keeping a cyclic reference between parent and follower. - $parent = $this; - ++$parent->requiredCancelRequests; - - return new static( - $this->resolver($onFulfilled, $onRejected), - static function () use (&$parent): void { - assert($parent instanceof self); - --$parent->requiredCancelRequests; - - if ($parent->requiredCancelRequests <= 0) { - $parent->cancel(); - } - - $parent = null; - } - ); - } - - /** - * @template TThrowable of \Throwable - * @template TRejected - * @param callable(TThrowable): (PromiseInterface|TRejected) $onRejected - * @return PromiseInterface - */ - public function catch(callable $onRejected): PromiseInterface - { - return $this->then(null, static function (\Throwable $reason) use ($onRejected) { - if (!_checkTypehint($onRejected, $reason)) { - return new RejectedPromise($reason); - } - - /** - * @var callable(\Throwable):(PromiseInterface|TRejected) $onRejected - */ - return $onRejected($reason); - }); - } - - public function finally(callable $onFulfilledOrRejected): PromiseInterface - { - return $this->then(static function ($value) use ($onFulfilledOrRejected): PromiseInterface { - return resolve($onFulfilledOrRejected())->then(function () use ($value) { - return $value; - }); - }, static function (\Throwable $reason) use ($onFulfilledOrRejected): PromiseInterface { - return resolve($onFulfilledOrRejected())->then(function () use ($reason): RejectedPromise { - return new RejectedPromise($reason); - }); - }); - } - - public function cancel(): void - { - $this->cancelled = true; - $canceller = $this->canceller; - $this->canceller = null; - - $parentCanceller = null; - - if (null !== $this->result) { - // Forward cancellation to rejected promise to avoid reporting unhandled rejection - if ($this->result instanceof RejectedPromise) { - $this->result->cancel(); - } - - // Go up the promise chain and reach the top most promise which is - // itself not following another promise - $root = $this->unwrap($this->result); - - // Return if the root promise is already resolved or a - // FulfilledPromise or RejectedPromise - if (!$root instanceof self || null !== $root->result) { - return; - } - - $root->requiredCancelRequests--; - - if ($root->requiredCancelRequests <= 0) { - $parentCanceller = [$root, 'cancel']; - } - } - - if (null !== $canceller) { - $this->call($canceller); - } - - // For BC, we call the parent canceller after our own canceller - if ($parentCanceller) { - $parentCanceller(); - } - } - - /** - * @deprecated 3.0.0 Use `catch()` instead - * @see self::catch() - */ - public function otherwise(callable $onRejected): PromiseInterface - { - return $this->catch($onRejected); - } - - /** - * @deprecated 3.0.0 Use `finally()` instead - * @see self::finally() - */ - public function always(callable $onFulfilledOrRejected): PromiseInterface - { - return $this->finally($onFulfilledOrRejected); - } - - private function resolver(?callable $onFulfilled = null, ?callable $onRejected = null): callable - { - return function (callable $resolve, callable $reject) use ($onFulfilled, $onRejected): void { - $this->handlers[] = static function (PromiseInterface $promise) use ($onFulfilled, $onRejected, $resolve, $reject): void { - $promise = $promise->then($onFulfilled, $onRejected); - - if ($promise instanceof self && $promise->result === null) { - $promise->handlers[] = static function (PromiseInterface $promise) use ($resolve, $reject): void { - $promise->then($resolve, $reject); - }; - } else { - $promise->then($resolve, $reject); - } - }; - }; - } - - private function reject(\Throwable $reason): void - { - if (null !== $this->result) { - return; - } - - $this->settle(reject($reason)); - } - - /** - * @param PromiseInterface $result - */ - private function settle(PromiseInterface $result): void - { - $result = $this->unwrap($result); - - if ($result === $this) { - $result = new RejectedPromise( - new \LogicException('Cannot resolve a promise with itself.') - ); - } - - if ($result instanceof self) { - $result->requiredCancelRequests++; - } else { - // Unset canceller only when not following a pending promise - $this->canceller = null; - } - - $handlers = $this->handlers; - - $this->handlers = []; - $this->result = $result; - - foreach ($handlers as $handler) { - $handler($result); - } - - // Forward cancellation to rejected promise to avoid reporting unhandled rejection - if ($this->cancelled && $result instanceof RejectedPromise) { - $result->cancel(); - } - } - - /** - * @param PromiseInterface $promise - * @return PromiseInterface - */ - private function unwrap(PromiseInterface $promise): PromiseInterface - { - while ($promise instanceof self && null !== $promise->result) { - /** @var PromiseInterface $promise */ - $promise = $promise->result; - } - - return $promise; - } - - /** - * @param callable(callable(mixed):void,callable(\Throwable):void):void $cb - */ - private function call(callable $cb): void - { - // Explicitly overwrite argument with null value. This ensure that this - // argument does not show up in the stack trace in PHP 7+ only. - $callback = $cb; - $cb = null; - - // Use reflection to inspect number of arguments expected by this callback. - // We did some careful benchmarking here: Using reflection to avoid unneeded - // function arguments is actually faster than blindly passing them. - // Also, this helps avoiding unnecessary function arguments in the call stack - // if the callback creates an Exception (creating garbage cycles). - if (\is_array($callback)) { - $ref = new \ReflectionMethod($callback[0], $callback[1]); - } elseif (\is_object($callback) && !$callback instanceof \Closure) { - $ref = new \ReflectionMethod($callback, '__invoke'); - } else { - assert($callback instanceof \Closure || \is_string($callback)); - $ref = new \ReflectionFunction($callback); - } - $args = $ref->getNumberOfParameters(); - - try { - if ($args === 0) { - $callback(); - } else { - // Keep references to this promise instance for the static resolve/reject functions. - // By using static callbacks that are not bound to this instance - // and passing the target promise instance by reference, we can - // still execute its resolving logic and still clear this - // reference when settling the promise. This helps avoiding - // garbage cycles if any callback creates an Exception. - // These assumptions are covered by the test suite, so if you ever feel like - // refactoring this, go ahead, any alternative suggestions are welcome! - $target =& $this; - - $callback( - static function ($value) use (&$target): void { - if ($target !== null) { - $target->settle(resolve($value)); - $target = null; - } - }, - static function (\Throwable $reason) use (&$target): void { - if ($target !== null) { - $target->reject($reason); - $target = null; - } - } - ); - } - } catch (\Throwable $e) { - $target = null; - $this->reject($e); - } - } -} diff --git a/digital_doctor/vendor/react/promise/src/PromiseInterface.php b/digital_doctor/vendor/react/promise/src/PromiseInterface.php deleted file mode 100644 index 5869f76..0000000 --- a/digital_doctor/vendor/react/promise/src/PromiseInterface.php +++ /dev/null @@ -1,152 +0,0 @@ -|TFulfilled)) $onFulfilled - * @param ?(callable(\Throwable): (PromiseInterface|TRejected)) $onRejected - * @return PromiseInterface<($onRejected is null ? ($onFulfilled is null ? T : TFulfilled) : ($onFulfilled is null ? T|TRejected : TFulfilled|TRejected))> - */ - public function then(?callable $onFulfilled = null, ?callable $onRejected = null): PromiseInterface; - - /** - * Registers a rejection handler for promise. It is a shortcut for: - * - * ```php - * $promise->then(null, $onRejected); - * ``` - * - * Additionally, you can type hint the `$reason` argument of `$onRejected` to catch - * only specific errors. - * - * @template TThrowable of \Throwable - * @template TRejected - * @param callable(TThrowable): (PromiseInterface|TRejected) $onRejected - * @return PromiseInterface - */ - public function catch(callable $onRejected): PromiseInterface; - - /** - * Allows you to execute "cleanup" type tasks in a promise chain. - * - * It arranges for `$onFulfilledOrRejected` to be called, with no arguments, - * when the promise is either fulfilled or rejected. - * - * * If `$promise` fulfills, and `$onFulfilledOrRejected` returns successfully, - * `$newPromise` will fulfill with the same value as `$promise`. - * * If `$promise` fulfills, and `$onFulfilledOrRejected` throws or returns a - * rejected promise, `$newPromise` will reject with the thrown exception or - * rejected promise's reason. - * * If `$promise` rejects, and `$onFulfilledOrRejected` returns successfully, - * `$newPromise` will reject with the same reason as `$promise`. - * * If `$promise` rejects, and `$onFulfilledOrRejected` throws or returns a - * rejected promise, `$newPromise` will reject with the thrown exception or - * rejected promise's reason. - * - * `finally()` behaves similarly to the synchronous finally statement. When combined - * with `catch()`, `finally()` allows you to write code that is similar to the familiar - * synchronous catch/finally pair. - * - * Consider the following synchronous code: - * - * ```php - * try { - * return doSomething(); - * } catch(\Exception $e) { - * return handleError($e); - * } finally { - * cleanup(); - * } - * ``` - * - * Similar asynchronous code (with `doSomething()` that returns a promise) can be - * written: - * - * ```php - * return doSomething() - * ->catch('handleError') - * ->finally('cleanup'); - * ``` - * - * @param callable(): (void|PromiseInterface) $onFulfilledOrRejected - * @return PromiseInterface - */ - public function finally(callable $onFulfilledOrRejected): PromiseInterface; - - /** - * The `cancel()` method notifies the creator of the promise that there is no - * further interest in the results of the operation. - * - * Once a promise is settled (either fulfilled or rejected), calling `cancel()` on - * a promise has no effect. - * - * @return void - */ - public function cancel(): void; - - /** - * [Deprecated] Registers a rejection handler for a promise. - * - * This method continues to exist only for BC reasons and to ease upgrading - * between versions. It is an alias for: - * - * ```php - * $promise->catch($onRejected); - * ``` - * - * @template TThrowable of \Throwable - * @template TRejected - * @param callable(TThrowable): (PromiseInterface|TRejected) $onRejected - * @return PromiseInterface - * @deprecated 3.0.0 Use catch() instead - * @see self::catch() - */ - public function otherwise(callable $onRejected): PromiseInterface; - - /** - * [Deprecated] Allows you to execute "cleanup" type tasks in a promise chain. - * - * This method continues to exist only for BC reasons and to ease upgrading - * between versions. It is an alias for: - * - * ```php - * $promise->finally($onFulfilledOrRejected); - * ``` - * - * @param callable(): (void|PromiseInterface) $onFulfilledOrRejected - * @return PromiseInterface - * @deprecated 3.0.0 Use finally() instead - * @see self::finally() - */ - public function always(callable $onFulfilledOrRejected): PromiseInterface; -} diff --git a/digital_doctor/vendor/react/promise/src/functions.php b/digital_doctor/vendor/react/promise/src/functions.php deleted file mode 100644 index 2aab877..0000000 --- a/digital_doctor/vendor/react/promise/src/functions.php +++ /dev/null @@ -1,345 +0,0 @@ -|T $promiseOrValue - * @return PromiseInterface - */ -function resolve($promiseOrValue): PromiseInterface -{ - if ($promiseOrValue instanceof PromiseInterface) { - return $promiseOrValue; - } - - if (\is_object($promiseOrValue) && \method_exists($promiseOrValue, 'then')) { - $canceller = null; - - if (\method_exists($promiseOrValue, 'cancel')) { - $canceller = [$promiseOrValue, 'cancel']; - assert(\is_callable($canceller)); - } - - /** @var Promise */ - return new Promise(function (callable $resolve, callable $reject) use ($promiseOrValue): void { - $promiseOrValue->then($resolve, $reject); - }, $canceller); - } - - return new FulfilledPromise($promiseOrValue); -} - -/** - * Creates a rejected promise for the supplied `$reason`. - * - * If `$reason` is a value, it will be the rejection value of the - * returned promise. - * - * If `$reason` is a promise, its completion value will be the rejected - * value of the returned promise. - * - * This can be useful in situations where you need to reject a promise without - * throwing an exception. For example, it allows you to propagate a rejection with - * the value of another promise. - * - * @return PromiseInterface - */ -function reject(\Throwable $reason): PromiseInterface -{ - return new RejectedPromise($reason); -} - -/** - * Returns a promise that will resolve only once all the items in - * `$promisesOrValues` have resolved. The resolution value of the returned promise - * will be an array containing the resolution values of each of the items in - * `$promisesOrValues`. - * - * @template T - * @param iterable|T> $promisesOrValues - * @return PromiseInterface> - */ -function all(iterable $promisesOrValues): PromiseInterface -{ - $cancellationQueue = new Internal\CancellationQueue(); - - /** @var Promise> */ - return new Promise(function (callable $resolve, callable $reject) use ($promisesOrValues, $cancellationQueue): void { - $toResolve = 0; - /** @var bool */ - $continue = true; - $values = []; - - foreach ($promisesOrValues as $i => $promiseOrValue) { - $cancellationQueue->enqueue($promiseOrValue); - $values[$i] = null; - ++$toResolve; - - resolve($promiseOrValue)->then( - function ($value) use ($i, &$values, &$toResolve, &$continue, $resolve): void { - $values[$i] = $value; - - if (0 === --$toResolve && !$continue) { - $resolve($values); - } - }, - function (\Throwable $reason) use (&$continue, $reject): void { - $continue = false; - $reject($reason); - } - ); - - if (!$continue && !\is_array($promisesOrValues)) { - break; - } - } - - $continue = false; - if ($toResolve === 0) { - $resolve($values); - } - }, $cancellationQueue); -} - -/** - * Initiates a competitive race that allows one winner. Returns a promise which is - * resolved in the same way the first settled promise resolves. - * - * The returned promise will become **infinitely pending** if `$promisesOrValues` - * contains 0 items. - * - * @template T - * @param iterable|T> $promisesOrValues - * @return PromiseInterface - */ -function race(iterable $promisesOrValues): PromiseInterface -{ - $cancellationQueue = new Internal\CancellationQueue(); - - /** @var Promise */ - return new Promise(function (callable $resolve, callable $reject) use ($promisesOrValues, $cancellationQueue): void { - $continue = true; - - foreach ($promisesOrValues as $promiseOrValue) { - $cancellationQueue->enqueue($promiseOrValue); - - resolve($promiseOrValue)->then($resolve, $reject)->finally(function () use (&$continue): void { - $continue = false; - }); - - if (!$continue && !\is_array($promisesOrValues)) { - break; - } - } - }, $cancellationQueue); -} - -/** - * Returns a promise that will resolve when any one of the items in - * `$promisesOrValues` resolves. The resolution value of the returned promise - * will be the resolution value of the triggering item. - * - * The returned promise will only reject if *all* items in `$promisesOrValues` are - * rejected. The rejection value will be an array of all rejection reasons. - * - * The returned promise will also reject with a `React\Promise\Exception\LengthException` - * if `$promisesOrValues` contains 0 items. - * - * @template T - * @param iterable|T> $promisesOrValues - * @return PromiseInterface - */ -function any(iterable $promisesOrValues): PromiseInterface -{ - $cancellationQueue = new Internal\CancellationQueue(); - - /** @var Promise */ - return new Promise(function (callable $resolve, callable $reject) use ($promisesOrValues, $cancellationQueue): void { - $toReject = 0; - $continue = true; - $reasons = []; - - foreach ($promisesOrValues as $i => $promiseOrValue) { - $cancellationQueue->enqueue($promiseOrValue); - ++$toReject; - - resolve($promiseOrValue)->then( - function ($value) use ($resolve, &$continue): void { - $continue = false; - $resolve($value); - }, - function (\Throwable $reason) use ($i, &$reasons, &$toReject, $reject, &$continue): void { - $reasons[$i] = $reason; - - if (0 === --$toReject && !$continue) { - $reject(new CompositeException( - $reasons, - 'All promises rejected.' - )); - } - } - ); - - if (!$continue && !\is_array($promisesOrValues)) { - break; - } - } - - $continue = false; - if ($toReject === 0 && !$reasons) { - $reject(new Exception\LengthException( - 'Must contain at least 1 item but contains only 0 items.' - )); - } elseif ($toReject === 0) { - $reject(new CompositeException( - $reasons, - 'All promises rejected.' - )); - } - }, $cancellationQueue); -} - -/** - * Sets the global rejection handler for unhandled promise rejections. - * - * Note that rejected promises should always be handled similar to how any - * exceptions should always be caught in a `try` + `catch` block. If you remove - * the last reference to a rejected promise that has not been handled, it will - * report an unhandled promise rejection. See also the [`reject()` function](#reject) - * for more details. - * - * The `?callable $callback` argument MUST be a valid callback function that - * accepts a single `Throwable` argument or a `null` value to restore the - * default promise rejection handler. The return value of the callback function - * will be ignored and has no effect, so you SHOULD return a `void` value. The - * callback function MUST NOT throw or the program will be terminated with a - * fatal error. - * - * The function returns the previous rejection handler or `null` if using the - * default promise rejection handler. - * - * The default promise rejection handler will log an error message plus its - * stack trace: - * - * ```php - * // Unhandled promise rejection with RuntimeException: Unhandled in example.php:2 - * React\Promise\reject(new RuntimeException('Unhandled')); - * ``` - * - * The promise rejection handler may be used to use customize the log message or - * write to custom log targets. As a rule of thumb, this function should only be - * used as a last resort and promise rejections are best handled with either the - * [`then()` method](#promiseinterfacethen), the - * [`catch()` method](#promiseinterfacecatch), or the - * [`finally()` method](#promiseinterfacefinally). - * See also the [`reject()` function](#reject) for more details. - * - * @param callable(\Throwable):void|null $callback - * @return callable(\Throwable):void|null - */ -function set_rejection_handler(?callable $callback): ?callable -{ - static $current = null; - $previous = $current; - $current = $callback; - - return $previous; -} - -/** - * @internal - */ -function _checkTypehint(callable $callback, \Throwable $reason): bool -{ - if (\is_array($callback)) { - $callbackReflection = new \ReflectionMethod($callback[0], $callback[1]); - } elseif (\is_object($callback) && !$callback instanceof \Closure) { - $callbackReflection = new \ReflectionMethod($callback, '__invoke'); - } else { - assert($callback instanceof \Closure || \is_string($callback)); - $callbackReflection = new \ReflectionFunction($callback); - } - - $parameters = $callbackReflection->getParameters(); - - if (!isset($parameters[0])) { - return true; - } - - $expectedException = $parameters[0]; - - // Extract the type of the argument and handle different possibilities - $type = $expectedException->getType(); - - $isTypeUnion = true; - $types = []; - - switch (true) { - case $type === null: - break; - case $type instanceof \ReflectionNamedType: - $types = [$type]; - break; - case $type instanceof \ReflectionIntersectionType: - $isTypeUnion = false; - case $type instanceof \ReflectionUnionType; - $types = $type->getTypes(); - break; - default: - throw new \LogicException('Unexpected return value of ReflectionParameter::getType'); - } - - // If there is no type restriction, it matches - if (empty($types)) { - return true; - } - - foreach ($types as $type) { - - if ($type instanceof \ReflectionIntersectionType) { - foreach ($type->getTypes() as $typeToMatch) { - assert($typeToMatch instanceof \ReflectionNamedType); - $name = $typeToMatch->getName(); - if (!($matches = (!$typeToMatch->isBuiltin() && $reason instanceof $name))) { - break; - } - } - assert(isset($matches)); - } else { - assert($type instanceof \ReflectionNamedType); - $name = $type->getName(); - $matches = !$type->isBuiltin() && $reason instanceof $name; - } - - // If we look for a single match (union), we can return early on match - // If we look for a full match (intersection), we can return early on mismatch - if ($matches) { - if ($isTypeUnion) { - return true; - } - } else { - if (!$isTypeUnion) { - return false; - } - } - } - - // If we look for a single match (union) and did not return early, we matched no type and are false - // If we look for a full match (intersection) and did not return early, we matched all types and are true - return $isTypeUnion ? false : true; -} diff --git a/digital_doctor/vendor/react/promise/src/functions_include.php b/digital_doctor/vendor/react/promise/src/functions_include.php deleted file mode 100644 index bd0c54f..0000000 --- a/digital_doctor/vendor/react/promise/src/functions_include.php +++ /dev/null @@ -1,5 +0,0 @@ -connect($uri)->then(function (React\Socket\ConnectionInterface $conn) { - // … - }, function (Exception $e) { - echo 'Error:' . $e->getMessage() . PHP_EOL; - }); - ``` - -* Improve test suite, test against PHP 8.1 release. - (#274 by @SimonFrings) - -## 1.9.0 (2021-08-03) - -* Feature: Add new `SocketServer` and deprecate `Server` to avoid class name collisions. - (#263 by @clue) - - The new `SocketServer` class has been added with an improved constructor signature - as a replacement for the previous `Server` class in order to avoid any ambiguities. - The previous name has been deprecated and should not be used anymore. - In its most basic form, the deprecated `Server` can now be considered an alias for new `SocketServer`. - - ```php - // deprecated - $socket = new React\Socket\Server(0); - $socket = new React\Socket\Server('127.0.0.1:8000'); - $socket = new React\Socket\Server('127.0.0.1:8000', null, $context); - $socket = new React\Socket\Server('127.0.0.1:8000', $loop, $context); - - // new - $socket = new React\Socket\SocketServer('127.0.0.1:0'); - $socket = new React\Socket\SocketServer('127.0.0.1:8000'); - $socket = new React\Socket\SocketServer('127.0.0.1:8000', $context); - $socket = new React\Socket\SocketServer('127.0.0.1:8000', $context, $loop); - ``` - -* Feature: Update `Connector` signature to take optional `$context` as first argument. - (#264 by @clue) - - The new signature has been added to match the new `SocketServer` and - consistently move the now commonly unneeded loop argument to the last argument. - The previous signature has been deprecated and should not be used anymore. - In its most basic form, both signatures are compatible. - - ```php - // deprecated - $connector = new React\Socket\Connector(null, $context); - $connector = new React\Socket\Connector($loop, $context); - - // new - $connector = new React\Socket\Connector($context); - $connector = new React\Socket\Connector($context, $loop); - ``` - -## 1.8.0 (2021-07-11) - -A major new feature release, see [**release announcement**](https://clue.engineering/2021/announcing-reactphp-default-loop). - -* Feature: Simplify usage by supporting new [default loop](https://reactphp.org/event-loop/#loop). - (#260 by @clue) - - ```php - // old (still supported) - $socket = new React\Socket\Server('127.0.0.1:8080', $loop); - $connector = new React\Socket\Connector($loop); - - // new (using default loop) - $socket = new React\Socket\Server('127.0.0.1:8080'); - $connector = new React\Socket\Connector(); - ``` - -## 1.7.0 (2021-06-25) - -* Feature: Support falling back to multiple DNS servers from DNS config. - (#257 by @clue) - - If you're using the default `Connector`, it will now use all DNS servers - configured on your system. If you have multiple DNS servers configured and - connectivity to the primary DNS server is broken, it will now fall back to - your other DNS servers, thus providing improved connectivity and redundancy - for broken DNS configurations. - -* Feature: Use round robin for happy eyeballs DNS responses (load balancing). - (#247 by @clue) - - If you're using the default `Connector`, it will now randomize the order of - the IP addresses resolved via DNS when connecting. This allows the load to - be distributed more evenly across all returned IP addresses. This can be - used as a very basic DNS load balancing mechanism. - -* Internal improvement to avoid unhandled rejection for future Promise API. - (#258 by @clue) - -* Improve test suite, use GitHub actions for continuous integration (CI). - (#254 by @SimonFrings) - -## 1.6.0 (2020-08-28) - -* Feature: Support upcoming PHP 8 release. - (#246 by @clue) - -* Feature: Change default socket backlog size to 511. - (#242 by @clue) - -* Fix: Fix closing connection when cancelling during TLS handshake. - (#241 by @clue) - -* Fix: Fix blocking during possible `accept()` race condition - when multiple socket servers listen on same socket address. - (#244 by @clue) - -* Improve test suite, update PHPUnit config and add full core team to the license. - (#243 by @SimonFrings and #245 by @WyriHaximus) - -## 1.5.0 (2020-07-01) - -* Feature / Fix: Improve error handling and reporting for happy eyeballs and - immediately try next connection when one connection attempt fails. - (#230, #231, #232 and #233 by @clue) - - Error messages for failed connection attempts now include more details to - ease debugging. Additionally, the happy eyeballs algorithm has been improved - to avoid having to wait for some timers to expire which significantly - improves connection setup times (in particular when IPv6 isn't available). - -* Improve test suite, minor code cleanup and improve code coverage to 100%. - Update to PHPUnit 9 and skip legacy TLS 1.0 / TLS 1.1 tests if disabled by - system. Run tests on Windows and simplify Travis CI test matrix for Mac OS X - setup and skip all TLS tests on legacy HHVM. - (#229, #235, #236 and #238 by @clue and #239 by @SimonFrings) - -## 1.4.0 (2020-03-12) - -A major new feature release, see [**release announcement**](https://clue.engineering/2020/introducing-ipv6-for-reactphp). - -* Feature: Add IPv6 support to `Connector` (implement "Happy Eyeballs" algorithm to support IPv6 probing). - IPv6 support is turned on by default, use new `happy_eyeballs` option in `Connector` to toggle behavior. - (#196, #224 and #225 by @WyriHaximus and @clue) - -* Feature: Default to using DNS cache (with max 256 entries) for `Connector`. - (#226 by @clue) - -* Add `.gitattributes` to exclude dev files from exports and some minor code style fixes. - (#219 by @reedy and #218 by @mmoreram) - -* Improve test suite to fix failing test cases when using new DNS component, - significantly improve test performance by awaiting events instead of sleeping, - exclude TLS 1.3 test on PHP 7.3, run tests on PHP 7.4 and simplify test matrix. - (#208, #209, #210, #217 and #223 by @clue) - -## 1.3.0 (2019-07-10) - -* Feature: Forward compatibility with upcoming stable DNS component. - (#206 by @clue) - -## 1.2.1 (2019-06-03) - -* Avoid uneeded fragmented TLS work around for PHP 7.3.3+ and - work around failing test case detecting EOF on TLS 1.3 socket streams. - (#201 and #202 by @clue) - -* Improve TLS certificate/passphrase example. - (#190 by @jsor) - -## 1.2.0 (2019-01-07) - -* Feature / Fix: Improve TLS 1.3 support. - (#186 by @clue) - - TLS 1.3 is now an official standard as of August 2018! :tada: - The protocol has major improvements in the areas of security, performance, and privacy. - TLS 1.3 is supported by default as of [OpenSSL 1.1.1](https://www.openssl.org/blog/blog/2018/09/11/release111/). - For example, this version ships with Ubuntu 18.10 (and newer) by default, meaning that recent installations support TLS 1.3 out of the box :shipit: - -* Fix: Avoid possibility of missing remote address when TLS handshake fails. - (#188 by @clue) - -* Improve performance by prefixing all global functions calls with `\` to skip the look up and resolve process and go straight to the global function. - (#183 by @WyriHaximus) - -* Update documentation to use full class names with namespaces. - (#187 by @clue) - -* Improve test suite to avoid some possible race conditions, - test against PHP 7.3 on Travis and - use dedicated `assertInstanceOf()` assertions. - (#185 by @clue, #178 by @WyriHaximus and #181 by @carusogabriel) - -## 1.1.0 (2018-10-01) - -* Feature: Improve error reporting for failed connection attempts and improve - cancellation forwarding during DNS lookup, TCP/IP connection or TLS handshake. - (#168, #169, #170, #171, #176 and #177 by @clue) - - All error messages now always contain a reference to the remote URI to give - more details which connection actually failed and the reason for this error. - Accordingly, failures during DNS lookup will now mention both the remote URI - as well as the DNS error reason. TCP/IP connection issues and errors during - a secure TLS handshake will both mention the remote URI as well as the - underlying socket error. Similarly, lost/dropped connections during a TLS - handshake will now report a lost connection instead of an empty error reason. - - For most common use cases this means that simply reporting the `Exception` - message should give the most relevant details for any connection issues: - - ```php - $promise = $connector->connect('tls://example.com:443'); - $promise->then(function (ConnectionInterface $conn) use ($loop) { - // … - }, function (Exception $e) { - echo $e->getMessage(); - }); - ``` - -## 1.0.0 (2018-07-11) - -* First stable LTS release, now following [SemVer](https://semver.org/). - We'd like to emphasize that this component is production ready and battle-tested. - We plan to support all long-term support (LTS) releases for at least 24 months, - so you have a rock-solid foundation to build on top of. - -> Contains no other changes, so it's actually fully compatible with the v0.8.12 release. - -## 0.8.12 (2018-06-11) - -* Feature: Improve memory consumption for failed and cancelled connection attempts. - (#161 by @clue) - -* Improve test suite to fix Travis config to test against legacy PHP 5.3 again. - (#162 by @clue) - -## 0.8.11 (2018-04-24) - -* Feature: Improve memory consumption for cancelled connection attempts and - simplify skipping DNS lookup when connecting to IP addresses. - (#159 and #160 by @clue) - -## 0.8.10 (2018-02-28) - -* Feature: Update DNS dependency to support loading system default DNS - nameserver config on all supported platforms - (`/etc/resolv.conf` on Unix/Linux/Mac/Docker/WSL and WMIC on Windows) - (#152 by @clue) - - This means that connecting to hosts that are managed by a local DNS server, - such as a corporate DNS server or when using Docker containers, will now - work as expected across all platforms with no changes required: - - ```php - $connector = new Connector($loop); - $connector->connect('intranet.example:80')->then(function ($connection) { - // … - }); - ``` - -## 0.8.9 (2018-01-18) - -* Feature: Support explicitly choosing TLS version to negotiate with remote side - by respecting `crypto_method` context parameter for all classes. - (#149 by @clue) - - By default, all connector and server classes support TLSv1.0+ and exclude - support for legacy SSLv2/SSLv3. As of PHP 5.6+ you can also explicitly - choose the TLS version you want to negotiate with the remote side: - - ```php - // new: now supports 'crypto_method` context parameter for all classes - $connector = new Connector($loop, array( - 'tls' => array( - 'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT - ) - )); - ``` - -* Minor internal clean up to unify class imports - (#148 by @clue) - -## 0.8.8 (2018-01-06) - -* Improve test suite by adding test group to skip integration tests relying on - internet connection and fix minor documentation typo. - (#146 by @clue and #145 by @cn007b) - -## 0.8.7 (2017-12-24) - -* Fix: Fix closing socket resource before removing from loop - (#141 by @clue) - - This fixes the root cause of an uncaught `Exception` that only manifested - itself after the recent Stream v0.7.4 component update and only if you're - using `ext-event` (`ExtEventLoop`). - -* Improve test suite by testing against PHP 7.2 - (#140 by @carusogabriel) - -## 0.8.6 (2017-11-18) - -* Feature: Add Unix domain socket (UDS) support to `Server` with `unix://` URI scheme - and add advanced `UnixServer` class. - (#120 by @andig) - - ```php - // new: Server now supports "unix://" scheme - $server = new Server('unix:///tmp/server.sock', $loop); - - // new: advanced usage - $server = new UnixServer('/tmp/server.sock', $loop); - ``` - -* Restructure examples to ease getting started - (#136 by @clue) - -* Improve test suite by adding forward compatibility with PHPUnit 6 and - ignore Mac OS X test failures for now until Travis tests work again - (#133 by @gabriel-caruso and #134 by @clue) - -## 0.8.5 (2017-10-23) - -* Fix: Work around PHP bug with Unix domain socket (UDS) paths for Mac OS X - (#123 by @andig) - -* Fix: Fix `SecureServer` to return `null` URI if server socket is already closed - (#129 by @clue) - -* Improve test suite by adding forward compatibility with PHPUnit v5 and - forward compatibility with upcoming EventLoop releases in tests and - test Mac OS X on Travis - (#122 by @andig and #125, #127 and #130 by @clue) - -* Readme improvements - (#118 by @jsor) - -## 0.8.4 (2017-09-16) - -* Feature: Add `FixedUriConnector` decorator to use fixed, preconfigured URI instead - (#117 by @clue) - - This can be useful for consumers that do not support certain URIs, such as - when you want to explicitly connect to a Unix domain socket (UDS) path - instead of connecting to a default address assumed by an higher-level API: - - ```php - $connector = new FixedUriConnector( - 'unix:///var/run/docker.sock', - new UnixConnector($loop) - ); - - // destination will be ignored, actually connects to Unix domain socket - $promise = $connector->connect('localhost:80'); - ``` - -## 0.8.3 (2017-09-08) - -* Feature: Reduce memory consumption for failed connections - (#113 by @valga) - -* Fix: Work around write chunk size for TLS streams for PHP < 7.1.14 - (#114 by @clue) - -## 0.8.2 (2017-08-25) - -* Feature: Update DNS dependency to support hosts file on all platforms - (#112 by @clue) - - This means that connecting to hosts such as `localhost` will now work as - expected across all platforms with no changes required: - - ```php - $connector = new Connector($loop); - $connector->connect('localhost:8080')->then(function ($connection) { - // … - }); - ``` - -## 0.8.1 (2017-08-15) - -* Feature: Forward compatibility with upcoming EventLoop v1.0 and v0.5 and - target evenement 3.0 a long side 2.0 and 1.0 - (#104 by @clue and #111 by @WyriHaximus) - -* Improve test suite by locking Travis distro so new defaults will not break the build and - fix HHVM build for now again and ignore future HHVM build errors - (#109 and #110 by @clue) - -* Minor documentation fixes - (#103 by @christiaan and #108 by @hansott) - -## 0.8.0 (2017-05-09) - -* Feature: New `Server` class now acts as a facade for existing server classes - and renamed old `Server` to `TcpServer` for advanced usage. - (#96 and #97 by @clue) - - The `Server` class is now the main class in this package that implements the - `ServerInterface` and allows you to accept incoming streaming connections, - such as plaintext TCP/IP or secure TLS connection streams. - - > This is not a BC break and consumer code does not have to be updated. - -* Feature / BC break: All addresses are now URIs that include the URI scheme - (#98 by @clue) - - ```diff - - $parts = parse_url('tcp://' . $conn->getRemoteAddress()); - + $parts = parse_url($conn->getRemoteAddress()); - ``` - -* Fix: Fix `unix://` addresses for Unix domain socket (UDS) paths - (#100 by @clue) - -* Feature: Forward compatibility with Stream v1.0 and v0.7 - (#99 by @clue) - -## 0.7.2 (2017-04-24) - -* Fix: Work around latest PHP 7.0.18 and 7.1.4 no longer accepting full URIs - (#94 by @clue) - -## 0.7.1 (2017-04-10) - -* Fix: Ignore HHVM errors when closing connection that is already closing - (#91 by @clue) - -## 0.7.0 (2017-04-10) - -* Feature: Merge SocketClient component into this component - (#87 by @clue) - - This means that this package now provides async, streaming plaintext TCP/IP - and secure TLS socket server and client connections for ReactPHP. - - ``` - $connector = new React\Socket\Connector($loop); - $connector->connect('google.com:80')->then(function (ConnectionInterface $conn) { - $connection->write('…'); - }); - ``` - - Accordingly, the `ConnectionInterface` is now used to represent both incoming - server side connections as well as outgoing client side connections. - - If you've previously used the SocketClient component to establish outgoing - client connections, upgrading should take no longer than a few minutes. - All classes have been merged as-is from the latest `v0.7.0` release with no - other changes, so you can simply update your code to use the updated namespace - like this: - - ```php - // old from SocketClient component and namespace - $connector = new React\SocketClient\Connector($loop); - $connector->connect('google.com:80')->then(function (ConnectionInterface $conn) { - $connection->write('…'); - }); - - // new - $connector = new React\Socket\Connector($loop); - $connector->connect('google.com:80')->then(function (ConnectionInterface $conn) { - $connection->write('…'); - }); - ``` - -## 0.6.0 (2017-04-04) - -* Feature: Add `LimitingServer` to limit and keep track of open connections - (#86 by @clue) - - ```php - $server = new Server(0, $loop); - $server = new LimitingServer($server, 100); - - $server->on('connection', function (ConnectionInterface $connection) { - $connection->write('hello there!' . PHP_EOL); - … - }); - ``` - -* Feature / BC break: Add `pause()` and `resume()` methods to limit active - connections - (#84 by @clue) - - ```php - $server = new Server(0, $loop); - $server->pause(); - - $loop->addTimer(1.0, function() use ($server) { - $server->resume(); - }); - ``` - -## 0.5.1 (2017-03-09) - -* Feature: Forward compatibility with Stream v0.5 and upcoming v0.6 - (#79 by @clue) - -## 0.5.0 (2017-02-14) - -* Feature / BC break: Replace `listen()` call with URIs passed to constructor - and reject listening on hostnames with `InvalidArgumentException` - and replace `ConnectionException` with `RuntimeException` for consistency - (#61, #66 and #72 by @clue) - - ```php - // old - $server = new Server($loop); - $server->listen(8080); - - // new - $server = new Server(8080, $loop); - ``` - - Similarly, you can now pass a full listening URI to the constructor to change - the listening host: - - ```php - // old - $server = new Server($loop); - $server->listen(8080, '127.0.0.1'); - - // new - $server = new Server('127.0.0.1:8080', $loop); - ``` - - Trying to start listening on (DNS) host names will now throw an - `InvalidArgumentException`, use IP addresses instead: - - ```php - // old - $server = new Server($loop); - $server->listen(8080, 'localhost'); - - // new - $server = new Server('127.0.0.1:8080', $loop); - ``` - - If trying to listen fails (such as if port is already in use or port below - 1024 may require root access etc.), it will now throw a `RuntimeException`, - the `ConnectionException` class has been removed: - - ```php - // old: throws React\Socket\ConnectionException - $server = new Server($loop); - $server->listen(80); - - // new: throws RuntimeException - $server = new Server(80, $loop); - ``` - -* Feature / BC break: Rename `shutdown()` to `close()` for consistency throughout React - (#62 by @clue) - - ```php - // old - $server->shutdown(); - - // new - $server->close(); - ``` - -* Feature / BC break: Replace `getPort()` with `getAddress()` - (#67 by @clue) - - ```php - // old - echo $server->getPort(); // 8080 - - // new - echo $server->getAddress(); // 127.0.0.1:8080 - ``` - -* Feature / BC break: `getRemoteAddress()` returns full address instead of only IP - (#65 by @clue) - - ```php - // old - echo $connection->getRemoteAddress(); // 192.168.0.1 - - // new - echo $connection->getRemoteAddress(); // 192.168.0.1:51743 - ``` - -* Feature / BC break: Add `getLocalAddress()` method - (#68 by @clue) - - ```php - echo $connection->getLocalAddress(); // 127.0.0.1:8080 - ``` - -* BC break: The `Server` and `SecureServer` class are now marked `final` - and you can no longer `extend` them - (which was never documented or recommended anyway). - Public properties and event handlers are now internal only. - Please use composition instead of extension. - (#71, #70 and #69 by @clue) - -## 0.4.6 (2017-01-26) - -* Feature: Support socket context options passed to `Server` - (#64 by @clue) - -* Fix: Properly return `null` for unknown addresses - (#63 by @clue) - -* Improve documentation for `ServerInterface` and lock test suite requirements - (#60 by @clue, #57 by @shaunbramley) - -## 0.4.5 (2017-01-08) - -* Feature: Add `SecureServer` for secure TLS connections - (#55 by @clue) - -* Add functional integration tests - (#54 by @clue) - -## 0.4.4 (2016-12-19) - -* Feature / Fix: `ConnectionInterface` should extend `DuplexStreamInterface` + documentation - (#50 by @clue) - -* Feature / Fix: Improve test suite and switch to normal stream handler - (#51 by @clue) - -* Feature: Add examples - (#49 by @clue) - -## 0.4.3 (2016-03-01) - -* Bug fix: Suppress errors on stream_socket_accept to prevent PHP from crashing -* Support for PHP7 and HHVM -* Support PHP 5.3 again - -## 0.4.2 (2014-05-25) - -* Verify stream is a valid resource in Connection - -## 0.4.1 (2014-04-13) - -* Bug fix: Check read buffer for data before shutdown signal and end emit (@ArtyDev) -* Bug fix: v0.3.4 changes merged for v0.4.1 - -## 0.3.4 (2014-03-30) - -* Bug fix: Reset socket to non-blocking after shutting down (PHP bug) - -## 0.4.0 (2014-02-02) - -* BC break: Bump minimum PHP version to PHP 5.4, remove 5.3 specific hacks -* BC break: Update to React/Promise 2.0 -* BC break: Update to Evenement 2.0 -* Dependency: Autoloading and filesystem structure now PSR-4 instead of PSR-0 -* Bump React dependencies to v0.4 - -## 0.3.3 (2013-07-08) - -* Version bump - -## 0.3.2 (2013-05-10) - -* Version bump - -## 0.3.1 (2013-04-21) - -* Feature: Support binding to IPv6 addresses (@clue) - -## 0.3.0 (2013-04-14) - -* Bump React dependencies to v0.3 - -## 0.2.6 (2012-12-26) - -* Version bump - -## 0.2.3 (2012-11-14) - -* Version bump - -## 0.2.0 (2012-09-10) - -* Bump React dependencies to v0.2 - -## 0.1.1 (2012-07-12) - -* Version bump - -## 0.1.0 (2012-07-11) - -* First tagged release diff --git a/digital_doctor/vendor/react/socket/LICENSE b/digital_doctor/vendor/react/socket/LICENSE deleted file mode 100644 index d6f8901..0000000 --- a/digital_doctor/vendor/react/socket/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2012 Christian Lück, Cees-Jan Kiewiet, Jan Sorgalla, Chris Boden, Igor Wiedler - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/digital_doctor/vendor/react/socket/README.md b/digital_doctor/vendor/react/socket/README.md deleted file mode 100644 index 18e3d91..0000000 --- a/digital_doctor/vendor/react/socket/README.md +++ /dev/null @@ -1,1564 +0,0 @@ -# Socket - -[![CI status](https://github.com/reactphp/socket/workflows/CI/badge.svg)](https://github.com/reactphp/socket/actions) -[![installs on Packagist](https://img.shields.io/packagist/dt/react/socket?color=blue&label=installs%20on%20Packagist)](https://packagist.org/packages/react/socket) - -Async, streaming plaintext TCP/IP and secure TLS socket server and client -connections for [ReactPHP](https://reactphp.org/). - -The socket library provides re-usable interfaces for a socket-layer -server and client based on the [`EventLoop`](https://github.com/reactphp/event-loop) -and [`Stream`](https://github.com/reactphp/stream) components. -Its server component allows you to build networking servers that accept incoming -connections from networking clients (such as an HTTP server). -Its client component allows you to build networking clients that establish -outgoing connections to networking servers (such as an HTTP or database client). -This library provides async, streaming means for all of this, so you can -handle multiple concurrent connections without blocking. - -**Table of Contents** - -* [Quickstart example](#quickstart-example) -* [Connection usage](#connection-usage) - * [ConnectionInterface](#connectioninterface) - * [getRemoteAddress()](#getremoteaddress) - * [getLocalAddress()](#getlocaladdress) -* [Server usage](#server-usage) - * [ServerInterface](#serverinterface) - * [connection event](#connection-event) - * [error event](#error-event) - * [getAddress()](#getaddress) - * [pause()](#pause) - * [resume()](#resume) - * [close()](#close) - * [SocketServer](#socketserver) - * [Advanced server usage](#advanced-server-usage) - * [TcpServer](#tcpserver) - * [SecureServer](#secureserver) - * [UnixServer](#unixserver) - * [LimitingServer](#limitingserver) - * [getConnections()](#getconnections) -* [Client usage](#client-usage) - * [ConnectorInterface](#connectorinterface) - * [connect()](#connect) - * [Connector](#connector) - * [Advanced client usage](#advanced-client-usage) - * [TcpConnector](#tcpconnector) - * [HappyEyeBallsConnector](#happyeyeballsconnector) - * [DnsConnector](#dnsconnector) - * [SecureConnector](#secureconnector) - * [TimeoutConnector](#timeoutconnector) - * [UnixConnector](#unixconnector) - * [FixUriConnector](#fixeduriconnector) -* [Install](#install) -* [Tests](#tests) -* [License](#license) - -## Quickstart example - -Here is a server that closes the connection if you send it anything: - -```php -$socket = new React\Socket\SocketServer('127.0.0.1:8080'); - -$socket->on('connection', function (React\Socket\ConnectionInterface $connection) { - $connection->write("Hello " . $connection->getRemoteAddress() . "!\n"); - $connection->write("Welcome to this amazing server!\n"); - $connection->write("Here's a tip: don't say anything.\n"); - - $connection->on('data', function ($data) use ($connection) { - $connection->close(); - }); -}); -``` - -See also the [examples](examples). - -Here's a client that outputs the output of said server and then attempts to -send it a string: - -```php -$connector = new React\Socket\Connector(); - -$connector->connect('127.0.0.1:8080')->then(function (React\Socket\ConnectionInterface $connection) { - $connection->pipe(new React\Stream\WritableResourceStream(STDOUT)); - $connection->write("Hello World!\n"); -}, function (Exception $e) { - echo 'Error: ' . $e->getMessage() . PHP_EOL; -}); -``` - -## Connection usage - -### ConnectionInterface - -The `ConnectionInterface` is used to represent any incoming and outgoing -connection, such as a normal TCP/IP connection. - -An incoming or outgoing connection is a duplex stream (both readable and -writable) that implements React's -[`DuplexStreamInterface`](https://github.com/reactphp/stream#duplexstreaminterface). -It contains additional properties for the local and remote address (client IP) -where this connection has been established to/from. - -Most commonly, instances implementing this `ConnectionInterface` are emitted -by all classes implementing the [`ServerInterface`](#serverinterface) and -used by all classes implementing the [`ConnectorInterface`](#connectorinterface). - -Because the `ConnectionInterface` implements the underlying -[`DuplexStreamInterface`](https://github.com/reactphp/stream#duplexstreaminterface) -you can use any of its events and methods as usual: - -```php -$connection->on('data', function ($chunk) { - echo $chunk; -}); - -$connection->on('end', function () { - echo 'ended'; -}); - -$connection->on('error', function (Exception $e) { - echo 'error: ' . $e->getMessage(); -}); - -$connection->on('close', function () { - echo 'closed'; -}); - -$connection->write($data); -$connection->end($data = null); -$connection->close(); -// … -``` - -For more details, see the -[`DuplexStreamInterface`](https://github.com/reactphp/stream#duplexstreaminterface). - -#### getRemoteAddress() - -The `getRemoteAddress(): ?string` method returns the full remote address -(URI) where this connection has been established with. - -```php -$address = $connection->getRemoteAddress(); -echo 'Connection with ' . $address . PHP_EOL; -``` - -If the remote address can not be determined or is unknown at this time (such as -after the connection has been closed), it MAY return a `NULL` value instead. - -Otherwise, it will return the full address (URI) as a string value, such -as `tcp://127.0.0.1:8080`, `tcp://[::1]:80`, `tls://127.0.0.1:443`, -`unix://example.sock` or `unix:///path/to/example.sock`. -Note that individual URI components are application specific and depend -on the underlying transport protocol. - -If this is a TCP/IP based connection and you only want the remote IP, you may -use something like this: - -```php -$address = $connection->getRemoteAddress(); -$ip = trim(parse_url($address, PHP_URL_HOST), '[]'); -echo 'Connection with ' . $ip . PHP_EOL; -``` - -#### getLocalAddress() - -The `getLocalAddress(): ?string` method returns the full local address -(URI) where this connection has been established with. - -```php -$address = $connection->getLocalAddress(); -echo 'Connection with ' . $address . PHP_EOL; -``` - -If the local address can not be determined or is unknown at this time (such as -after the connection has been closed), it MAY return a `NULL` value instead. - -Otherwise, it will return the full address (URI) as a string value, such -as `tcp://127.0.0.1:8080`, `tcp://[::1]:80`, `tls://127.0.0.1:443`, -`unix://example.sock` or `unix:///path/to/example.sock`. -Note that individual URI components are application specific and depend -on the underlying transport protocol. - -This method complements the [`getRemoteAddress()`](#getremoteaddress) method, -so they should not be confused. - -If your `TcpServer` instance is listening on multiple interfaces (e.g. using -the address `0.0.0.0`), you can use this method to find out which interface -actually accepted this connection (such as a public or local interface). - -If your system has multiple interfaces (e.g. a WAN and a LAN interface), -you can use this method to find out which interface was actually -used for this connection. - -## Server usage - -### ServerInterface - -The `ServerInterface` is responsible for providing an interface for accepting -incoming streaming connections, such as a normal TCP/IP connection. - -Most higher-level components (such as a HTTP server) accept an instance -implementing this interface to accept incoming streaming connections. -This is usually done via dependency injection, so it's fairly simple to actually -swap this implementation against any other implementation of this interface. -This means that you SHOULD typehint against this interface instead of a concrete -implementation of this interface. - -Besides defining a few methods, this interface also implements the -[`EventEmitterInterface`](https://github.com/igorw/evenement) -which allows you to react to certain events. - -#### connection event - -The `connection` event will be emitted whenever a new connection has been -established, i.e. a new client connects to this server socket: - -```php -$socket->on('connection', function (React\Socket\ConnectionInterface $connection) { - echo 'new connection' . PHP_EOL; -}); -``` - -See also the [`ConnectionInterface`](#connectioninterface) for more details -about handling the incoming connection. - -#### error event - -The `error` event will be emitted whenever there's an error accepting a new -connection from a client. - -```php -$socket->on('error', function (Exception $e) { - echo 'error: ' . $e->getMessage() . PHP_EOL; -}); -``` - -Note that this is not a fatal error event, i.e. the server keeps listening for -new connections even after this event. - -#### getAddress() - -The `getAddress(): ?string` method can be used to -return the full address (URI) this server is currently listening on. - -```php -$address = $socket->getAddress(); -echo 'Server listening on ' . $address . PHP_EOL; -``` - -If the address can not be determined or is unknown at this time (such as -after the socket has been closed), it MAY return a `NULL` value instead. - -Otherwise, it will return the full address (URI) as a string value, such -as `tcp://127.0.0.1:8080`, `tcp://[::1]:80`, `tls://127.0.0.1:443` -`unix://example.sock` or `unix:///path/to/example.sock`. -Note that individual URI components are application specific and depend -on the underlying transport protocol. - -If this is a TCP/IP based server and you only want the local port, you may -use something like this: - -```php -$address = $socket->getAddress(); -$port = parse_url($address, PHP_URL_PORT); -echo 'Server listening on port ' . $port . PHP_EOL; -``` - -#### pause() - -The `pause(): void` method can be used to -pause accepting new incoming connections. - -Removes the socket resource from the EventLoop and thus stop accepting -new connections. Note that the listening socket stays active and is not -closed. - -This means that new incoming connections will stay pending in the -operating system backlog until its configurable backlog is filled. -Once the backlog is filled, the operating system may reject further -incoming connections until the backlog is drained again by resuming -to accept new connections. - -Once the server is paused, no futher `connection` events SHOULD -be emitted. - -```php -$socket->pause(); - -$socket->on('connection', assertShouldNeverCalled()); -``` - -This method is advisory-only, though generally not recommended, the -server MAY continue emitting `connection` events. - -Unless otherwise noted, a successfully opened server SHOULD NOT start -in paused state. - -You can continue processing events by calling `resume()` again. - -Note that both methods can be called any number of times, in particular -calling `pause()` more than once SHOULD NOT have any effect. -Similarly, calling this after `close()` is a NO-OP. - -#### resume() - -The `resume(): void` method can be used to -resume accepting new incoming connections. - -Re-attach the socket resource to the EventLoop after a previous `pause()`. - -```php -$socket->pause(); - -Loop::addTimer(1.0, function () use ($socket) { - $socket->resume(); -}); -``` - -Note that both methods can be called any number of times, in particular -calling `resume()` without a prior `pause()` SHOULD NOT have any effect. -Similarly, calling this after `close()` is a NO-OP. - -#### close() - -The `close(): void` method can be used to -shut down this listening socket. - -This will stop listening for new incoming connections on this socket. - -```php -echo 'Shutting down server socket' . PHP_EOL; -$socket->close(); -``` - -Calling this method more than once on the same instance is a NO-OP. - -### SocketServer - - - -The `SocketServer` class is the main class in this package that implements the -[`ServerInterface`](#serverinterface) and allows you to accept incoming -streaming connections, such as plaintext TCP/IP or secure TLS connection streams. - -In order to accept plaintext TCP/IP connections, you can simply pass a host -and port combination like this: - -```php -$socket = new React\Socket\SocketServer('127.0.0.1:8080'); -``` - -Listening on the localhost address `127.0.0.1` means it will not be reachable from -outside of this system. -In order to change the host the socket is listening on, you can provide an IP -address of an interface or use the special `0.0.0.0` address to listen on all -interfaces: - -```php -$socket = new React\Socket\SocketServer('0.0.0.0:8080'); -``` - -If you want to listen on an IPv6 address, you MUST enclose the host in square -brackets: - -```php -$socket = new React\Socket\SocketServer('[::1]:8080'); -``` - -In order to use a random port assignment, you can use the port `0`: - -```php -$socket = new React\Socket\SocketServer('127.0.0.1:0'); -$address = $socket->getAddress(); -``` - -To listen on a Unix domain socket (UDS) path, you MUST prefix the URI with the -`unix://` scheme: - -```php -$socket = new React\Socket\SocketServer('unix:///tmp/server.sock'); -``` - -In order to listen on an existing file descriptor (FD) number, you MUST prefix -the URI with `php://fd/` like this: - -```php -$socket = new React\Socket\SocketServer('php://fd/3'); -``` - -If the given URI is invalid, does not contain a port, any other scheme or if it -contains a hostname, it will throw an `InvalidArgumentException`: - -```php -// throws InvalidArgumentException due to missing port -$socket = new React\Socket\SocketServer('127.0.0.1'); -``` - -If the given URI appears to be valid, but listening on it fails (such as if port -is already in use or port below 1024 may require root access etc.), it will -throw a `RuntimeException`: - -```php -$first = new React\Socket\SocketServer('127.0.0.1:8080'); - -// throws RuntimeException because port is already in use -$second = new React\Socket\SocketServer('127.0.0.1:8080'); -``` - -> Note that these error conditions may vary depending on your system and/or - configuration. - See the exception message and code for more details about the actual error - condition. - -Optionally, you can specify [TCP socket context options](https://www.php.net/manual/en/context.socket.php) -for the underlying stream socket resource like this: - -```php -$socket = new React\Socket\SocketServer('[::1]:8080', array( - 'tcp' => array( - 'backlog' => 200, - 'so_reuseport' => true, - 'ipv6_v6only' => true - ) -)); -``` - -> Note that available [socket context options](https://www.php.net/manual/en/context.socket.php), - their defaults and effects of changing these may vary depending on your system - and/or PHP version. - Passing unknown context options has no effect. - The `backlog` context option defaults to `511` unless given explicitly. - -You can start a secure TLS (formerly known as SSL) server by simply prepending -the `tls://` URI scheme. -Internally, it will wait for plaintext TCP/IP connections and then performs a -TLS handshake for each connection. -It thus requires valid [TLS context options](https://www.php.net/manual/en/context.ssl.php), -which in its most basic form may look something like this if you're using a -PEM encoded certificate file: - -```php -$socket = new React\Socket\SocketServer('tls://127.0.0.1:8080', array( - 'tls' => array( - 'local_cert' => 'server.pem' - ) -)); -``` - -> Note that the certificate file will not be loaded on instantiation but when an - incoming connection initializes its TLS context. - This implies that any invalid certificate file paths or contents will only cause - an `error` event at a later time. - -If your private key is encrypted with a passphrase, you have to specify it -like this: - -```php -$socket = new React\Socket\SocketServer('tls://127.0.0.1:8000', array( - 'tls' => array( - 'local_cert' => 'server.pem', - 'passphrase' => 'secret' - ) -)); -``` - -By default, this server supports TLSv1.0+ and excludes support for legacy -SSLv2/SSLv3. As of PHP 5.6+ you can also explicitly choose the TLS version you -want to negotiate with the remote side: - -```php -$socket = new React\Socket\SocketServer('tls://127.0.0.1:8000', array( - 'tls' => array( - 'local_cert' => 'server.pem', - 'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_2_SERVER - ) -)); -``` - -> Note that available [TLS context options](https://www.php.net/manual/en/context.ssl.php), - their defaults and effects of changing these may vary depending on your system - and/or PHP version. - The outer context array allows you to also use `tcp` (and possibly more) - context options at the same time. - Passing unknown context options has no effect. - If you do not use the `tls://` scheme, then passing `tls` context options - has no effect. - -Whenever a client connects, it will emit a `connection` event with a connection -instance implementing [`ConnectionInterface`](#connectioninterface): - -```php -$socket->on('connection', function (React\Socket\ConnectionInterface $connection) { - echo 'Plaintext connection from ' . $connection->getRemoteAddress() . PHP_EOL; - - $connection->write('hello there!' . PHP_EOL); - … -}); -``` - -See also the [`ServerInterface`](#serverinterface) for more details. - -This class takes an optional `LoopInterface|null $loop` parameter that can be used to -pass the event loop instance to use for this object. You can use a `null` value -here in order to use the [default loop](https://github.com/reactphp/event-loop#loop). -This value SHOULD NOT be given unless you're sure you want to explicitly use a -given event loop instance. - -> Note that the `SocketServer` class is a concrete implementation for TCP/IP sockets. - If you want to typehint in your higher-level protocol implementation, you SHOULD - use the generic [`ServerInterface`](#serverinterface) instead. - -> Changelog v1.9.0: This class has been added with an improved constructor signature - as a replacement for the previous `Server` class in order to avoid any ambiguities. - The previous name has been deprecated and should not be used anymore. - -### Advanced server usage - -#### TcpServer - -The `TcpServer` class implements the [`ServerInterface`](#serverinterface) and -is responsible for accepting plaintext TCP/IP connections. - -```php -$server = new React\Socket\TcpServer(8080); -``` - -As above, the `$uri` parameter can consist of only a port, in which case the -server will default to listening on the localhost address `127.0.0.1`, -which means it will not be reachable from outside of this system. - -In order to use a random port assignment, you can use the port `0`: - -```php -$server = new React\Socket\TcpServer(0); -$address = $server->getAddress(); -``` - -In order to change the host the socket is listening on, you can provide an IP -address through the first parameter provided to the constructor, optionally -preceded by the `tcp://` scheme: - -```php -$server = new React\Socket\TcpServer('192.168.0.1:8080'); -``` - -If you want to listen on an IPv6 address, you MUST enclose the host in square -brackets: - -```php -$server = new React\Socket\TcpServer('[::1]:8080'); -``` - -If the given URI is invalid, does not contain a port, any other scheme or if it -contains a hostname, it will throw an `InvalidArgumentException`: - -```php -// throws InvalidArgumentException due to missing port -$server = new React\Socket\TcpServer('127.0.0.1'); -``` - -If the given URI appears to be valid, but listening on it fails (such as if port -is already in use or port below 1024 may require root access etc.), it will -throw a `RuntimeException`: - -```php -$first = new React\Socket\TcpServer(8080); - -// throws RuntimeException because port is already in use -$second = new React\Socket\TcpServer(8080); -``` - -> Note that these error conditions may vary depending on your system and/or -configuration. -See the exception message and code for more details about the actual error -condition. - -This class takes an optional `LoopInterface|null $loop` parameter that can be used to -pass the event loop instance to use for this object. You can use a `null` value -here in order to use the [default loop](https://github.com/reactphp/event-loop#loop). -This value SHOULD NOT be given unless you're sure you want to explicitly use a -given event loop instance. - -Optionally, you can specify [socket context options](https://www.php.net/manual/en/context.socket.php) -for the underlying stream socket resource like this: - -```php -$server = new React\Socket\TcpServer('[::1]:8080', null, array( - 'backlog' => 200, - 'so_reuseport' => true, - 'ipv6_v6only' => true -)); -``` - -> Note that available [socket context options](https://www.php.net/manual/en/context.socket.php), -their defaults and effects of changing these may vary depending on your system -and/or PHP version. -Passing unknown context options has no effect. -The `backlog` context option defaults to `511` unless given explicitly. - -Whenever a client connects, it will emit a `connection` event with a connection -instance implementing [`ConnectionInterface`](#connectioninterface): - -```php -$server->on('connection', function (React\Socket\ConnectionInterface $connection) { - echo 'Plaintext connection from ' . $connection->getRemoteAddress() . PHP_EOL; - - $connection->write('hello there!' . PHP_EOL); - … -}); -``` - -See also the [`ServerInterface`](#serverinterface) for more details. - -#### SecureServer - -The `SecureServer` class implements the [`ServerInterface`](#serverinterface) -and is responsible for providing a secure TLS (formerly known as SSL) server. - -It does so by wrapping a [`TcpServer`](#tcpserver) instance which waits for plaintext -TCP/IP connections and then performs a TLS handshake for each connection. -It thus requires valid [TLS context options](https://www.php.net/manual/en/context.ssl.php), -which in its most basic form may look something like this if you're using a -PEM encoded certificate file: - -```php -$server = new React\Socket\TcpServer(8000); -$server = new React\Socket\SecureServer($server, null, array( - 'local_cert' => 'server.pem' -)); -``` - -> Note that the certificate file will not be loaded on instantiation but when an -incoming connection initializes its TLS context. -This implies that any invalid certificate file paths or contents will only cause -an `error` event at a later time. - -If your private key is encrypted with a passphrase, you have to specify it -like this: - -```php -$server = new React\Socket\TcpServer(8000); -$server = new React\Socket\SecureServer($server, null, array( - 'local_cert' => 'server.pem', - 'passphrase' => 'secret' -)); -``` - -By default, this server supports TLSv1.0+ and excludes support for legacy -SSLv2/SSLv3. As of PHP 5.6+ you can also explicitly choose the TLS version you -want to negotiate with the remote side: - -```php -$server = new React\Socket\TcpServer(8000); -$server = new React\Socket\SecureServer($server, null, array( - 'local_cert' => 'server.pem', - 'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_2_SERVER -)); -``` - -> Note that available [TLS context options](https://www.php.net/manual/en/context.ssl.php), -their defaults and effects of changing these may vary depending on your system -and/or PHP version. -Passing unknown context options has no effect. - -Whenever a client completes the TLS handshake, it will emit a `connection` event -with a connection instance implementing [`ConnectionInterface`](#connectioninterface): - -```php -$server->on('connection', function (React\Socket\ConnectionInterface $connection) { - echo 'Secure connection from' . $connection->getRemoteAddress() . PHP_EOL; - - $connection->write('hello there!' . PHP_EOL); - … -}); -``` - -Whenever a client fails to perform a successful TLS handshake, it will emit an -`error` event and then close the underlying TCP/IP connection: - -```php -$server->on('error', function (Exception $e) { - echo 'Error' . $e->getMessage() . PHP_EOL; -}); -``` - -See also the [`ServerInterface`](#serverinterface) for more details. - -Note that the `SecureServer` class is a concrete implementation for TLS sockets. -If you want to typehint in your higher-level protocol implementation, you SHOULD -use the generic [`ServerInterface`](#serverinterface) instead. - -This class takes an optional `LoopInterface|null $loop` parameter that can be used to -pass the event loop instance to use for this object. You can use a `null` value -here in order to use the [default loop](https://github.com/reactphp/event-loop#loop). -This value SHOULD NOT be given unless you're sure you want to explicitly use a -given event loop instance. - -> Advanced usage: Despite allowing any `ServerInterface` as first parameter, -you SHOULD pass a `TcpServer` instance as first parameter, unless you -know what you're doing. -Internally, the `SecureServer` has to set the required TLS context options on -the underlying stream resources. -These resources are not exposed through any of the interfaces defined in this -package, but only through the internal `Connection` class. -The `TcpServer` class is guaranteed to emit connections that implement -the `ConnectionInterface` and uses the internal `Connection` class in order to -expose these underlying resources. -If you use a custom `ServerInterface` and its `connection` event does not -meet this requirement, the `SecureServer` will emit an `error` event and -then close the underlying connection. - -#### UnixServer - -The `UnixServer` class implements the [`ServerInterface`](#serverinterface) and -is responsible for accepting connections on Unix domain sockets (UDS). - -```php -$server = new React\Socket\UnixServer('/tmp/server.sock'); -``` - -As above, the `$uri` parameter can consist of only a socket path or socket path -prefixed by the `unix://` scheme. - -If the given URI appears to be valid, but listening on it fails (such as if the -socket is already in use or the file not accessible etc.), it will throw a -`RuntimeException`: - -```php -$first = new React\Socket\UnixServer('/tmp/same.sock'); - -// throws RuntimeException because socket is already in use -$second = new React\Socket\UnixServer('/tmp/same.sock'); -``` - -> Note that these error conditions may vary depending on your system and/or - configuration. - In particular, Zend PHP does only report "Unknown error" when the UDS path - already exists and can not be bound. You may want to check `is_file()` on the - given UDS path to report a more user-friendly error message in this case. - See the exception message and code for more details about the actual error - condition. - -This class takes an optional `LoopInterface|null $loop` parameter that can be used to -pass the event loop instance to use for this object. You can use a `null` value -here in order to use the [default loop](https://github.com/reactphp/event-loop#loop). -This value SHOULD NOT be given unless you're sure you want to explicitly use a -given event loop instance. - -Whenever a client connects, it will emit a `connection` event with a connection -instance implementing [`ConnectionInterface`](#connectioninterface): - -```php -$server->on('connection', function (React\Socket\ConnectionInterface $connection) { - echo 'New connection' . PHP_EOL; - - $connection->write('hello there!' . PHP_EOL); - … -}); -``` - -See also the [`ServerInterface`](#serverinterface) for more details. - -#### LimitingServer - -The `LimitingServer` decorator wraps a given `ServerInterface` and is responsible -for limiting and keeping track of open connections to this server instance. - -Whenever the underlying server emits a `connection` event, it will check its -limits and then either - - keep track of this connection by adding it to the list of - open connections and then forward the `connection` event - - or reject (close) the connection when its limits are exceeded and will - forward an `error` event instead. - -Whenever a connection closes, it will remove this connection from the list of -open connections. - -```php -$server = new React\Socket\LimitingServer($server, 100); -$server->on('connection', function (React\Socket\ConnectionInterface $connection) { - $connection->write('hello there!' . PHP_EOL); - … -}); -``` - -See also the [second example](examples) for more details. - -You have to pass a maximum number of open connections to ensure -the server will automatically reject (close) connections once this limit -is exceeded. In this case, it will emit an `error` event to inform about -this and no `connection` event will be emitted. - -```php -$server = new React\Socket\LimitingServer($server, 100); -$server->on('connection', function (React\Socket\ConnectionInterface $connection) { - $connection->write('hello there!' . PHP_EOL); - … -}); -``` - -You MAY pass a `null` limit in order to put no limit on the number of -open connections and keep accepting new connection until you run out of -operating system resources (such as open file handles). This may be -useful if you do not want to take care of applying a limit but still want -to use the `getConnections()` method. - -You can optionally configure the server to pause accepting new -connections once the connection limit is reached. In this case, it will -pause the underlying server and no longer process any new connections at -all, thus also no longer closing any excessive connections. -The underlying operating system is responsible for keeping a backlog of -pending connections until its limit is reached, at which point it will -start rejecting further connections. -Once the server is below the connection limit, it will continue consuming -connections from the backlog and will process any outstanding data on -each connection. -This mode may be useful for some protocols that are designed to wait for -a response message (such as HTTP), but may be less useful for other -protocols that demand immediate responses (such as a "welcome" message in -an interactive chat). - -```php -$server = new React\Socket\LimitingServer($server, 100, true); -$server->on('connection', function (React\Socket\ConnectionInterface $connection) { - $connection->write('hello there!' . PHP_EOL); - … -}); -``` - -##### getConnections() - -The `getConnections(): ConnectionInterface[]` method can be used to -return an array with all currently active connections. - -```php -foreach ($server->getConnection() as $connection) { - $connection->write('Hi!'); -} -``` - -## Client usage - -### ConnectorInterface - -The `ConnectorInterface` is responsible for providing an interface for -establishing streaming connections, such as a normal TCP/IP connection. - -This is the main interface defined in this package and it is used throughout -React's vast ecosystem. - -Most higher-level components (such as HTTP, database or other networking -service clients) accept an instance implementing this interface to create their -TCP/IP connection to the underlying networking service. -This is usually done via dependency injection, so it's fairly simple to actually -swap this implementation against any other implementation of this interface. - -The interface only offers a single method: - -#### connect() - -The `connect(string $uri): PromiseInterface` method can be used to -create a streaming connection to the given remote address. - -It returns a [Promise](https://github.com/reactphp/promise) which either -fulfills with a stream implementing [`ConnectionInterface`](#connectioninterface) -on success or rejects with an `Exception` if the connection is not successful: - -```php -$connector->connect('google.com:443')->then( - function (React\Socket\ConnectionInterface $connection) { - // connection successfully established - }, - function (Exception $error) { - // failed to connect due to $error - } -); -``` - -See also [`ConnectionInterface`](#connectioninterface) for more details. - -The returned Promise MUST be implemented in such a way that it can be -cancelled when it is still pending. Cancelling a pending promise MUST -reject its value with an `Exception`. It SHOULD clean up any underlying -resources and references as applicable: - -```php -$promise = $connector->connect($uri); - -$promise->cancel(); -``` - -### Connector - -The `Connector` class is the main class in this package that implements the -[`ConnectorInterface`](#connectorinterface) and allows you to create streaming connections. - -You can use this connector to create any kind of streaming connections, such -as plaintext TCP/IP, secure TLS or local Unix connection streams. - -It binds to the main event loop and can be used like this: - -```php -$connector = new React\Socket\Connector(); - -$connector->connect($uri)->then(function (React\Socket\ConnectionInterface $connection) { - $connection->write('...'); - $connection->end(); -}, function (Exception $e) { - echo 'Error: ' . $e->getMessage() . PHP_EOL; -}); -``` - -In order to create a plaintext TCP/IP connection, you can simply pass a host -and port combination like this: - -```php -$connector->connect('www.google.com:80')->then(function (React\Socket\ConnectionInterface $connection) { - $connection->write('...'); - $connection->end(); -}); -``` - -> If you do no specify a URI scheme in the destination URI, it will assume - `tcp://` as a default and establish a plaintext TCP/IP connection. - Note that TCP/IP connections require a host and port part in the destination - URI like above, all other URI components are optional. - -In order to create a secure TLS connection, you can use the `tls://` URI scheme -like this: - -```php -$connector->connect('tls://www.google.com:443')->then(function (React\Socket\ConnectionInterface $connection) { - $connection->write('...'); - $connection->end(); -}); -``` - -In order to create a local Unix domain socket connection, you can use the -`unix://` URI scheme like this: - -```php -$connector->connect('unix:///tmp/demo.sock')->then(function (React\Socket\ConnectionInterface $connection) { - $connection->write('...'); - $connection->end(); -}); -``` - -> The [`getRemoteAddress()`](#getremoteaddress) method will return the target - Unix domain socket (UDS) path as given to the `connect()` method, including - the `unix://` scheme, for example `unix:///tmp/demo.sock`. - The [`getLocalAddress()`](#getlocaladdress) method will most likely return a - `null` value as this value is not applicable to UDS connections here. - -Under the hood, the `Connector` is implemented as a *higher-level facade* -for the lower-level connectors implemented in this package. This means it -also shares all of their features and implementation details. -If you want to typehint in your higher-level protocol implementation, you SHOULD -use the generic [`ConnectorInterface`](#connectorinterface) instead. - -As of `v1.4.0`, the `Connector` class defaults to using the -[happy eyeballs algorithm](https://en.wikipedia.org/wiki/Happy_Eyeballs) to -automatically connect over IPv4 or IPv6 when a hostname is given. -This automatically attempts to connect using both IPv4 and IPv6 at the same time -(preferring IPv6), thus avoiding the usual problems faced by users with imperfect -IPv6 connections or setups. -If you want to revert to the old behavior of only doing an IPv4 lookup and -only attempt a single IPv4 connection, you can set up the `Connector` like this: - -```php -$connector = new React\Socket\Connector(array( - 'happy_eyeballs' => false -)); -``` - -Similarly, you can also affect the default DNS behavior as follows. -The `Connector` class will try to detect your system DNS settings (and uses -Google's public DNS server `8.8.8.8` as a fallback if unable to determine your -system settings) to resolve all public hostnames into underlying IP addresses by -default. -If you explicitly want to use a custom DNS server (such as a local DNS relay or -a company wide DNS server), you can set up the `Connector` like this: - -```php -$connector = new React\Socket\Connector(array( - 'dns' => '127.0.1.1' -)); - -$connector->connect('localhost:80')->then(function (React\Socket\ConnectionInterface $connection) { - $connection->write('...'); - $connection->end(); -}); -``` - -If you do not want to use a DNS resolver at all and want to connect to IP -addresses only, you can also set up your `Connector` like this: - -```php -$connector = new React\Socket\Connector(array( - 'dns' => false -)); - -$connector->connect('127.0.0.1:80')->then(function (React\Socket\ConnectionInterface $connection) { - $connection->write('...'); - $connection->end(); -}); -``` - -Advanced: If you need a custom DNS `React\Dns\Resolver\ResolverInterface` instance, you -can also set up your `Connector` like this: - -```php -$dnsResolverFactory = new React\Dns\Resolver\Factory(); -$resolver = $dnsResolverFactory->createCached('127.0.1.1'); - -$connector = new React\Socket\Connector(array( - 'dns' => $resolver -)); - -$connector->connect('localhost:80')->then(function (React\Socket\ConnectionInterface $connection) { - $connection->write('...'); - $connection->end(); -}); -``` - -By default, the `tcp://` and `tls://` URI schemes will use timeout value that -respects your `default_socket_timeout` ini setting (which defaults to 60s). -If you want a custom timeout value, you can simply pass this like this: - -```php -$connector = new React\Socket\Connector(array( - 'timeout' => 10.0 -)); -``` - -Similarly, if you do not want to apply a timeout at all and let the operating -system handle this, you can pass a boolean flag like this: - -```php -$connector = new React\Socket\Connector(array( - 'timeout' => false -)); -``` - -By default, the `Connector` supports the `tcp://`, `tls://` and `unix://` -URI schemes. If you want to explicitly prohibit any of these, you can simply -pass boolean flags like this: - -```php -// only allow secure TLS connections -$connector = new React\Socket\Connector(array( - 'tcp' => false, - 'tls' => true, - 'unix' => false, -)); - -$connector->connect('tls://google.com:443')->then(function (React\Socket\ConnectionInterface $connection) { - $connection->write('...'); - $connection->end(); -}); -``` - -The `tcp://` and `tls://` also accept additional context options passed to -the underlying connectors. -If you want to explicitly pass additional context options, you can simply -pass arrays of context options like this: - -```php -// allow insecure TLS connections -$connector = new React\Socket\Connector(array( - 'tcp' => array( - 'bindto' => '192.168.0.1:0' - ), - 'tls' => array( - 'verify_peer' => false, - 'verify_peer_name' => false - ), -)); - -$connector->connect('tls://localhost:443')->then(function (React\Socket\ConnectionInterface $connection) { - $connection->write('...'); - $connection->end(); -}); -``` - -By default, this connector supports TLSv1.0+ and excludes support for legacy -SSLv2/SSLv3. As of PHP 5.6+ you can also explicitly choose the TLS version you -want to negotiate with the remote side: - -```php -$connector = new React\Socket\Connector(array( - 'tls' => array( - 'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT - ) -)); -``` - -> For more details about context options, please refer to the PHP documentation - about [socket context options](https://www.php.net/manual/en/context.socket.php) - and [SSL context options](https://www.php.net/manual/en/context.ssl.php). - -Advanced: By default, the `Connector` supports the `tcp://`, `tls://` and -`unix://` URI schemes. -For this, it sets up the required connector classes automatically. -If you want to explicitly pass custom connectors for any of these, you can simply -pass an instance implementing the `ConnectorInterface` like this: - -```php -$dnsResolverFactory = new React\Dns\Resolver\Factory(); -$resolver = $dnsResolverFactory->createCached('127.0.1.1'); -$tcp = new React\Socket\HappyEyeBallsConnector(null, new React\Socket\TcpConnector(), $resolver); - -$tls = new React\Socket\SecureConnector($tcp); - -$unix = new React\Socket\UnixConnector(); - -$connector = new React\Socket\Connector(array( - 'tcp' => $tcp, - 'tls' => $tls, - 'unix' => $unix, - - 'dns' => false, - 'timeout' => false, -)); - -$connector->connect('google.com:80')->then(function (React\Socket\ConnectionInterface $connection) { - $connection->write('...'); - $connection->end(); -}); -``` - -> Internally, the `tcp://` connector will always be wrapped by the DNS resolver, - unless you disable DNS like in the above example. In this case, the `tcp://` - connector receives the actual hostname instead of only the resolved IP address - and is thus responsible for performing the lookup. - Internally, the automatically created `tls://` connector will always wrap the - underlying `tcp://` connector for establishing the underlying plaintext - TCP/IP connection before enabling secure TLS mode. If you want to use a custom - underlying `tcp://` connector for secure TLS connections only, you may - explicitly pass a `tls://` connector like above instead. - Internally, the `tcp://` and `tls://` connectors will always be wrapped by - `TimeoutConnector`, unless you disable timeouts like in the above example. - -This class takes an optional `LoopInterface|null $loop` parameter that can be used to -pass the event loop instance to use for this object. You can use a `null` value -here in order to use the [default loop](https://github.com/reactphp/event-loop#loop). -This value SHOULD NOT be given unless you're sure you want to explicitly use a -given event loop instance. - -> Changelog v1.9.0: The constructur signature has been updated to take the -> optional `$context` as the first parameter and the optional `$loop` as a second -> argument. The previous signature has been deprecated and should not be used anymore. -> -> ```php -> // constructor signature as of v1.9.0 -> $connector = new React\Socket\Connector(array $context = [], ?LoopInterface $loop = null); -> -> // legacy constructor signature before v1.9.0 -> $connector = new React\Socket\Connector(?LoopInterface $loop = null, array $context = []); -> ``` - -### Advanced client usage - -#### TcpConnector - -The `TcpConnector` class implements the -[`ConnectorInterface`](#connectorinterface) and allows you to create plaintext -TCP/IP connections to any IP-port-combination: - -```php -$tcpConnector = new React\Socket\TcpConnector(); - -$tcpConnector->connect('127.0.0.1:80')->then(function (React\Socket\ConnectionInterface $connection) { - $connection->write('...'); - $connection->end(); -}); -``` - -See also the [examples](examples). - -Pending connection attempts can be cancelled by cancelling its pending promise like so: - -```php -$promise = $tcpConnector->connect('127.0.0.1:80'); - -$promise->cancel(); -``` - -Calling `cancel()` on a pending promise will close the underlying socket -resource, thus cancelling the pending TCP/IP connection, and reject the -resulting promise. - -This class takes an optional `LoopInterface|null $loop` parameter that can be used to -pass the event loop instance to use for this object. You can use a `null` value -here in order to use the [default loop](https://github.com/reactphp/event-loop#loop). -This value SHOULD NOT be given unless you're sure you want to explicitly use a -given event loop instance. - -You can optionally pass additional -[socket context options](https://www.php.net/manual/en/context.socket.php) -to the constructor like this: - -```php -$tcpConnector = new React\Socket\TcpConnector(null, array( - 'bindto' => '192.168.0.1:0' -)); -``` - -Note that this class only allows you to connect to IP-port-combinations. -If the given URI is invalid, does not contain a valid IP address and port -or contains any other scheme, it will reject with an -`InvalidArgumentException`: - -If the given URI appears to be valid, but connecting to it fails (such as if -the remote host rejects the connection etc.), it will reject with a -`RuntimeException`. - -If you want to connect to hostname-port-combinations, see also the following chapter. - -> Advanced usage: Internally, the `TcpConnector` allocates an empty *context* -resource for each stream resource. -If the destination URI contains a `hostname` query parameter, its value will -be used to set up the TLS peer name. -This is used by the `SecureConnector` and `DnsConnector` to verify the peer -name and can also be used if you want a custom TLS peer name. - -#### HappyEyeBallsConnector - -The `HappyEyeBallsConnector` class implements the -[`ConnectorInterface`](#connectorinterface) and allows you to create plaintext -TCP/IP connections to any hostname-port-combination. Internally it implements the -happy eyeballs algorithm from [`RFC6555`](https://tools.ietf.org/html/rfc6555) and -[`RFC8305`](https://tools.ietf.org/html/rfc8305) to support IPv6 and IPv4 hostnames. - -It does so by decorating a given `TcpConnector` instance so that it first -looks up the given domain name via DNS (if applicable) and then establishes the -underlying TCP/IP connection to the resolved target IP address. - -Make sure to set up your DNS resolver and underlying TCP connector like this: - -```php -$dnsResolverFactory = new React\Dns\Resolver\Factory(); -$dns = $dnsResolverFactory->createCached('8.8.8.8'); - -$dnsConnector = new React\Socket\HappyEyeBallsConnector(null, $tcpConnector, $dns); - -$dnsConnector->connect('www.google.com:80')->then(function (React\Socket\ConnectionInterface $connection) { - $connection->write('...'); - $connection->end(); -}); -``` - -See also the [examples](examples). - -Pending connection attempts can be cancelled by cancelling its pending promise like so: - -```php -$promise = $dnsConnector->connect('www.google.com:80'); - -$promise->cancel(); -``` - -Calling `cancel()` on a pending promise will cancel the underlying DNS lookups -and/or the underlying TCP/IP connection(s) and reject the resulting promise. - -This class takes an optional `LoopInterface|null $loop` parameter that can be used to -pass the event loop instance to use for this object. You can use a `null` value -here in order to use the [default loop](https://github.com/reactphp/event-loop#loop). -This value SHOULD NOT be given unless you're sure you want to explicitly use a -given event loop instance. - -> Advanced usage: Internally, the `HappyEyeBallsConnector` relies on a `Resolver` to -look up the IP addresses for the given hostname. -It will then replace the hostname in the destination URI with this IP's and -append a `hostname` query parameter and pass this updated URI to the underlying -connector. -The Happy Eye Balls algorithm describes looking the IPv6 and IPv4 address for -the given hostname so this connector sends out two DNS lookups for the A and -AAAA records. It then uses all IP addresses (both v6 and v4) and tries to -connect to all of them with a 50ms interval in between. Alterating between IPv6 -and IPv4 addresses. When a connection is established all the other DNS lookups -and connection attempts are cancelled. - -#### DnsConnector - -The `DnsConnector` class implements the -[`ConnectorInterface`](#connectorinterface) and allows you to create plaintext -TCP/IP connections to any hostname-port-combination. - -It does so by decorating a given `TcpConnector` instance so that it first -looks up the given domain name via DNS (if applicable) and then establishes the -underlying TCP/IP connection to the resolved target IP address. - -Make sure to set up your DNS resolver and underlying TCP connector like this: - -```php -$dnsResolverFactory = new React\Dns\Resolver\Factory(); -$dns = $dnsResolverFactory->createCached('8.8.8.8'); - -$dnsConnector = new React\Socket\DnsConnector($tcpConnector, $dns); - -$dnsConnector->connect('www.google.com:80')->then(function (React\Socket\ConnectionInterface $connection) { - $connection->write('...'); - $connection->end(); -}); -``` - -See also the [examples](examples). - -Pending connection attempts can be cancelled by cancelling its pending promise like so: - -```php -$promise = $dnsConnector->connect('www.google.com:80'); - -$promise->cancel(); -``` - -Calling `cancel()` on a pending promise will cancel the underlying DNS lookup -and/or the underlying TCP/IP connection and reject the resulting promise. - -> Advanced usage: Internally, the `DnsConnector` relies on a `React\Dns\Resolver\ResolverInterface` -to look up the IP address for the given hostname. -It will then replace the hostname in the destination URI with this IP and -append a `hostname` query parameter and pass this updated URI to the underlying -connector. -The underlying connector is thus responsible for creating a connection to the -target IP address, while this query parameter can be used to check the original -hostname and is used by the `TcpConnector` to set up the TLS peer name. -If a `hostname` is given explicitly, this query parameter will not be modified, -which can be useful if you want a custom TLS peer name. - -#### SecureConnector - -The `SecureConnector` class implements the -[`ConnectorInterface`](#connectorinterface) and allows you to create secure -TLS (formerly known as SSL) connections to any hostname-port-combination. - -It does so by decorating a given `DnsConnector` instance so that it first -creates a plaintext TCP/IP connection and then enables TLS encryption on this -stream. - -```php -$secureConnector = new React\Socket\SecureConnector($dnsConnector); - -$secureConnector->connect('www.google.com:443')->then(function (React\Socket\ConnectionInterface $connection) { - $connection->write("GET / HTTP/1.0\r\nHost: www.google.com\r\n\r\n"); - ... -}); -``` - -See also the [examples](examples). - -Pending connection attempts can be cancelled by cancelling its pending promise like so: - -```php -$promise = $secureConnector->connect('www.google.com:443'); - -$promise->cancel(); -``` - -Calling `cancel()` on a pending promise will cancel the underlying TCP/IP -connection and/or the SSL/TLS negotiation and reject the resulting promise. - -This class takes an optional `LoopInterface|null $loop` parameter that can be used to -pass the event loop instance to use for this object. You can use a `null` value -here in order to use the [default loop](https://github.com/reactphp/event-loop#loop). -This value SHOULD NOT be given unless you're sure you want to explicitly use a -given event loop instance. - -You can optionally pass additional -[SSL context options](https://www.php.net/manual/en/context.ssl.php) -to the constructor like this: - -```php -$secureConnector = new React\Socket\SecureConnector($dnsConnector, null, array( - 'verify_peer' => false, - 'verify_peer_name' => false -)); -``` - -By default, this connector supports TLSv1.0+ and excludes support for legacy -SSLv2/SSLv3. As of PHP 5.6+ you can also explicitly choose the TLS version you -want to negotiate with the remote side: - -```php -$secureConnector = new React\Socket\SecureConnector($dnsConnector, null, array( - 'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT -)); -``` - -> Advanced usage: Internally, the `SecureConnector` relies on setting up the -required *context options* on the underlying stream resource. -It should therefor be used with a `TcpConnector` somewhere in the connector -stack so that it can allocate an empty *context* resource for each stream -resource and verify the peer name. -Failing to do so may result in a TLS peer name mismatch error or some hard to -trace race conditions, because all stream resources will use a single, shared -*default context* resource otherwise. - -#### TimeoutConnector - -The `TimeoutConnector` class implements the -[`ConnectorInterface`](#connectorinterface) and allows you to add timeout -handling to any existing connector instance. - -It does so by decorating any given [`ConnectorInterface`](#connectorinterface) -instance and starting a timer that will automatically reject and abort any -underlying connection attempt if it takes too long. - -```php -$timeoutConnector = new React\Socket\TimeoutConnector($connector, 3.0); - -$timeoutConnector->connect('google.com:80')->then(function (React\Socket\ConnectionInterface $connection) { - // connection succeeded within 3.0 seconds -}); -``` - -See also any of the [examples](examples). - -This class takes an optional `LoopInterface|null $loop` parameter that can be used to -pass the event loop instance to use for this object. You can use a `null` value -here in order to use the [default loop](https://github.com/reactphp/event-loop#loop). -This value SHOULD NOT be given unless you're sure you want to explicitly use a -given event loop instance. - -Pending connection attempts can be cancelled by cancelling its pending promise like so: - -```php -$promise = $timeoutConnector->connect('google.com:80'); - -$promise->cancel(); -``` - -Calling `cancel()` on a pending promise will cancel the underlying connection -attempt, abort the timer and reject the resulting promise. - -#### UnixConnector - -The `UnixConnector` class implements the -[`ConnectorInterface`](#connectorinterface) and allows you to connect to -Unix domain socket (UDS) paths like this: - -```php -$connector = new React\Socket\UnixConnector(); - -$connector->connect('/tmp/demo.sock')->then(function (React\Socket\ConnectionInterface $connection) { - $connection->write("HELLO\n"); -}); -``` - -Connecting to Unix domain sockets is an atomic operation, i.e. its promise will -settle (either resolve or reject) immediately. -As such, calling `cancel()` on the resulting promise has no effect. - -> The [`getRemoteAddress()`](#getremoteaddress) method will return the target - Unix domain socket (UDS) path as given to the `connect()` method, prepended - with the `unix://` scheme, for example `unix:///tmp/demo.sock`. - The [`getLocalAddress()`](#getlocaladdress) method will most likely return a - `null` value as this value is not applicable to UDS connections here. - -This class takes an optional `LoopInterface|null $loop` parameter that can be used to -pass the event loop instance to use for this object. You can use a `null` value -here in order to use the [default loop](https://github.com/reactphp/event-loop#loop). -This value SHOULD NOT be given unless you're sure you want to explicitly use a -given event loop instance. - -#### FixedUriConnector - -The `FixedUriConnector` class implements the -[`ConnectorInterface`](#connectorinterface) and decorates an existing Connector -to always use a fixed, preconfigured URI. - -This can be useful for consumers that do not support certain URIs, such as -when you want to explicitly connect to a Unix domain socket (UDS) path -instead of connecting to a default address assumed by an higher-level API: - -```php -$connector = new React\Socket\FixedUriConnector( - 'unix:///var/run/docker.sock', - new React\Socket\UnixConnector() -); - -// destination will be ignored, actually connects to Unix domain socket -$promise = $connector->connect('localhost:80'); -``` - -## Install - -The recommended way to install this library is [through Composer](https://getcomposer.org/). -[New to Composer?](https://getcomposer.org/doc/00-intro.md) - -This project follows [SemVer](https://semver.org/). -This will install the latest supported version: - -```bash -composer require react/socket:^1.15 -``` - -See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades. - -This project aims to run on any platform and thus does not require any PHP -extensions and supports running on legacy PHP 5.3 through current PHP 8+ and HHVM. -It's *highly recommended to use the latest supported PHP version* for this project, -partly due to its vast performance improvements and partly because legacy PHP -versions require several workarounds as described below. - -Secure TLS connections received some major upgrades starting with PHP 5.6, with -the defaults now being more secure, while older versions required explicit -context options. -This library does not take responsibility over these context options, so it's -up to consumers of this library to take care of setting appropriate context -options as described above. - -PHP < 7.3.3 (and PHP < 7.2.15) suffers from a bug where feof() might -block with 100% CPU usage on fragmented TLS records. -We try to work around this by always consuming the complete receive -buffer at once to avoid stale data in TLS buffers. This is known to -work around high CPU usage for well-behaving peers, but this may -cause very large data chunks for high throughput scenarios. The buggy -behavior can still be triggered due to network I/O buffers or -malicious peers on affected versions, upgrading is highly recommended. - -PHP < 7.1.4 (and PHP < 7.0.18) suffers from a bug when writing big -chunks of data over TLS streams at once. -We try to work around this by limiting the write chunk size to 8192 -bytes for older PHP versions only. -This is only a work-around and has a noticable performance penalty on -affected versions. - -This project also supports running on HHVM. -Note that really old HHVM < 3.8 does not support secure TLS connections, as it -lacks the required `stream_socket_enable_crypto()` function. -As such, trying to create a secure TLS connections on affected versions will -return a rejected promise instead. -This issue is also covered by our test suite, which will skip related tests -on affected versions. - -## Tests - -To run the test suite, you first need to clone this repo and then install all -dependencies [through Composer](https://getcomposer.org/): - -```bash -composer install -``` - -To run the test suite, go to the project root and run: - -```bash -vendor/bin/phpunit -``` - -The test suite also contains a number of functional integration tests that rely -on a stable internet connection. -If you do not want to run these, they can simply be skipped like this: - -```bash -vendor/bin/phpunit --exclude-group internet -``` - -## License - -MIT, see [LICENSE file](LICENSE). diff --git a/digital_doctor/vendor/react/socket/composer.json b/digital_doctor/vendor/react/socket/composer.json deleted file mode 100644 index 02c184f..0000000 --- a/digital_doctor/vendor/react/socket/composer.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "name": "react/socket", - "description": "Async, streaming plaintext TCP/IP and secure TLS socket server and client connections for ReactPHP", - "keywords": ["async", "socket", "stream", "connection", "ReactPHP"], - "license": "MIT", - "authors": [ - { - "name": "Christian Lück", - "homepage": "https://clue.engineering/", - "email": "christian@clue.engineering" - }, - { - "name": "Cees-Jan Kiewiet", - "homepage": "https://wyrihaximus.net/", - "email": "reactphp@ceesjankiewiet.nl" - }, - { - "name": "Jan Sorgalla", - "homepage": "https://sorgalla.com/", - "email": "jsorgalla@gmail.com" - }, - { - "name": "Chris Boden", - "homepage": "https://cboden.dev/", - "email": "cboden@gmail.com" - } - ], - "require": { - "php": ">=5.3.0", - "evenement/evenement": "^3.0 || ^2.0 || ^1.0", - "react/dns": "^1.11", - "react/event-loop": "^1.2", - "react/promise": "^3 || ^2.6 || ^1.2.1", - "react/stream": "^1.2" - }, - "require-dev": { - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", - "react/async": "^4 || ^3 || ^2", - "react/promise-stream": "^1.4", - "react/promise-timer": "^1.10" - }, - "autoload": { - "psr-4": { - "React\\Socket\\": "src/" - } - }, - "autoload-dev": { - "psr-4": { - "React\\Tests\\Socket\\": "tests/" - } - } -} diff --git a/digital_doctor/vendor/react/socket/src/Connection.php b/digital_doctor/vendor/react/socket/src/Connection.php deleted file mode 100644 index 65ae26b..0000000 --- a/digital_doctor/vendor/react/socket/src/Connection.php +++ /dev/null @@ -1,183 +0,0 @@ -= 70300 && \PHP_VERSION_ID < 70303); - - // PHP < 7.1.4 (and PHP < 7.0.18) suffers from a bug when writing big - // chunks of data over TLS streams at once. - // We try to work around this by limiting the write chunk size to 8192 - // bytes for older PHP versions only. - // This is only a work-around and has a noticable performance penalty on - // affected versions. Please update your PHP version. - // This applies to all streams because TLS may be enabled later on. - // See https://github.com/reactphp/socket/issues/105 - $limitWriteChunks = (\PHP_VERSION_ID < 70018 || (\PHP_VERSION_ID >= 70100 && \PHP_VERSION_ID < 70104)); - - $this->input = new DuplexResourceStream( - $resource, - $loop, - $clearCompleteBuffer ? -1 : null, - new WritableResourceStream($resource, $loop, null, $limitWriteChunks ? 8192 : null) - ); - - $this->stream = $resource; - - Util::forwardEvents($this->input, $this, array('data', 'end', 'error', 'close', 'pipe', 'drain')); - - $this->input->on('close', array($this, 'close')); - } - - public function isReadable() - { - return $this->input->isReadable(); - } - - public function isWritable() - { - return $this->input->isWritable(); - } - - public function pause() - { - $this->input->pause(); - } - - public function resume() - { - $this->input->resume(); - } - - public function pipe(WritableStreamInterface $dest, array $options = array()) - { - return $this->input->pipe($dest, $options); - } - - public function write($data) - { - return $this->input->write($data); - } - - public function end($data = null) - { - $this->input->end($data); - } - - public function close() - { - $this->input->close(); - $this->handleClose(); - $this->removeAllListeners(); - } - - public function handleClose() - { - if (!\is_resource($this->stream)) { - return; - } - - // Try to cleanly shut down socket and ignore any errors in case other - // side already closed. Underlying Stream implementation will take care - // of closing stream resource, so we otherwise keep this open here. - @\stream_socket_shutdown($this->stream, \STREAM_SHUT_RDWR); - } - - public function getRemoteAddress() - { - if (!\is_resource($this->stream)) { - return null; - } - - return $this->parseAddress(\stream_socket_get_name($this->stream, true)); - } - - public function getLocalAddress() - { - if (!\is_resource($this->stream)) { - return null; - } - - return $this->parseAddress(\stream_socket_get_name($this->stream, false)); - } - - private function parseAddress($address) - { - if ($address === false) { - return null; - } - - if ($this->unix) { - // remove trailing colon from address for HHVM < 3.19: https://3v4l.org/5C1lo - // note that technically ":" is a valid address, so keep this in place otherwise - if (\substr($address, -1) === ':' && \defined('HHVM_VERSION_ID') && \HHVM_VERSION_ID < 31900) { - $address = (string)\substr($address, 0, -1); // @codeCoverageIgnore - } - - // work around unknown addresses should return null value: https://3v4l.org/5C1lo and https://bugs.php.net/bug.php?id=74556 - // PHP uses "\0" string and HHVM uses empty string (colon removed above) - if ($address === '' || $address[0] === "\x00" ) { - return null; // @codeCoverageIgnore - } - - return 'unix://' . $address; - } - - // check if this is an IPv6 address which includes multiple colons but no square brackets - $pos = \strrpos($address, ':'); - if ($pos !== false && \strpos($address, ':') < $pos && \substr($address, 0, 1) !== '[') { - $address = '[' . \substr($address, 0, $pos) . ']:' . \substr($address, $pos + 1); // @codeCoverageIgnore - } - - return ($this->encryptionEnabled ? 'tls' : 'tcp') . '://' . $address; - } -} diff --git a/digital_doctor/vendor/react/socket/src/ConnectionInterface.php b/digital_doctor/vendor/react/socket/src/ConnectionInterface.php deleted file mode 100644 index 64613b5..0000000 --- a/digital_doctor/vendor/react/socket/src/ConnectionInterface.php +++ /dev/null @@ -1,119 +0,0 @@ -on('data', function ($chunk) { - * echo $chunk; - * }); - * - * $connection->on('end', function () { - * echo 'ended'; - * }); - * - * $connection->on('error', function (Exception $e) { - * echo 'error: ' . $e->getMessage(); - * }); - * - * $connection->on('close', function () { - * echo 'closed'; - * }); - * - * $connection->write($data); - * $connection->end($data = null); - * $connection->close(); - * // … - * ``` - * - * For more details, see the - * [`DuplexStreamInterface`](https://github.com/reactphp/stream#duplexstreaminterface). - * - * @see DuplexStreamInterface - * @see ServerInterface - * @see ConnectorInterface - */ -interface ConnectionInterface extends DuplexStreamInterface -{ - /** - * Returns the full remote address (URI) where this connection has been established with - * - * ```php - * $address = $connection->getRemoteAddress(); - * echo 'Connection with ' . $address . PHP_EOL; - * ``` - * - * If the remote address can not be determined or is unknown at this time (such as - * after the connection has been closed), it MAY return a `NULL` value instead. - * - * Otherwise, it will return the full address (URI) as a string value, such - * as `tcp://127.0.0.1:8080`, `tcp://[::1]:80`, `tls://127.0.0.1:443`, - * `unix://example.sock` or `unix:///path/to/example.sock`. - * Note that individual URI components are application specific and depend - * on the underlying transport protocol. - * - * If this is a TCP/IP based connection and you only want the remote IP, you may - * use something like this: - * - * ```php - * $address = $connection->getRemoteAddress(); - * $ip = trim(parse_url($address, PHP_URL_HOST), '[]'); - * echo 'Connection with ' . $ip . PHP_EOL; - * ``` - * - * @return ?string remote address (URI) or null if unknown - */ - public function getRemoteAddress(); - - /** - * Returns the full local address (full URI with scheme, IP and port) where this connection has been established with - * - * ```php - * $address = $connection->getLocalAddress(); - * echo 'Connection with ' . $address . PHP_EOL; - * ``` - * - * If the local address can not be determined or is unknown at this time (such as - * after the connection has been closed), it MAY return a `NULL` value instead. - * - * Otherwise, it will return the full address (URI) as a string value, such - * as `tcp://127.0.0.1:8080`, `tcp://[::1]:80`, `tls://127.0.0.1:443`, - * `unix://example.sock` or `unix:///path/to/example.sock`. - * Note that individual URI components are application specific and depend - * on the underlying transport protocol. - * - * This method complements the [`getRemoteAddress()`](#getremoteaddress) method, - * so they should not be confused. - * - * If your `TcpServer` instance is listening on multiple interfaces (e.g. using - * the address `0.0.0.0`), you can use this method to find out which interface - * actually accepted this connection (such as a public or local interface). - * - * If your system has multiple interfaces (e.g. a WAN and a LAN interface), - * you can use this method to find out which interface was actually - * used for this connection. - * - * @return ?string local address (URI) or null if unknown - * @see self::getRemoteAddress() - */ - public function getLocalAddress(); -} diff --git a/digital_doctor/vendor/react/socket/src/Connector.php b/digital_doctor/vendor/react/socket/src/Connector.php deleted file mode 100644 index 15faa46..0000000 --- a/digital_doctor/vendor/react/socket/src/Connector.php +++ /dev/null @@ -1,236 +0,0 @@ - true, - 'tls' => true, - 'unix' => true, - - 'dns' => true, - 'timeout' => true, - 'happy_eyeballs' => true, - ); - - if ($context['timeout'] === true) { - $context['timeout'] = (float)\ini_get("default_socket_timeout"); - } - - if ($context['tcp'] instanceof ConnectorInterface) { - $tcp = $context['tcp']; - } else { - $tcp = new TcpConnector( - $loop, - \is_array($context['tcp']) ? $context['tcp'] : array() - ); - } - - if ($context['dns'] !== false) { - if ($context['dns'] instanceof ResolverInterface) { - $resolver = $context['dns']; - } else { - if ($context['dns'] !== true) { - $config = $context['dns']; - } else { - // try to load nameservers from system config or default to Google's public DNS - $config = DnsConfig::loadSystemConfigBlocking(); - if (!$config->nameservers) { - $config->nameservers[] = '8.8.8.8'; // @codeCoverageIgnore - } - } - - $factory = new DnsFactory(); - $resolver = $factory->createCached( - $config, - $loop - ); - } - - if ($context['happy_eyeballs'] === true) { - $tcp = new HappyEyeBallsConnector($loop, $tcp, $resolver); - } else { - $tcp = new DnsConnector($tcp, $resolver); - } - } - - if ($context['tcp'] !== false) { - $context['tcp'] = $tcp; - - if ($context['timeout'] !== false) { - $context['tcp'] = new TimeoutConnector( - $context['tcp'], - $context['timeout'], - $loop - ); - } - - $this->connectors['tcp'] = $context['tcp']; - } - - if ($context['tls'] !== false) { - if (!$context['tls'] instanceof ConnectorInterface) { - $context['tls'] = new SecureConnector( - $tcp, - $loop, - \is_array($context['tls']) ? $context['tls'] : array() - ); - } - - if ($context['timeout'] !== false) { - $context['tls'] = new TimeoutConnector( - $context['tls'], - $context['timeout'], - $loop - ); - } - - $this->connectors['tls'] = $context['tls']; - } - - if ($context['unix'] !== false) { - if (!$context['unix'] instanceof ConnectorInterface) { - $context['unix'] = new UnixConnector($loop); - } - $this->connectors['unix'] = $context['unix']; - } - } - - public function connect($uri) - { - $scheme = 'tcp'; - if (\strpos($uri, '://') !== false) { - $scheme = (string)\substr($uri, 0, \strpos($uri, '://')); - } - - if (!isset($this->connectors[$scheme])) { - return \React\Promise\reject(new \RuntimeException( - 'No connector available for URI scheme "' . $scheme . '" (EINVAL)', - \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22) - )); - } - - return $this->connectors[$scheme]->connect($uri); - } - - - /** - * [internal] Builds on URI from the given URI parts and ip address with original hostname as query - * - * @param array $parts - * @param string $host - * @param string $ip - * @return string - * @internal - */ - public static function uri(array $parts, $host, $ip) - { - $uri = ''; - - // prepend original scheme if known - if (isset($parts['scheme'])) { - $uri .= $parts['scheme'] . '://'; - } - - if (\strpos($ip, ':') !== false) { - // enclose IPv6 addresses in square brackets before appending port - $uri .= '[' . $ip . ']'; - } else { - $uri .= $ip; - } - - // append original port if known - if (isset($parts['port'])) { - $uri .= ':' . $parts['port']; - } - - // append orignal path if known - if (isset($parts['path'])) { - $uri .= $parts['path']; - } - - // append original query if known - if (isset($parts['query'])) { - $uri .= '?' . $parts['query']; - } - - // append original hostname as query if resolved via DNS and if - // destination URI does not contain "hostname" query param already - $args = array(); - \parse_str(isset($parts['query']) ? $parts['query'] : '', $args); - if ($host !== $ip && !isset($args['hostname'])) { - $uri .= (isset($parts['query']) ? '&' : '?') . 'hostname=' . \rawurlencode($host); - } - - // append original fragment if known - if (isset($parts['fragment'])) { - $uri .= '#' . $parts['fragment']; - } - - return $uri; - } -} diff --git a/digital_doctor/vendor/react/socket/src/ConnectorInterface.php b/digital_doctor/vendor/react/socket/src/ConnectorInterface.php deleted file mode 100644 index 1f07b75..0000000 --- a/digital_doctor/vendor/react/socket/src/ConnectorInterface.php +++ /dev/null @@ -1,59 +0,0 @@ -connect('google.com:443')->then( - * function (React\Socket\ConnectionInterface $connection) { - * // connection successfully established - * }, - * function (Exception $error) { - * // failed to connect due to $error - * } - * ); - * ``` - * - * The returned Promise MUST be implemented in such a way that it can be - * cancelled when it is still pending. Cancelling a pending promise MUST - * reject its value with an Exception. It SHOULD clean up any underlying - * resources and references as applicable. - * - * ```php - * $promise = $connector->connect($uri); - * - * $promise->cancel(); - * ``` - * - * @param string $uri - * @return \React\Promise\PromiseInterface - * Resolves with a `ConnectionInterface` on success or rejects with an `Exception` on error. - * @see ConnectionInterface - */ - public function connect($uri); -} diff --git a/digital_doctor/vendor/react/socket/src/DnsConnector.php b/digital_doctor/vendor/react/socket/src/DnsConnector.php deleted file mode 100644 index d2fb2c7..0000000 --- a/digital_doctor/vendor/react/socket/src/DnsConnector.php +++ /dev/null @@ -1,117 +0,0 @@ -connector = $connector; - $this->resolver = $resolver; - } - - public function connect($uri) - { - $original = $uri; - if (\strpos($uri, '://') === false) { - $uri = 'tcp://' . $uri; - $parts = \parse_url($uri); - if (isset($parts['scheme'])) { - unset($parts['scheme']); - } - } else { - $parts = \parse_url($uri); - } - - if (!$parts || !isset($parts['host'])) { - return Promise\reject(new \InvalidArgumentException( - 'Given URI "' . $original . '" is invalid (EINVAL)', - \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22) - )); - } - - $host = \trim($parts['host'], '[]'); - $connector = $this->connector; - - // skip DNS lookup / URI manipulation if this URI already contains an IP - if (@\inet_pton($host) !== false) { - return $connector->connect($original); - } - - $promise = $this->resolver->resolve($host); - $resolved = null; - - return new Promise\Promise( - function ($resolve, $reject) use (&$promise, &$resolved, $uri, $connector, $host, $parts) { - // resolve/reject with result of DNS lookup - $promise->then(function ($ip) use (&$promise, &$resolved, $uri, $connector, $host, $parts) { - $resolved = $ip; - - return $promise = $connector->connect( - Connector::uri($parts, $host, $ip) - )->then(null, function (\Exception $e) use ($uri) { - if ($e instanceof \RuntimeException) { - $message = \preg_replace('/^(Connection to [^ ]+)[&?]hostname=[^ &]+/', '$1', $e->getMessage()); - $e = new \RuntimeException( - 'Connection to ' . $uri . ' failed: ' . $message, - $e->getCode(), - $e - ); - - // avoid garbage references by replacing all closures in call stack. - // what a lovely piece of code! - $r = new \ReflectionProperty('Exception', 'trace'); - $r->setAccessible(true); - $trace = $r->getValue($e); - - // Exception trace arguments are not available on some PHP 7.4 installs - // @codeCoverageIgnoreStart - foreach ($trace as $ti => $one) { - if (isset($one['args'])) { - foreach ($one['args'] as $ai => $arg) { - if ($arg instanceof \Closure) { - $trace[$ti]['args'][$ai] = 'Object(' . \get_class($arg) . ')'; - } - } - } - } - // @codeCoverageIgnoreEnd - $r->setValue($e, $trace); - } - - throw $e; - }); - }, function ($e) use ($uri, $reject) { - $reject(new \RuntimeException('Connection to ' . $uri .' failed during DNS lookup: ' . $e->getMessage(), 0, $e)); - })->then($resolve, $reject); - }, - function ($_, $reject) use (&$promise, &$resolved, $uri) { - // cancellation should reject connection attempt - // reject DNS resolution with custom reason, otherwise rely on connection cancellation below - if ($resolved === null) { - $reject(new \RuntimeException( - 'Connection to ' . $uri . ' cancelled during DNS lookup (ECONNABORTED)', - \defined('SOCKET_ECONNABORTED') ? \SOCKET_ECONNABORTED : 103 - )); - } - - // (try to) cancel pending DNS lookup / connection attempt - if ($promise instanceof PromiseInterface && \method_exists($promise, 'cancel')) { - // overwrite callback arguments for PHP7+ only, so they do not show - // up in the Exception trace and do not cause a possible cyclic reference. - $_ = $reject = null; - - $promise->cancel(); - $promise = null; - } - } - ); - } -} diff --git a/digital_doctor/vendor/react/socket/src/FdServer.php b/digital_doctor/vendor/react/socket/src/FdServer.php deleted file mode 100644 index b1ed777..0000000 --- a/digital_doctor/vendor/react/socket/src/FdServer.php +++ /dev/null @@ -1,218 +0,0 @@ -on('connection', function (ConnectionInterface $connection) { - * echo 'Plaintext connection from ' . $connection->getRemoteAddress() . PHP_EOL; - * $connection->write('hello there!' . PHP_EOL); - * … - * }); - * ``` - * - * See also the `ServerInterface` for more details. - * - * @see ServerInterface - * @see ConnectionInterface - * @internal - */ -final class FdServer extends EventEmitter implements ServerInterface -{ - private $master; - private $loop; - private $unix = false; - private $listening = false; - - /** - * Creates a socket server and starts listening on the given file descriptor - * - * This starts accepting new incoming connections on the given file descriptor. - * See also the `connection event` documented in the `ServerInterface` - * for more details. - * - * ```php - * $socket = new React\Socket\FdServer(3); - * ``` - * - * If the given FD is invalid or out of range, it will throw an `InvalidArgumentException`: - * - * ```php - * // throws InvalidArgumentException - * $socket = new React\Socket\FdServer(-1); - * ``` - * - * If the given FD appears to be valid, but listening on it fails (such as - * if the FD does not exist or does not refer to a socket server), it will - * throw a `RuntimeException`: - * - * ```php - * // throws RuntimeException because FD does not reference a socket server - * $socket = new React\Socket\FdServer(0, $loop); - * ``` - * - * Note that these error conditions may vary depending on your system and/or - * configuration. - * See the exception message and code for more details about the actual error - * condition. - * - * @param int|string $fd FD number such as `3` or as URL in the form of `php://fd/3` - * @param ?LoopInterface $loop - * @throws \InvalidArgumentException if the listening address is invalid - * @throws \RuntimeException if listening on this address fails (already in use etc.) - */ - public function __construct($fd, LoopInterface $loop = null) - { - if (\preg_match('#^php://fd/(\d+)$#', $fd, $m)) { - $fd = (int) $m[1]; - } - if (!\is_int($fd) || $fd < 0 || $fd >= \PHP_INT_MAX) { - throw new \InvalidArgumentException( - 'Invalid FD number given (EINVAL)', - \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22) - ); - } - - $this->loop = $loop ?: Loop::get(); - - $errno = 0; - $errstr = ''; - \set_error_handler(function ($_, $error) use (&$errno, &$errstr) { - // Match errstr from PHP's warning message. - // fopen(php://fd/3): Failed to open stream: Error duping file descriptor 3; possibly it doesn't exist: [9]: Bad file descriptor - \preg_match('/\[(\d+)\]: (.*)/', $error, $m); - $errno = isset($m[1]) ? (int) $m[1] : 0; - $errstr = isset($m[2]) ? $m[2] : $error; - }); - - $this->master = \fopen('php://fd/' . $fd, 'r+'); - - \restore_error_handler(); - - if (false === $this->master) { - throw new \RuntimeException( - 'Failed to listen on FD ' . $fd . ': ' . $errstr . SocketServer::errconst($errno), - $errno - ); - } - - $meta = \stream_get_meta_data($this->master); - if (!isset($meta['stream_type']) || $meta['stream_type'] !== 'tcp_socket') { - \fclose($this->master); - - $errno = \defined('SOCKET_ENOTSOCK') ? \SOCKET_ENOTSOCK : 88; - $errstr = \function_exists('socket_strerror') ? \socket_strerror($errno) : 'Not a socket'; - - throw new \RuntimeException( - 'Failed to listen on FD ' . $fd . ': ' . $errstr . ' (ENOTSOCK)', - $errno - ); - } - - // Socket should not have a peer address if this is a listening socket. - // Looks like this work-around is the closest we can get because PHP doesn't expose SO_ACCEPTCONN even with ext-sockets. - if (\stream_socket_get_name($this->master, true) !== false) { - \fclose($this->master); - - $errno = \defined('SOCKET_EISCONN') ? \SOCKET_EISCONN : 106; - $errstr = \function_exists('socket_strerror') ? \socket_strerror($errno) : 'Socket is connected'; - - throw new \RuntimeException( - 'Failed to listen on FD ' . $fd . ': ' . $errstr . ' (EISCONN)', - $errno - ); - } - - // Assume this is a Unix domain socket (UDS) when its listening address doesn't parse as a valid URL with a port. - // Looks like this work-around is the closest we can get because PHP doesn't expose SO_DOMAIN even with ext-sockets. - $this->unix = \parse_url($this->getAddress(), \PHP_URL_PORT) === false; - - \stream_set_blocking($this->master, false); - - $this->resume(); - } - - public function getAddress() - { - if (!\is_resource($this->master)) { - return null; - } - - $address = \stream_socket_get_name($this->master, false); - - if ($this->unix === true) { - return 'unix://' . $address; - } - - // check if this is an IPv6 address which includes multiple colons but no square brackets - $pos = \strrpos($address, ':'); - if ($pos !== false && \strpos($address, ':') < $pos && \substr($address, 0, 1) !== '[') { - $address = '[' . \substr($address, 0, $pos) . ']:' . \substr($address, $pos + 1); // @codeCoverageIgnore - } - - return 'tcp://' . $address; - } - - public function pause() - { - if (!$this->listening) { - return; - } - - $this->loop->removeReadStream($this->master); - $this->listening = false; - } - - public function resume() - { - if ($this->listening || !\is_resource($this->master)) { - return; - } - - $that = $this; - $this->loop->addReadStream($this->master, function ($master) use ($that) { - try { - $newSocket = SocketServer::accept($master); - } catch (\RuntimeException $e) { - $that->emit('error', array($e)); - return; - } - $that->handleConnection($newSocket); - }); - $this->listening = true; - } - - public function close() - { - if (!\is_resource($this->master)) { - return; - } - - $this->pause(); - \fclose($this->master); - $this->removeAllListeners(); - } - - /** @internal */ - public function handleConnection($socket) - { - $connection = new Connection($socket, $this->loop); - $connection->unix = $this->unix; - - $this->emit('connection', array($connection)); - } -} diff --git a/digital_doctor/vendor/react/socket/src/FixedUriConnector.php b/digital_doctor/vendor/react/socket/src/FixedUriConnector.php deleted file mode 100644 index f83241d..0000000 --- a/digital_doctor/vendor/react/socket/src/FixedUriConnector.php +++ /dev/null @@ -1,41 +0,0 @@ -connect('localhost:80'); - * ``` - */ -class FixedUriConnector implements ConnectorInterface -{ - private $uri; - private $connector; - - /** - * @param string $uri - * @param ConnectorInterface $connector - */ - public function __construct($uri, ConnectorInterface $connector) - { - $this->uri = $uri; - $this->connector = $connector; - } - - public function connect($_) - { - return $this->connector->connect($this->uri); - } -} diff --git a/digital_doctor/vendor/react/socket/src/HappyEyeBallsConnectionBuilder.php b/digital_doctor/vendor/react/socket/src/HappyEyeBallsConnectionBuilder.php deleted file mode 100644 index d4f05e8..0000000 --- a/digital_doctor/vendor/react/socket/src/HappyEyeBallsConnectionBuilder.php +++ /dev/null @@ -1,334 +0,0 @@ - false, - Message::TYPE_AAAA => false, - ); - public $resolverPromises = array(); - public $connectionPromises = array(); - public $connectQueue = array(); - public $nextAttemptTimer; - public $parts; - public $ipsCount = 0; - public $failureCount = 0; - public $resolve; - public $reject; - - public $lastErrorFamily; - public $lastError6; - public $lastError4; - - public function __construct(LoopInterface $loop, ConnectorInterface $connector, ResolverInterface $resolver, $uri, $host, $parts) - { - $this->loop = $loop; - $this->connector = $connector; - $this->resolver = $resolver; - $this->uri = $uri; - $this->host = $host; - $this->parts = $parts; - } - - public function connect() - { - $that = $this; - return new Promise\Promise(function ($resolve, $reject) use ($that) { - $lookupResolve = function ($type) use ($that, $resolve, $reject) { - return function (array $ips) use ($that, $type, $resolve, $reject) { - unset($that->resolverPromises[$type]); - $that->resolved[$type] = true; - - $that->mixIpsIntoConnectQueue($ips); - - // start next connection attempt if not already awaiting next - if ($that->nextAttemptTimer === null && $that->connectQueue) { - $that->check($resolve, $reject); - } - }; - }; - - $that->resolverPromises[Message::TYPE_AAAA] = $that->resolve(Message::TYPE_AAAA, $reject)->then($lookupResolve(Message::TYPE_AAAA)); - $that->resolverPromises[Message::TYPE_A] = $that->resolve(Message::TYPE_A, $reject)->then(function (array $ips) use ($that) { - // happy path: IPv6 has resolved already (or could not resolve), continue with IPv4 addresses - if ($that->resolved[Message::TYPE_AAAA] === true || !$ips) { - return $ips; - } - - // Otherwise delay processing IPv4 lookup until short timer passes or IPv6 resolves in the meantime - $deferred = new Promise\Deferred(function () use (&$ips) { - // discard all IPv4 addresses if cancelled - $ips = array(); - }); - $timer = $that->loop->addTimer($that::RESOLUTION_DELAY, function () use ($deferred, $ips) { - $deferred->resolve($ips); - }); - - $that->resolverPromises[Message::TYPE_AAAA]->then(function () use ($that, $timer, $deferred, &$ips) { - $that->loop->cancelTimer($timer); - $deferred->resolve($ips); - }); - - return $deferred->promise(); - })->then($lookupResolve(Message::TYPE_A)); - }, function ($_, $reject) use ($that) { - $reject(new \RuntimeException( - 'Connection to ' . $that->uri . ' cancelled' . (!$that->connectionPromises ? ' during DNS lookup' : '') . ' (ECONNABORTED)', - \defined('SOCKET_ECONNABORTED') ? \SOCKET_ECONNABORTED : 103 - )); - $_ = $reject = null; - - $that->cleanUp(); - }); - } - - /** - * @internal - * @param int $type DNS query type - * @param callable $reject - * @return \React\Promise\PromiseInterface Returns a promise that - * always resolves with a list of IP addresses on success or an empty - * list on error. - */ - public function resolve($type, $reject) - { - $that = $this; - return $that->resolver->resolveAll($that->host, $type)->then(null, function (\Exception $e) use ($type, $reject, $that) { - unset($that->resolverPromises[$type]); - $that->resolved[$type] = true; - - if ($type === Message::TYPE_A) { - $that->lastError4 = $e->getMessage(); - $that->lastErrorFamily = 4; - } else { - $that->lastError6 = $e->getMessage(); - $that->lastErrorFamily = 6; - } - - // cancel next attempt timer when there are no more IPs to connect to anymore - if ($that->nextAttemptTimer !== null && !$that->connectQueue) { - $that->loop->cancelTimer($that->nextAttemptTimer); - $that->nextAttemptTimer = null; - } - - if ($that->hasBeenResolved() && $that->ipsCount === 0) { - $reject(new \RuntimeException( - $that->error(), - 0, - $e - )); - } - - // Exception already handled above, so don't throw an unhandled rejection here - return array(); - }); - } - - /** - * @internal - */ - public function check($resolve, $reject) - { - $ip = \array_shift($this->connectQueue); - - // start connection attempt and remember array position to later unset again - $this->connectionPromises[] = $this->attemptConnection($ip); - \end($this->connectionPromises); - $index = \key($this->connectionPromises); - - $that = $this; - $that->connectionPromises[$index]->then(function ($connection) use ($that, $index, $resolve) { - unset($that->connectionPromises[$index]); - - $that->cleanUp(); - - $resolve($connection); - }, function (\Exception $e) use ($that, $index, $ip, $resolve, $reject) { - unset($that->connectionPromises[$index]); - - $that->failureCount++; - - $message = \preg_replace('/^(Connection to [^ ]+)[&?]hostname=[^ &]+/', '$1', $e->getMessage()); - if (\strpos($ip, ':') === false) { - $that->lastError4 = $message; - $that->lastErrorFamily = 4; - } else { - $that->lastError6 = $message; - $that->lastErrorFamily = 6; - } - - // start next connection attempt immediately on error - if ($that->connectQueue) { - if ($that->nextAttemptTimer !== null) { - $that->loop->cancelTimer($that->nextAttemptTimer); - $that->nextAttemptTimer = null; - } - - $that->check($resolve, $reject); - } - - if ($that->hasBeenResolved() === false) { - return; - } - - if ($that->ipsCount === $that->failureCount) { - $that->cleanUp(); - - $reject(new \RuntimeException( - $that->error(), - $e->getCode(), - $e - )); - } - }); - - // Allow next connection attempt in 100ms: https://tools.ietf.org/html/rfc8305#section-5 - // Only start timer when more IPs are queued or when DNS query is still pending (might add more IPs) - if ($this->nextAttemptTimer === null && (\count($this->connectQueue) > 0 || $this->resolved[Message::TYPE_A] === false || $this->resolved[Message::TYPE_AAAA] === false)) { - $this->nextAttemptTimer = $this->loop->addTimer(self::CONNECTION_ATTEMPT_DELAY, function () use ($that, $resolve, $reject) { - $that->nextAttemptTimer = null; - - if ($that->connectQueue) { - $that->check($resolve, $reject); - } - }); - } - } - - /** - * @internal - */ - public function attemptConnection($ip) - { - $uri = Connector::uri($this->parts, $this->host, $ip); - - return $this->connector->connect($uri); - } - - /** - * @internal - */ - public function cleanUp() - { - // clear list of outstanding IPs to avoid creating new connections - $this->connectQueue = array(); - - // cancel pending connection attempts - foreach ($this->connectionPromises as $connectionPromise) { - if ($connectionPromise instanceof PromiseInterface && \method_exists($connectionPromise, 'cancel')) { - $connectionPromise->cancel(); - } - } - - // cancel pending DNS resolution (cancel IPv4 first in case it is awaiting IPv6 resolution delay) - foreach (\array_reverse($this->resolverPromises) as $resolverPromise) { - if ($resolverPromise instanceof PromiseInterface && \method_exists($resolverPromise, 'cancel')) { - $resolverPromise->cancel(); - } - } - - if ($this->nextAttemptTimer instanceof TimerInterface) { - $this->loop->cancelTimer($this->nextAttemptTimer); - $this->nextAttemptTimer = null; - } - } - - /** - * @internal - */ - public function hasBeenResolved() - { - foreach ($this->resolved as $typeHasBeenResolved) { - if ($typeHasBeenResolved === false) { - return false; - } - } - - return true; - } - - /** - * Mixes an array of IP addresses into the connect queue in such a way they alternate when attempting to connect. - * The goal behind it is first attempt to connect to IPv6, then to IPv4, then to IPv6 again until one of those - * attempts succeeds. - * - * @link https://tools.ietf.org/html/rfc8305#section-4 - * - * @internal - */ - public function mixIpsIntoConnectQueue(array $ips) - { - \shuffle($ips); - $this->ipsCount += \count($ips); - $connectQueueStash = $this->connectQueue; - $this->connectQueue = array(); - while (\count($connectQueueStash) > 0 || \count($ips) > 0) { - if (\count($ips) > 0) { - $this->connectQueue[] = \array_shift($ips); - } - if (\count($connectQueueStash) > 0) { - $this->connectQueue[] = \array_shift($connectQueueStash); - } - } - } - - /** - * @internal - * @return string - */ - public function error() - { - if ($this->lastError4 === $this->lastError6) { - $message = $this->lastError6; - } elseif ($this->lastErrorFamily === 6) { - $message = 'Last error for IPv6: ' . $this->lastError6 . '. Previous error for IPv4: ' . $this->lastError4; - } else { - $message = 'Last error for IPv4: ' . $this->lastError4 . '. Previous error for IPv6: ' . $this->lastError6; - } - - if ($this->hasBeenResolved() && $this->ipsCount === 0) { - if ($this->lastError6 === $this->lastError4) { - $message = ' during DNS lookup: ' . $this->lastError6; - } else { - $message = ' during DNS lookup. ' . $message; - } - } else { - $message = ': ' . $message; - } - - return 'Connection to ' . $this->uri . ' failed' . $message; - } -} diff --git a/digital_doctor/vendor/react/socket/src/HappyEyeBallsConnector.php b/digital_doctor/vendor/react/socket/src/HappyEyeBallsConnector.php deleted file mode 100644 index 98b1d58..0000000 --- a/digital_doctor/vendor/react/socket/src/HappyEyeBallsConnector.php +++ /dev/null @@ -1,69 +0,0 @@ -loop = $loop ?: Loop::get(); - $this->connector = $connector; - $this->resolver = $resolver; - } - - public function connect($uri) - { - $original = $uri; - if (\strpos($uri, '://') === false) { - $uri = 'tcp://' . $uri; - $parts = \parse_url($uri); - if (isset($parts['scheme'])) { - unset($parts['scheme']); - } - } else { - $parts = \parse_url($uri); - } - - if (!$parts || !isset($parts['host'])) { - return Promise\reject(new \InvalidArgumentException( - 'Given URI "' . $original . '" is invalid (EINVAL)', - \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22) - )); - } - - $host = \trim($parts['host'], '[]'); - - // skip DNS lookup / URI manipulation if this URI already contains an IP - if (@\inet_pton($host) !== false) { - return $this->connector->connect($original); - } - - $builder = new HappyEyeBallsConnectionBuilder( - $this->loop, - $this->connector, - $this->resolver, - $uri, - $host, - $parts - ); - return $builder->connect(); - } -} diff --git a/digital_doctor/vendor/react/socket/src/LimitingServer.php b/digital_doctor/vendor/react/socket/src/LimitingServer.php deleted file mode 100644 index d19000b..0000000 --- a/digital_doctor/vendor/react/socket/src/LimitingServer.php +++ /dev/null @@ -1,203 +0,0 @@ -on('connection', function (React\Socket\ConnectionInterface $connection) { - * $connection->write('hello there!' . PHP_EOL); - * … - * }); - * ``` - * - * See also the `ServerInterface` for more details. - * - * @see ServerInterface - * @see ConnectionInterface - */ -class LimitingServer extends EventEmitter implements ServerInterface -{ - private $connections = array(); - private $server; - private $limit; - - private $pauseOnLimit = false; - private $autoPaused = false; - private $manuPaused = false; - - /** - * Instantiates a new LimitingServer. - * - * You have to pass a maximum number of open connections to ensure - * the server will automatically reject (close) connections once this limit - * is exceeded. In this case, it will emit an `error` event to inform about - * this and no `connection` event will be emitted. - * - * ```php - * $server = new React\Socket\LimitingServer($server, 100); - * $server->on('connection', function (React\Socket\ConnectionInterface $connection) { - * $connection->write('hello there!' . PHP_EOL); - * … - * }); - * ``` - * - * You MAY pass a `null` limit in order to put no limit on the number of - * open connections and keep accepting new connection until you run out of - * operating system resources (such as open file handles). This may be - * useful if you do not want to take care of applying a limit but still want - * to use the `getConnections()` method. - * - * You can optionally configure the server to pause accepting new - * connections once the connection limit is reached. In this case, it will - * pause the underlying server and no longer process any new connections at - * all, thus also no longer closing any excessive connections. - * The underlying operating system is responsible for keeping a backlog of - * pending connections until its limit is reached, at which point it will - * start rejecting further connections. - * Once the server is below the connection limit, it will continue consuming - * connections from the backlog and will process any outstanding data on - * each connection. - * This mode may be useful for some protocols that are designed to wait for - * a response message (such as HTTP), but may be less useful for other - * protocols that demand immediate responses (such as a "welcome" message in - * an interactive chat). - * - * ```php - * $server = new React\Socket\LimitingServer($server, 100, true); - * $server->on('connection', function (React\Socket\ConnectionInterface $connection) { - * $connection->write('hello there!' . PHP_EOL); - * … - * }); - * ``` - * - * @param ServerInterface $server - * @param int|null $connectionLimit - * @param bool $pauseOnLimit - */ - public function __construct(ServerInterface $server, $connectionLimit, $pauseOnLimit = false) - { - $this->server = $server; - $this->limit = $connectionLimit; - if ($connectionLimit !== null) { - $this->pauseOnLimit = $pauseOnLimit; - } - - $this->server->on('connection', array($this, 'handleConnection')); - $this->server->on('error', array($this, 'handleError')); - } - - /** - * Returns an array with all currently active connections - * - * ```php - * foreach ($server->getConnection() as $connection) { - * $connection->write('Hi!'); - * } - * ``` - * - * @return ConnectionInterface[] - */ - public function getConnections() - { - return $this->connections; - } - - public function getAddress() - { - return $this->server->getAddress(); - } - - public function pause() - { - if (!$this->manuPaused) { - $this->manuPaused = true; - - if (!$this->autoPaused) { - $this->server->pause(); - } - } - } - - public function resume() - { - if ($this->manuPaused) { - $this->manuPaused = false; - - if (!$this->autoPaused) { - $this->server->resume(); - } - } - } - - public function close() - { - $this->server->close(); - } - - /** @internal */ - public function handleConnection(ConnectionInterface $connection) - { - // close connection if limit exceeded - if ($this->limit !== null && \count($this->connections) >= $this->limit) { - $this->handleError(new \OverflowException('Connection closed because server reached connection limit')); - $connection->close(); - return; - } - - $this->connections[] = $connection; - $that = $this; - $connection->on('close', function () use ($that, $connection) { - $that->handleDisconnection($connection); - }); - - // pause accepting new connections if limit exceeded - if ($this->pauseOnLimit && !$this->autoPaused && \count($this->connections) >= $this->limit) { - $this->autoPaused = true; - - if (!$this->manuPaused) { - $this->server->pause(); - } - } - - $this->emit('connection', array($connection)); - } - - /** @internal */ - public function handleDisconnection(ConnectionInterface $connection) - { - unset($this->connections[\array_search($connection, $this->connections)]); - - // continue accepting new connection if below limit - if ($this->autoPaused && \count($this->connections) < $this->limit) { - $this->autoPaused = false; - - if (!$this->manuPaused) { - $this->server->resume(); - } - } - } - - /** @internal */ - public function handleError(\Exception $error) - { - $this->emit('error', array($error)); - } -} diff --git a/digital_doctor/vendor/react/socket/src/SecureConnector.php b/digital_doctor/vendor/react/socket/src/SecureConnector.php deleted file mode 100644 index 17c229d..0000000 --- a/digital_doctor/vendor/react/socket/src/SecureConnector.php +++ /dev/null @@ -1,123 +0,0 @@ -connector = $connector; - $this->streamEncryption = new StreamEncryption($loop ?: Loop::get(), false); - $this->context = $context; - } - - public function connect($uri) - { - if (!\function_exists('stream_socket_enable_crypto')) { - return Promise\reject(new \BadMethodCallException('Encryption not supported on your platform (HHVM < 3.8?)')); // @codeCoverageIgnore - } - - if (\strpos($uri, '://') === false) { - $uri = 'tls://' . $uri; - } - - $parts = \parse_url($uri); - if (!$parts || !isset($parts['scheme']) || $parts['scheme'] !== 'tls') { - return Promise\reject(new \InvalidArgumentException( - 'Given URI "' . $uri . '" is invalid (EINVAL)', - \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22) - )); - } - - $context = $this->context; - $encryption = $this->streamEncryption; - $connected = false; - /** @var \React\Promise\PromiseInterface $promise */ - $promise = $this->connector->connect( - \str_replace('tls://', '', $uri) - )->then(function (ConnectionInterface $connection) use ($context, $encryption, $uri, &$promise, &$connected) { - // (unencrypted) TCP/IP connection succeeded - $connected = true; - - if (!$connection instanceof Connection) { - $connection->close(); - throw new \UnexpectedValueException('Base connector does not use internal Connection class exposing stream resource'); - } - - // set required SSL/TLS context options - foreach ($context as $name => $value) { - \stream_context_set_option($connection->stream, 'ssl', $name, $value); - } - - // try to enable encryption - return $promise = $encryption->enable($connection)->then(null, function ($error) use ($connection, $uri) { - // establishing encryption failed => close invalid connection and return error - $connection->close(); - - throw new \RuntimeException( - 'Connection to ' . $uri . ' failed during TLS handshake: ' . $error->getMessage(), - $error->getCode() - ); - }); - }, function (\Exception $e) use ($uri) { - if ($e instanceof \RuntimeException) { - $message = \preg_replace('/^Connection to [^ ]+/', '', $e->getMessage()); - $e = new \RuntimeException( - 'Connection to ' . $uri . $message, - $e->getCode(), - $e - ); - - // avoid garbage references by replacing all closures in call stack. - // what a lovely piece of code! - $r = new \ReflectionProperty('Exception', 'trace'); - $r->setAccessible(true); - $trace = $r->getValue($e); - - // Exception trace arguments are not available on some PHP 7.4 installs - // @codeCoverageIgnoreStart - foreach ($trace as $ti => $one) { - if (isset($one['args'])) { - foreach ($one['args'] as $ai => $arg) { - if ($arg instanceof \Closure) { - $trace[$ti]['args'][$ai] = 'Object(' . \get_class($arg) . ')'; - } - } - } - } - // @codeCoverageIgnoreEnd - $r->setValue($e, $trace); - } - - throw $e; - }); - - return new \React\Promise\Promise( - function ($resolve, $reject) use ($promise) { - $promise->then($resolve, $reject); - }, - function ($_, $reject) use (&$promise, $uri, &$connected) { - if ($connected) { - $reject(new \RuntimeException( - 'Connection to ' . $uri . ' cancelled during TLS handshake (ECONNABORTED)', - \defined('SOCKET_ECONNABORTED') ? \SOCKET_ECONNABORTED : 103 - )); - } - - $promise->cancel(); - $promise = null; - } - ); - } -} diff --git a/digital_doctor/vendor/react/socket/src/SecureServer.php b/digital_doctor/vendor/react/socket/src/SecureServer.php deleted file mode 100644 index d0525c9..0000000 --- a/digital_doctor/vendor/react/socket/src/SecureServer.php +++ /dev/null @@ -1,206 +0,0 @@ -on('connection', function (React\Socket\ConnectionInterface $connection) { - * echo 'Secure connection from' . $connection->getRemoteAddress() . PHP_EOL; - * - * $connection->write('hello there!' . PHP_EOL); - * … - * }); - * ``` - * - * Whenever a client fails to perform a successful TLS handshake, it will emit an - * `error` event and then close the underlying TCP/IP connection: - * - * ```php - * $server->on('error', function (Exception $e) { - * echo 'Error' . $e->getMessage() . PHP_EOL; - * }); - * ``` - * - * See also the `ServerInterface` for more details. - * - * Note that the `SecureServer` class is a concrete implementation for TLS sockets. - * If you want to typehint in your higher-level protocol implementation, you SHOULD - * use the generic `ServerInterface` instead. - * - * @see ServerInterface - * @see ConnectionInterface - */ -final class SecureServer extends EventEmitter implements ServerInterface -{ - private $tcp; - private $encryption; - private $context; - - /** - * Creates a secure TLS server and starts waiting for incoming connections - * - * It does so by wrapping a `TcpServer` instance which waits for plaintext - * TCP/IP connections and then performs a TLS handshake for each connection. - * It thus requires valid [TLS context options], - * which in its most basic form may look something like this if you're using a - * PEM encoded certificate file: - * - * ```php - * $server = new React\Socket\TcpServer(8000); - * $server = new React\Socket\SecureServer($server, null, array( - * 'local_cert' => 'server.pem' - * )); - * ``` - * - * Note that the certificate file will not be loaded on instantiation but when an - * incoming connection initializes its TLS context. - * This implies that any invalid certificate file paths or contents will only cause - * an `error` event at a later time. - * - * If your private key is encrypted with a passphrase, you have to specify it - * like this: - * - * ```php - * $server = new React\Socket\TcpServer(8000); - * $server = new React\Socket\SecureServer($server, null, array( - * 'local_cert' => 'server.pem', - * 'passphrase' => 'secret' - * )); - * ``` - * - * Note that available [TLS context options], - * their defaults and effects of changing these may vary depending on your system - * and/or PHP version. - * Passing unknown context options has no effect. - * - * This class takes an optional `LoopInterface|null $loop` parameter that can be used to - * pass the event loop instance to use for this object. You can use a `null` value - * here in order to use the [default loop](https://github.com/reactphp/event-loop#loop). - * This value SHOULD NOT be given unless you're sure you want to explicitly use a - * given event loop instance. - * - * Advanced usage: Despite allowing any `ServerInterface` as first parameter, - * you SHOULD pass a `TcpServer` instance as first parameter, unless you - * know what you're doing. - * Internally, the `SecureServer` has to set the required TLS context options on - * the underlying stream resources. - * These resources are not exposed through any of the interfaces defined in this - * package, but only through the internal `Connection` class. - * The `TcpServer` class is guaranteed to emit connections that implement - * the `ConnectionInterface` and uses the internal `Connection` class in order to - * expose these underlying resources. - * If you use a custom `ServerInterface` and its `connection` event does not - * meet this requirement, the `SecureServer` will emit an `error` event and - * then close the underlying connection. - * - * @param ServerInterface|TcpServer $tcp - * @param ?LoopInterface $loop - * @param array $context - * @throws BadMethodCallException for legacy HHVM < 3.8 due to lack of support - * @see TcpServer - * @link https://www.php.net/manual/en/context.ssl.php for TLS context options - */ - public function __construct(ServerInterface $tcp, LoopInterface $loop = null, array $context = array()) - { - if (!\function_exists('stream_socket_enable_crypto')) { - throw new \BadMethodCallException('Encryption not supported on your platform (HHVM < 3.8?)'); // @codeCoverageIgnore - } - - // default to empty passphrase to suppress blocking passphrase prompt - $context += array( - 'passphrase' => '' - ); - - $this->tcp = $tcp; - $this->encryption = new StreamEncryption($loop ?: Loop::get()); - $this->context = $context; - - $that = $this; - $this->tcp->on('connection', function ($connection) use ($that) { - $that->handleConnection($connection); - }); - $this->tcp->on('error', function ($error) use ($that) { - $that->emit('error', array($error)); - }); - } - - public function getAddress() - { - $address = $this->tcp->getAddress(); - if ($address === null) { - return null; - } - - return \str_replace('tcp://' , 'tls://', $address); - } - - public function pause() - { - $this->tcp->pause(); - } - - public function resume() - { - $this->tcp->resume(); - } - - public function close() - { - return $this->tcp->close(); - } - - /** @internal */ - public function handleConnection(ConnectionInterface $connection) - { - if (!$connection instanceof Connection) { - $this->emit('error', array(new \UnexpectedValueException('Base server does not use internal Connection class exposing stream resource'))); - $connection->close(); - return; - } - - foreach ($this->context as $name => $value) { - \stream_context_set_option($connection->stream, 'ssl', $name, $value); - } - - // get remote address before starting TLS handshake in case connection closes during handshake - $remote = $connection->getRemoteAddress(); - $that = $this; - - $this->encryption->enable($connection)->then( - function ($conn) use ($that) { - $that->emit('connection', array($conn)); - }, - function ($error) use ($that, $connection, $remote) { - $error = new \RuntimeException( - 'Connection from ' . $remote . ' failed during TLS handshake: ' . $error->getMessage(), - $error->getCode() - ); - - $that->emit('error', array($error)); - $connection->close(); - } - ); - } -} diff --git a/digital_doctor/vendor/react/socket/src/Server.php b/digital_doctor/vendor/react/socket/src/Server.php deleted file mode 100644 index 7d4111e..0000000 --- a/digital_doctor/vendor/react/socket/src/Server.php +++ /dev/null @@ -1,114 +0,0 @@ - $context); - } - - // apply default options if not explicitly given - $context += array( - 'tcp' => array(), - 'tls' => array(), - 'unix' => array() - ); - - $scheme = 'tcp'; - $pos = \strpos($uri, '://'); - if ($pos !== false) { - $scheme = \substr($uri, 0, $pos); - } - - if ($scheme === 'unix') { - $server = new UnixServer($uri, $loop, $context['unix']); - } else { - $server = new TcpServer(str_replace('tls://', '', $uri), $loop, $context['tcp']); - - if ($scheme === 'tls') { - $server = new SecureServer($server, $loop, $context['tls']); - } - } - - $this->server = $server; - - $that = $this; - $server->on('connection', function (ConnectionInterface $conn) use ($that) { - $that->emit('connection', array($conn)); - }); - $server->on('error', function (Exception $error) use ($that) { - $that->emit('error', array($error)); - }); - } - - public function getAddress() - { - return $this->server->getAddress(); - } - - public function pause() - { - $this->server->pause(); - } - - public function resume() - { - $this->server->resume(); - } - - public function close() - { - $this->server->close(); - } -} diff --git a/digital_doctor/vendor/react/socket/src/ServerInterface.php b/digital_doctor/vendor/react/socket/src/ServerInterface.php deleted file mode 100644 index aa79fa1..0000000 --- a/digital_doctor/vendor/react/socket/src/ServerInterface.php +++ /dev/null @@ -1,151 +0,0 @@ -on('connection', function (React\Socket\ConnectionInterface $connection) { - * echo 'new connection' . PHP_EOL; - * }); - * ``` - * - * See also the `ConnectionInterface` for more details about handling the - * incoming connection. - * - * error event: - * The `error` event will be emitted whenever there's an error accepting a new - * connection from a client. - * - * ```php - * $socket->on('error', function (Exception $e) { - * echo 'error: ' . $e->getMessage() . PHP_EOL; - * }); - * ``` - * - * Note that this is not a fatal error event, i.e. the server keeps listening for - * new connections even after this event. - * - * @see ConnectionInterface - */ -interface ServerInterface extends EventEmitterInterface -{ - /** - * Returns the full address (URI) this server is currently listening on - * - * ```php - * $address = $socket->getAddress(); - * echo 'Server listening on ' . $address . PHP_EOL; - * ``` - * - * If the address can not be determined or is unknown at this time (such as - * after the socket has been closed), it MAY return a `NULL` value instead. - * - * Otherwise, it will return the full address (URI) as a string value, such - * as `tcp://127.0.0.1:8080`, `tcp://[::1]:80` or `tls://127.0.0.1:443`. - * Note that individual URI components are application specific and depend - * on the underlying transport protocol. - * - * If this is a TCP/IP based server and you only want the local port, you may - * use something like this: - * - * ```php - * $address = $socket->getAddress(); - * $port = parse_url($address, PHP_URL_PORT); - * echo 'Server listening on port ' . $port . PHP_EOL; - * ``` - * - * @return ?string the full listening address (URI) or NULL if it is unknown (not applicable to this server socket or already closed) - */ - public function getAddress(); - - /** - * Pauses accepting new incoming connections. - * - * Removes the socket resource from the EventLoop and thus stop accepting - * new connections. Note that the listening socket stays active and is not - * closed. - * - * This means that new incoming connections will stay pending in the - * operating system backlog until its configurable backlog is filled. - * Once the backlog is filled, the operating system may reject further - * incoming connections until the backlog is drained again by resuming - * to accept new connections. - * - * Once the server is paused, no futher `connection` events SHOULD - * be emitted. - * - * ```php - * $socket->pause(); - * - * $socket->on('connection', assertShouldNeverCalled()); - * ``` - * - * This method is advisory-only, though generally not recommended, the - * server MAY continue emitting `connection` events. - * - * Unless otherwise noted, a successfully opened server SHOULD NOT start - * in paused state. - * - * You can continue processing events by calling `resume()` again. - * - * Note that both methods can be called any number of times, in particular - * calling `pause()` more than once SHOULD NOT have any effect. - * Similarly, calling this after `close()` is a NO-OP. - * - * @see self::resume() - * @return void - */ - public function pause(); - - /** - * Resumes accepting new incoming connections. - * - * Re-attach the socket resource to the EventLoop after a previous `pause()`. - * - * ```php - * $socket->pause(); - * - * Loop::addTimer(1.0, function () use ($socket) { - * $socket->resume(); - * }); - * ``` - * - * Note that both methods can be called any number of times, in particular - * calling `resume()` without a prior `pause()` SHOULD NOT have any effect. - * Similarly, calling this after `close()` is a NO-OP. - * - * @see self::pause() - * @return void - */ - public function resume(); - - /** - * Shuts down this listening socket - * - * This will stop listening for new incoming connections on this socket. - * - * Calling this method more than once on the same instance is a NO-OP. - * - * @return void - */ - public function close(); -} diff --git a/digital_doctor/vendor/react/socket/src/SocketServer.php b/digital_doctor/vendor/react/socket/src/SocketServer.php deleted file mode 100644 index b78dc3a..0000000 --- a/digital_doctor/vendor/react/socket/src/SocketServer.php +++ /dev/null @@ -1,211 +0,0 @@ - array(), - 'tls' => array(), - 'unix' => array() - ); - - $scheme = 'tcp'; - $pos = \strpos($uri, '://'); - if ($pos !== false) { - $scheme = \substr($uri, 0, $pos); - } - - if ($scheme === 'unix') { - $server = new UnixServer($uri, $loop, $context['unix']); - } elseif ($scheme === 'php') { - $server = new FdServer($uri, $loop); - } else { - if (preg_match('#^(?:\w+://)?\d+$#', $uri)) { - throw new \InvalidArgumentException( - 'Invalid URI given (EINVAL)', - \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22) - ); - } - - $server = new TcpServer(str_replace('tls://', '', $uri), $loop, $context['tcp']); - - if ($scheme === 'tls') { - $server = new SecureServer($server, $loop, $context['tls']); - } - } - - $this->server = $server; - - $that = $this; - $server->on('connection', function (ConnectionInterface $conn) use ($that) { - $that->emit('connection', array($conn)); - }); - $server->on('error', function (\Exception $error) use ($that) { - $that->emit('error', array($error)); - }); - } - - public function getAddress() - { - return $this->server->getAddress(); - } - - public function pause() - { - $this->server->pause(); - } - - public function resume() - { - $this->server->resume(); - } - - public function close() - { - $this->server->close(); - } - - /** - * [internal] Internal helper method to accept new connection from given server socket - * - * @param resource $socket server socket to accept connection from - * @return resource new client socket if any - * @throws \RuntimeException if accepting fails - * @internal - */ - public static function accept($socket) - { - $errno = 0; - $errstr = ''; - \set_error_handler(function ($_, $error) use (&$errno, &$errstr) { - // Match errstr from PHP's warning message. - // stream_socket_accept(): accept failed: Connection timed out - $errstr = \preg_replace('#.*: #', '', $error); - $errno = SocketServer::errno($errstr); - }); - - $newSocket = \stream_socket_accept($socket, 0); - - \restore_error_handler(); - - if (false === $newSocket) { - throw new \RuntimeException( - 'Unable to accept new connection: ' . $errstr . self::errconst($errno), - $errno - ); - } - - return $newSocket; - } - - /** - * [Internal] Returns errno value for given errstr - * - * The errno and errstr values describes the type of error that has been - * encountered. This method tries to look up the given errstr and find a - * matching errno value which can be useful to provide more context to error - * messages. It goes through the list of known errno constants when either - * `ext-sockets`, `ext-posix` or `ext-pcntl` is available to find an errno - * matching the given errstr. - * - * @param string $errstr - * @return int errno value (e.g. value of `SOCKET_ECONNREFUSED`) or 0 if not found - * @internal - * @copyright Copyright (c) 2023 Christian Lück, taken from https://github.com/clue/errno with permission - * @codeCoverageIgnore - */ - public static function errno($errstr) - { - // PHP defines the required `strerror()` function through either `ext-sockets`, `ext-posix` or `ext-pcntl` - $strerror = \function_exists('socket_strerror') ? 'socket_strerror' : (\function_exists('posix_strerror') ? 'posix_strerror' : (\function_exists('pcntl_strerror') ? 'pcntl_strerror' : null)); - if ($strerror !== null) { - assert(\is_string($strerror) && \is_callable($strerror)); - - // PHP defines most useful errno constants like `ECONNREFUSED` through constants in `ext-sockets` like `SOCKET_ECONNREFUSED` - // PHP also defines a hand full of errno constants like `EMFILE` through constants in `ext-pcntl` like `PCNTL_EMFILE` - // go through list of all defined constants like `SOCKET_E*` and `PCNTL_E*` and see if they match the given `$errstr` - foreach (\get_defined_constants(false) as $name => $value) { - if (\is_int($value) && (\strpos($name, 'SOCKET_E') === 0 || \strpos($name, 'PCNTL_E') === 0) && $strerror($value) === $errstr) { - return $value; - } - } - - // if we reach this, no matching errno constant could be found (unlikely when `ext-sockets` is available) - // go through list of all possible errno values from 1 to `MAX_ERRNO` and see if they match the given `$errstr` - for ($errno = 1, $max = \defined('MAX_ERRNO') ? \MAX_ERRNO : 4095; $errno <= $max; ++$errno) { - if ($strerror($errno) === $errstr) { - return $errno; - } - } - } - - // if we reach this, no matching errno value could be found (unlikely when either `ext-sockets`, `ext-posix` or `ext-pcntl` is available) - return 0; - } - - /** - * [Internal] Returns errno constant name for given errno value - * - * The errno value describes the type of error that has been encountered. - * This method tries to look up the given errno value and find a matching - * errno constant name which can be useful to provide more context and more - * descriptive error messages. It goes through the list of known errno - * constants when either `ext-sockets` or `ext-pcntl` is available to find - * the matching errno constant name. - * - * Because this method is used to append more context to error messages, the - * constant name will be prefixed with a space and put between parenthesis - * when found. - * - * @param int $errno - * @return string e.g. ` (ECONNREFUSED)` or empty string if no matching const for the given errno could be found - * @internal - * @copyright Copyright (c) 2023 Christian Lück, taken from https://github.com/clue/errno with permission - * @codeCoverageIgnore - */ - public static function errconst($errno) - { - // PHP defines most useful errno constants like `ECONNREFUSED` through constants in `ext-sockets` like `SOCKET_ECONNREFUSED` - // PHP also defines a hand full of errno constants like `EMFILE` through constants in `ext-pcntl` like `PCNTL_EMFILE` - // go through list of all defined constants like `SOCKET_E*` and `PCNTL_E*` and see if they match the given `$errno` - foreach (\get_defined_constants(false) as $name => $value) { - if ($value === $errno && (\strpos($name, 'SOCKET_E') === 0 || \strpos($name, 'PCNTL_E') === 0)) { - return ' (' . \substr($name, \strpos($name, '_') + 1) . ')'; - } - } - - // if we reach this, no matching errno constant could be found (unlikely when `ext-sockets` is available) - return ''; - } -} diff --git a/digital_doctor/vendor/react/socket/src/StreamEncryption.php b/digital_doctor/vendor/react/socket/src/StreamEncryption.php deleted file mode 100644 index f91a359..0000000 --- a/digital_doctor/vendor/react/socket/src/StreamEncryption.php +++ /dev/null @@ -1,158 +0,0 @@ -loop = $loop; - $this->server = $server; - - // support TLSv1.0+ by default and exclude legacy SSLv2/SSLv3. - // As of PHP 7.2+ the main crypto method constant includes all TLS versions. - // As of PHP 5.6+ the crypto method is a bitmask, so we explicitly include all TLS versions. - // For legacy PHP < 5.6 the crypto method is a single value only and this constant includes all TLS versions. - // @link https://3v4l.org/9PSST - if ($server) { - $this->method = \STREAM_CRYPTO_METHOD_TLS_SERVER; - - if (\PHP_VERSION_ID < 70200 && \PHP_VERSION_ID >= 50600) { - $this->method |= \STREAM_CRYPTO_METHOD_TLSv1_0_SERVER | \STREAM_CRYPTO_METHOD_TLSv1_1_SERVER | \STREAM_CRYPTO_METHOD_TLSv1_2_SERVER; // @codeCoverageIgnore - } - } else { - $this->method = \STREAM_CRYPTO_METHOD_TLS_CLIENT; - - if (\PHP_VERSION_ID < 70200 && \PHP_VERSION_ID >= 50600) { - $this->method |= \STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT | \STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT | \STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT; // @codeCoverageIgnore - } - } - } - - /** - * @param Connection $stream - * @return \React\Promise\PromiseInterface - */ - public function enable(Connection $stream) - { - return $this->toggle($stream, true); - } - - /** - * @param Connection $stream - * @param bool $toggle - * @return \React\Promise\PromiseInterface - */ - public function toggle(Connection $stream, $toggle) - { - // pause actual stream instance to continue operation on raw stream socket - $stream->pause(); - - // TODO: add write() event to make sure we're not sending any excessive data - - // cancelling this leaves this stream in an inconsistent state… - $deferred = new Deferred(function () { - throw new \RuntimeException(); - }); - - // get actual stream socket from stream instance - $socket = $stream->stream; - - // get crypto method from context options or use global setting from constructor - $method = $this->method; - $context = \stream_context_get_options($socket); - if (isset($context['ssl']['crypto_method'])) { - $method = $context['ssl']['crypto_method']; - } - - $that = $this; - $toggleCrypto = function () use ($socket, $deferred, $toggle, $method, $that) { - $that->toggleCrypto($socket, $deferred, $toggle, $method); - }; - - $this->loop->addReadStream($socket, $toggleCrypto); - - if (!$this->server) { - $toggleCrypto(); - } - - $loop = $this->loop; - - return $deferred->promise()->then(function () use ($stream, $socket, $loop, $toggle) { - $loop->removeReadStream($socket); - - $stream->encryptionEnabled = $toggle; - $stream->resume(); - - return $stream; - }, function($error) use ($stream, $socket, $loop) { - $loop->removeReadStream($socket); - $stream->resume(); - throw $error; - }); - } - - /** - * @internal - * @param resource $socket - * @param Deferred $deferred - * @param bool $toggle - * @param int $method - * @return void - */ - public function toggleCrypto($socket, Deferred $deferred, $toggle, $method) - { - $error = null; - \set_error_handler(function ($_, $errstr) use (&$error) { - $error = \str_replace(array("\r", "\n"), ' ', $errstr); - - // remove useless function name from error message - if (($pos = \strpos($error, "): ")) !== false) { - $error = \substr($error, $pos + 3); - } - }); - - $result = \stream_socket_enable_crypto($socket, $toggle, $method); - - \restore_error_handler(); - - if (true === $result) { - $deferred->resolve(null); - } else if (false === $result) { - // overwrite callback arguments for PHP7+ only, so they do not show - // up in the Exception trace and do not cause a possible cyclic reference. - $d = $deferred; - $deferred = null; - - if (\feof($socket) || $error === null) { - // EOF or failed without error => connection closed during handshake - $d->reject(new \UnexpectedValueException( - 'Connection lost during TLS handshake (ECONNRESET)', - \defined('SOCKET_ECONNRESET') ? \SOCKET_ECONNRESET : 104 - )); - } else { - // handshake failed with error message - $d->reject(new \UnexpectedValueException( - $error - )); - } - } else { - // need more data, will retry - } - } -} diff --git a/digital_doctor/vendor/react/socket/src/TcpConnector.php b/digital_doctor/vendor/react/socket/src/TcpConnector.php deleted file mode 100644 index 8cfc7bf..0000000 --- a/digital_doctor/vendor/react/socket/src/TcpConnector.php +++ /dev/null @@ -1,165 +0,0 @@ -loop = $loop ?: Loop::get(); - $this->context = $context; - } - - public function connect($uri) - { - if (\strpos($uri, '://') === false) { - $uri = 'tcp://' . $uri; - } - - $parts = \parse_url($uri); - if (!$parts || !isset($parts['scheme'], $parts['host'], $parts['port']) || $parts['scheme'] !== 'tcp') { - return Promise\reject(new \InvalidArgumentException( - 'Given URI "' . $uri . '" is invalid (EINVAL)', - \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22) - )); - } - - $ip = \trim($parts['host'], '[]'); - if (@\inet_pton($ip) === false) { - return Promise\reject(new \InvalidArgumentException( - 'Given URI "' . $uri . '" does not contain a valid host IP (EINVAL)', - \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22) - )); - } - - // use context given in constructor - $context = array( - 'socket' => $this->context - ); - - // parse arguments from query component of URI - $args = array(); - if (isset($parts['query'])) { - \parse_str($parts['query'], $args); - } - - // If an original hostname has been given, use this for TLS setup. - // This can happen due to layers of nested connectors, such as a - // DnsConnector reporting its original hostname. - // These context options are here in case TLS is enabled later on this stream. - // If TLS is not enabled later, this doesn't hurt either. - if (isset($args['hostname'])) { - $context['ssl'] = array( - 'SNI_enabled' => true, - 'peer_name' => $args['hostname'] - ); - - // Legacy PHP < 5.6 ignores peer_name and requires legacy context options instead. - // The SNI_server_name context option has to be set here during construction, - // as legacy PHP ignores any values set later. - // @codeCoverageIgnoreStart - if (\PHP_VERSION_ID < 50600) { - $context['ssl'] += array( - 'SNI_server_name' => $args['hostname'], - 'CN_match' => $args['hostname'] - ); - } - // @codeCoverageIgnoreEnd - } - - // latest versions of PHP no longer accept any other URI components and - // HHVM fails to parse URIs with a query but no path, so let's simplify our URI here - $remote = 'tcp://' . $parts['host'] . ':' . $parts['port']; - - $stream = @\stream_socket_client( - $remote, - $errno, - $errstr, - 0, - \STREAM_CLIENT_CONNECT | \STREAM_CLIENT_ASYNC_CONNECT, - \stream_context_create($context) - ); - - if (false === $stream) { - return Promise\reject(new \RuntimeException( - 'Connection to ' . $uri . ' failed: ' . $errstr . SocketServer::errconst($errno), - $errno - )); - } - - // wait for connection - $loop = $this->loop; - return new Promise\Promise(function ($resolve, $reject) use ($loop, $stream, $uri) { - $loop->addWriteStream($stream, function ($stream) use ($loop, $resolve, $reject, $uri) { - $loop->removeWriteStream($stream); - - // The following hack looks like the only way to - // detect connection refused errors with PHP's stream sockets. - if (false === \stream_socket_get_name($stream, true)) { - // If we reach this point, we know the connection is dead, but we don't know the underlying error condition. - // @codeCoverageIgnoreStart - if (\function_exists('socket_import_stream')) { - // actual socket errno and errstr can be retrieved with ext-sockets on PHP 5.4+ - $socket = \socket_import_stream($stream); - $errno = \socket_get_option($socket, \SOL_SOCKET, \SO_ERROR); - $errstr = \socket_strerror($errno); - } elseif (\PHP_OS === 'Linux') { - // Linux reports socket errno and errstr again when trying to write to the dead socket. - // Suppress error reporting to get error message below and close dead socket before rejecting. - // This is only known to work on Linux, Mac and Windows are known to not support this. - $errno = 0; - $errstr = ''; - \set_error_handler(function ($_, $error) use (&$errno, &$errstr) { - // Match errstr from PHP's warning message. - // fwrite(): send of 1 bytes failed with errno=111 Connection refused - \preg_match('/errno=(\d+) (.+)/', $error, $m); - $errno = isset($m[1]) ? (int) $m[1] : 0; - $errstr = isset($m[2]) ? $m[2] : $error; - }); - - \fwrite($stream, \PHP_EOL); - - \restore_error_handler(); - } else { - // Not on Linux and ext-sockets not available? Too bad. - $errno = \defined('SOCKET_ECONNREFUSED') ? \SOCKET_ECONNREFUSED : 111; - $errstr = 'Connection refused?'; - } - // @codeCoverageIgnoreEnd - - \fclose($stream); - $reject(new \RuntimeException( - 'Connection to ' . $uri . ' failed: ' . $errstr . SocketServer::errconst($errno), - $errno - )); - } else { - $resolve(new Connection($stream, $loop)); - } - }); - }, function () use ($loop, $stream, $uri) { - $loop->removeWriteStream($stream); - \fclose($stream); - - // @codeCoverageIgnoreStart - // legacy PHP 5.3 sometimes requires a second close call (see tests) - if (\PHP_VERSION_ID < 50400 && \is_resource($stream)) { - \fclose($stream); - } - // @codeCoverageIgnoreEnd - - throw new \RuntimeException( - 'Connection to ' . $uri . ' cancelled during TCP/IP handshake (ECONNABORTED)', - \defined('SOCKET_ECONNABORTED') ? \SOCKET_ECONNABORTED : 103 - ); - }); - } -} diff --git a/digital_doctor/vendor/react/socket/src/TcpServer.php b/digital_doctor/vendor/react/socket/src/TcpServer.php deleted file mode 100644 index 235761d..0000000 --- a/digital_doctor/vendor/react/socket/src/TcpServer.php +++ /dev/null @@ -1,258 +0,0 @@ -on('connection', function (React\Socket\ConnectionInterface $connection) { - * echo 'Plaintext connection from ' . $connection->getRemoteAddress() . PHP_EOL; - * $connection->write('hello there!' . PHP_EOL); - * … - * }); - * ``` - * - * See also the `ServerInterface` for more details. - * - * @see ServerInterface - * @see ConnectionInterface - */ -final class TcpServer extends EventEmitter implements ServerInterface -{ - private $master; - private $loop; - private $listening = false; - - /** - * Creates a plaintext TCP/IP socket server and starts listening on the given address - * - * This starts accepting new incoming connections on the given address. - * See also the `connection event` documented in the `ServerInterface` - * for more details. - * - * ```php - * $server = new React\Socket\TcpServer(8080); - * ``` - * - * As above, the `$uri` parameter can consist of only a port, in which case the - * server will default to listening on the localhost address `127.0.0.1`, - * which means it will not be reachable from outside of this system. - * - * In order to use a random port assignment, you can use the port `0`: - * - * ```php - * $server = new React\Socket\TcpServer(0); - * $address = $server->getAddress(); - * ``` - * - * In order to change the host the socket is listening on, you can provide an IP - * address through the first parameter provided to the constructor, optionally - * preceded by the `tcp://` scheme: - * - * ```php - * $server = new React\Socket\TcpServer('192.168.0.1:8080'); - * ``` - * - * If you want to listen on an IPv6 address, you MUST enclose the host in square - * brackets: - * - * ```php - * $server = new React\Socket\TcpServer('[::1]:8080'); - * ``` - * - * If the given URI is invalid, does not contain a port, any other scheme or if it - * contains a hostname, it will throw an `InvalidArgumentException`: - * - * ```php - * // throws InvalidArgumentException due to missing port - * $server = new React\Socket\TcpServer('127.0.0.1'); - * ``` - * - * If the given URI appears to be valid, but listening on it fails (such as if port - * is already in use or port below 1024 may require root access etc.), it will - * throw a `RuntimeException`: - * - * ```php - * $first = new React\Socket\TcpServer(8080); - * - * // throws RuntimeException because port is already in use - * $second = new React\Socket\TcpServer(8080); - * ``` - * - * Note that these error conditions may vary depending on your system and/or - * configuration. - * See the exception message and code for more details about the actual error - * condition. - * - * This class takes an optional `LoopInterface|null $loop` parameter that can be used to - * pass the event loop instance to use for this object. You can use a `null` value - * here in order to use the [default loop](https://github.com/reactphp/event-loop#loop). - * This value SHOULD NOT be given unless you're sure you want to explicitly use a - * given event loop instance. - * - * Optionally, you can specify [socket context options](https://www.php.net/manual/en/context.socket.php) - * for the underlying stream socket resource like this: - * - * ```php - * $server = new React\Socket\TcpServer('[::1]:8080', null, array( - * 'backlog' => 200, - * 'so_reuseport' => true, - * 'ipv6_v6only' => true - * )); - * ``` - * - * Note that available [socket context options](https://www.php.net/manual/en/context.socket.php), - * their defaults and effects of changing these may vary depending on your system - * and/or PHP version. - * Passing unknown context options has no effect. - * The `backlog` context option defaults to `511` unless given explicitly. - * - * @param string|int $uri - * @param ?LoopInterface $loop - * @param array $context - * @throws InvalidArgumentException if the listening address is invalid - * @throws RuntimeException if listening on this address fails (already in use etc.) - */ - public function __construct($uri, LoopInterface $loop = null, array $context = array()) - { - $this->loop = $loop ?: Loop::get(); - - // a single port has been given => assume localhost - if ((string)(int)$uri === (string)$uri) { - $uri = '127.0.0.1:' . $uri; - } - - // assume default scheme if none has been given - if (\strpos($uri, '://') === false) { - $uri = 'tcp://' . $uri; - } - - // parse_url() does not accept null ports (random port assignment) => manually remove - if (\substr($uri, -2) === ':0') { - $parts = \parse_url(\substr($uri, 0, -2)); - if ($parts) { - $parts['port'] = 0; - } - } else { - $parts = \parse_url($uri); - } - - // ensure URI contains TCP scheme, host and port - if (!$parts || !isset($parts['scheme'], $parts['host'], $parts['port']) || $parts['scheme'] !== 'tcp') { - throw new \InvalidArgumentException( - 'Invalid URI "' . $uri . '" given (EINVAL)', - \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22) - ); - } - - if (@\inet_pton(\trim($parts['host'], '[]')) === false) { - throw new \InvalidArgumentException( - 'Given URI "' . $uri . '" does not contain a valid host IP (EINVAL)', - \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22) - ); - } - - $this->master = @\stream_socket_server( - $uri, - $errno, - $errstr, - \STREAM_SERVER_BIND | \STREAM_SERVER_LISTEN, - \stream_context_create(array('socket' => $context + array('backlog' => 511))) - ); - if (false === $this->master) { - if ($errno === 0) { - // PHP does not seem to report errno, so match errno from errstr - // @link https://3v4l.org/3qOBl - $errno = SocketServer::errno($errstr); - } - - throw new \RuntimeException( - 'Failed to listen on "' . $uri . '": ' . $errstr . SocketServer::errconst($errno), - $errno - ); - } - \stream_set_blocking($this->master, false); - - $this->resume(); - } - - public function getAddress() - { - if (!\is_resource($this->master)) { - return null; - } - - $address = \stream_socket_get_name($this->master, false); - - // check if this is an IPv6 address which includes multiple colons but no square brackets - $pos = \strrpos($address, ':'); - if ($pos !== false && \strpos($address, ':') < $pos && \substr($address, 0, 1) !== '[') { - $address = '[' . \substr($address, 0, $pos) . ']:' . \substr($address, $pos + 1); // @codeCoverageIgnore - } - - return 'tcp://' . $address; - } - - public function pause() - { - if (!$this->listening) { - return; - } - - $this->loop->removeReadStream($this->master); - $this->listening = false; - } - - public function resume() - { - if ($this->listening || !\is_resource($this->master)) { - return; - } - - $that = $this; - $this->loop->addReadStream($this->master, function ($master) use ($that) { - try { - $newSocket = SocketServer::accept($master); - } catch (\RuntimeException $e) { - $that->emit('error', array($e)); - return; - } - $that->handleConnection($newSocket); - }); - $this->listening = true; - } - - public function close() - { - if (!\is_resource($this->master)) { - return; - } - - $this->pause(); - \fclose($this->master); - $this->removeAllListeners(); - } - - /** @internal */ - public function handleConnection($socket) - { - $this->emit('connection', array( - new Connection($socket, $this->loop) - )); - } -} diff --git a/digital_doctor/vendor/react/socket/src/TimeoutConnector.php b/digital_doctor/vendor/react/socket/src/TimeoutConnector.php deleted file mode 100644 index a20ea5a..0000000 --- a/digital_doctor/vendor/react/socket/src/TimeoutConnector.php +++ /dev/null @@ -1,70 +0,0 @@ -connector = $connector; - $this->timeout = $timeout; - $this->loop = $loop ?: Loop::get(); - } - - public function connect($uri) - { - $promise = $this->connector->connect($uri); - - $loop = $this->loop; - $time = $this->timeout; - return new Promise(function ($resolve, $reject) use ($loop, $time, $promise, $uri) { - $timer = null; - $promise = $promise->then(function ($v) use (&$timer, $loop, $resolve) { - if ($timer) { - $loop->cancelTimer($timer); - } - $timer = false; - $resolve($v); - }, function ($v) use (&$timer, $loop, $reject) { - if ($timer) { - $loop->cancelTimer($timer); - } - $timer = false; - $reject($v); - }); - - // promise already resolved => no need to start timer - if ($timer === false) { - return; - } - - // start timeout timer which will cancel the pending promise - $timer = $loop->addTimer($time, function () use ($time, &$promise, $reject, $uri) { - $reject(new \RuntimeException( - 'Connection to ' . $uri . ' timed out after ' . $time . ' seconds (ETIMEDOUT)', - \defined('SOCKET_ETIMEDOUT') ? \SOCKET_ETIMEDOUT : 110 - )); - - // Cancel pending connection to clean up any underlying resources and references. - // Avoid garbage references in call stack by passing pending promise by reference. - assert(\method_exists($promise, 'cancel')); - $promise->cancel(); - $promise = null; - }); - }, function () use (&$promise) { - // Cancelling this promise will cancel the pending connection, thus triggering the rejection logic above. - // Avoid garbage references in call stack by passing pending promise by reference. - assert(\method_exists($promise, 'cancel')); - $promise->cancel(); - $promise = null; - }); - } -} diff --git a/digital_doctor/vendor/react/socket/src/UnixConnector.php b/digital_doctor/vendor/react/socket/src/UnixConnector.php deleted file mode 100644 index 627d60f..0000000 --- a/digital_doctor/vendor/react/socket/src/UnixConnector.php +++ /dev/null @@ -1,51 +0,0 @@ -loop = $loop ?: Loop::get(); - } - - public function connect($path) - { - if (\strpos($path, '://') === false) { - $path = 'unix://' . $path; - } elseif (\substr($path, 0, 7) !== 'unix://') { - return Promise\reject(new \InvalidArgumentException( - 'Given URI "' . $path . '" is invalid (EINVAL)', - \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22) - )); - } - - $resource = @\stream_socket_client($path, $errno, $errstr, 1.0); - - if (!$resource) { - return Promise\reject(new \RuntimeException( - 'Unable to connect to unix domain socket "' . $path . '": ' . $errstr . SocketServer::errconst($errno), - $errno - )); - } - - $connection = new Connection($resource, $this->loop); - $connection->unix = true; - - return Promise\resolve($connection); - } -} diff --git a/digital_doctor/vendor/react/socket/src/UnixServer.php b/digital_doctor/vendor/react/socket/src/UnixServer.php deleted file mode 100644 index cc46968..0000000 --- a/digital_doctor/vendor/react/socket/src/UnixServer.php +++ /dev/null @@ -1,158 +0,0 @@ -loop = $loop ?: Loop::get(); - - if (\strpos($path, '://') === false) { - $path = 'unix://' . $path; - } elseif (\substr($path, 0, 7) !== 'unix://') { - throw new \InvalidArgumentException( - 'Given URI "' . $path . '" is invalid (EINVAL)', - \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22) - ); - } - - $errno = 0; - $errstr = ''; - \set_error_handler(function ($_, $error) use (&$errno, &$errstr) { - // PHP does not seem to report errno/errstr for Unix domain sockets (UDS) right now. - // This only applies to UDS server sockets, see also https://3v4l.org/NAhpr. - // Parse PHP warning message containing unknown error, HHVM reports proper info at least. - if (\preg_match('/\(([^\)]+)\)|\[(\d+)\]: (.*)/', $error, $match)) { - $errstr = isset($match[3]) ? $match['3'] : $match[1]; - $errno = isset($match[2]) ? (int)$match[2] : 0; - } - }); - - $this->master = \stream_socket_server( - $path, - $errno, - $errstr, - \STREAM_SERVER_BIND | \STREAM_SERVER_LISTEN, - \stream_context_create(array('socket' => $context)) - ); - - \restore_error_handler(); - - if (false === $this->master) { - throw new \RuntimeException( - 'Failed to listen on Unix domain socket "' . $path . '": ' . $errstr . SocketServer::errconst($errno), - $errno - ); - } - \stream_set_blocking($this->master, 0); - - $this->resume(); - } - - public function getAddress() - { - if (!\is_resource($this->master)) { - return null; - } - - return 'unix://' . \stream_socket_get_name($this->master, false); - } - - public function pause() - { - if (!$this->listening) { - return; - } - - $this->loop->removeReadStream($this->master); - $this->listening = false; - } - - public function resume() - { - if ($this->listening || !is_resource($this->master)) { - return; - } - - $that = $this; - $this->loop->addReadStream($this->master, function ($master) use ($that) { - try { - $newSocket = SocketServer::accept($master); - } catch (\RuntimeException $e) { - $that->emit('error', array($e)); - return; - } - $that->handleConnection($newSocket); - }); - $this->listening = true; - } - - public function close() - { - if (!\is_resource($this->master)) { - return; - } - - $this->pause(); - \fclose($this->master); - $this->removeAllListeners(); - } - - /** @internal */ - public function handleConnection($socket) - { - $connection = new Connection($socket, $this->loop); - $connection->unix = true; - - $this->emit('connection', array( - $connection - )); - } -} diff --git a/digital_doctor/vendor/react/stream/CHANGELOG.md b/digital_doctor/vendor/react/stream/CHANGELOG.md deleted file mode 100644 index 639db65..0000000 --- a/digital_doctor/vendor/react/stream/CHANGELOG.md +++ /dev/null @@ -1,460 +0,0 @@ -# Changelog - -## 1.4.0 (2024-06-11) - -* Feature: Improve PHP 8.4+ support by avoiding implicitly nullable type declarations. - (#179 by @clue) - -* Feature: Full PHP 8.3 compatibility. - (#172 by @clue) - -* Fix: Fix `drain` event of `ThroughStream` to handle potential race condition. - (#171 by @clue) - -## 1.3.0 (2023-06-16) - -* Feature: Full PHP 8.1 and PHP 8.2 compatibility. - (#160 by @SimonFrings, #165 by @clue and #169 by @WyriHaximus) - -* Feature: Avoid unneeded syscall when creating non-blocking `DuplexResourceStream`. - (#164 by @clue) - -* Minor documentation improvements. - (#161 by @mrsimonbennett, #162 by @SimonFrings and #166 by @nhedger) - -* Improve test suite and project setup and report failed assertions. - (#168 and #170 by @clue and #163 by @SimonFrings) - -## 1.2.0 (2021-07-11) - -A major new feature release, see [**release announcement**](https://clue.engineering/2021/announcing-reactphp-default-loop). - -* Feature: Simplify usage by supporting new [default loop](https://reactphp.org/event-loop/#loop). - (#159 by @clue) - - ```php - // old (still supported) - $stream = new ReadableResourceStream($resource, $loop); - $stream = new WritabeResourceStream($resource, $loop); - $stream = new DuplexResourceStream($resource, $loop); - - // new (using default loop) - $stream = new ReadableResourceStream($resource); - $stream = new WritabeResourceStream($resource); - $stream = new DuplexResourceStream($resource); - ``` - -* Improve test suite, use GitHub actions for continuous integration (CI), - update PHPUnit config, run tests on PHP 8 and add full core team to the license. - (#153, #156 and #157 by @SimonFrings and #154 by @WyriHaximus) - -## 1.1.1 (2020-05-04) - -* Fix: Fix faulty write buffer behavior when sending large data chunks over TLS (Mac OS X only). - (#150 by @clue) - -* Minor code style improvements to fix phpstan analysis warnings and - add `.gitattributes` to exclude dev files from exports. - (#140 by @flow-control and #144 by @reedy) - -* Improve test suite to run tests on PHP 7.4 and simplify test matrix. - (#147 by @clue) - -## 1.1.0 (2019-01-01) - -* Improvement: Increase performance by optimizing global function and constant look ups. - (#137 by @WyriHaximus) - -* Travis: Test against PHP 7.3. - (#138 by @WyriHaximus) - -* Fix: Ignore empty reads. - (#139 by @WyriHaximus) - -## 1.0.0 (2018-07-11) - -* First stable LTS release, now following [SemVer](https://semver.org/). - We'd like to emphasize that this component is production ready and battle-tested. - We plan to support all long-term support (LTS) releases for at least 24 months, - so you have a rock-solid foundation to build on top of. - -> Contains no other changes, so it's actually fully compatible with the v0.7.7 release. - -## 0.7.7 (2018-01-19) - -* Improve test suite by fixing forward compatibility with upcoming EventLoop - releases, avoid risky tests and add test group to skip integration tests - relying on internet connection and apply appropriate test timeouts. - (#128, #131 and #132 by @clue) - -## 0.7.6 (2017-12-21) - -* Fix: Work around reading from unbuffered pipe stream in legacy PHP < 5.4.28 and PHP < 5.5.12 - (#126 by @clue) - -* Improve test suite by simplifying test bootstrapping logic via Composer and - test against PHP 7.2 - (#127 by @clue and #124 by @carusogabriel) - -## 0.7.5 (2017-11-20) - -* Fix: Igore excessive `fopen()` mode flags for `WritableResourceStream` - (#119 by @clue) - -* Fix: Fix forward compatibility with upcoming EventLoop releases - (#121 by @clue) - -* Restructure examples to ease getting started - (#123 by @clue) - -* Improve test suite by adding forward compatibility with PHPUnit 6 and - ignore Mac OS X test failures for now until Travis tests work again - (#122 by @gabriel-caruso and #120 by @clue) - -## 0.7.4 (2017-10-11) - -* Fix: Remove event listeners from `CompositeStream` once closed and - remove undocumented left-over `close` event argument - (#116 by @clue) - -* Minor documentation improvements: Fix wrong class name in example, - fix typos in README and - fix forward compatibility with upcoming EventLoop releases in example - (#113 by @docteurklein and #114 and #115 by @clue) - -* Improve test suite by running against Mac OS X on Travis - (#112 by @clue) - -## 0.7.3 (2017-08-05) - -* Improvement: Support Événement 3.0 a long side 2.0 and 1.0 - (#108 by @WyriHaximus) - -* Readme: Corrected loop initialization in usage example - (#109 by @pulyavin) - -* Travis: Lock linux distribution preventing future builds from breaking - (#110 by @clue) - -## 0.7.2 (2017-06-15) - -* Bug fix: WritableResourceStream: Close the underlying stream when closing the stream. - (#107 by @WyriHaximus) - -## 0.7.1 (2017-05-20) - -* Feature: Add optional `$writeChunkSize` parameter to limit maximum number of - bytes to write at once. - (#105 by @clue) - - ```php - $stream = new WritableResourceStream(STDOUT, $loop, null, 8192); - ``` - -* Ignore HHVM test failures for now until Travis tests work again - (#106 by @clue) - -## 0.7.0 (2017-05-04) - -* Removed / BC break: Remove deprecated and unneeded functionality - (#45, #87, #90, #91 and #93 by @clue) - - * Remove deprecated `Stream` class, use `DuplexResourceStream` instead - (#87 by @clue) - - * Remove public `$buffer` property, use new constructor parameters instead - (#91 by @clue) - - * Remove public `$stream` property from all resource streams - (#90 by @clue) - - * Remove undocumented and now unused `ReadableStream` and `WritableStream` - (#93 by @clue) - - * Remove `BufferedSink` - (#45 by @clue) - -* Feature / BC break: Simplify `ThroughStream` by using data callback instead of - inheritance. It is now a direct implementation of `DuplexStreamInterface`. - (#88 and #89 by @clue) - - ```php - $through = new ThroughStream(function ($data) { - return json_encode($data) . PHP_EOL; - }); - $through->on('data', $this->expectCallableOnceWith("[2, true]\n")); - - $through->write(array(2, true)); - ``` - -* Feature / BC break: The `CompositeStream` starts closed if either side is - already closed and forwards pause to pipe source on first write attempt. - (#96 and #103 by @clue) - - If either side of the composite stream closes, it will also close the other - side. We now also ensure that if either side is already closed during - instantiation, it will also close the other side. - -* BC break: Mark all classes as `final` and - mark internal API as `private` to discourage inheritance - (#95 and #99 by @clue) - -* Feature / BC break: Only emit `error` event for fatal errors - (#92 by @clue) - - > The `error` event was previously also allowed to be emitted for non-fatal - errors, but our implementations actually only ever emitted this as a fatal - error and then closed the stream. - -* Feature: Explicitly allow custom events and exclude any semantics - (#97 by @clue) - -* Strict definition for event callback functions - (#101 by @clue) - -* Support legacy PHP 5.3 through PHP 7.1 and HHVM and improve usage documentation - (#100 and #102 by @clue) - -* Actually require all dependencies so this is self-contained and improve - forward compatibility with EventLoop v1.0 and v0.5 - (#94 and #98 by @clue) - -## 0.6.0 (2017-03-26) - -* Feature / Fix / BC break: Add `DuplexResourceStream` and deprecate `Stream` - (#85 by @clue) - - ```php - // old (does still work for BC reasons) - $stream = new Stream($connection, $loop); - - // new - $stream = new DuplexResourceStream($connection, $loop); - ``` - - Note that the `DuplexResourceStream` now rejects read-only or write-only - streams, so this may affect BC. If you want a read-only or write-only - resource, use `ReadableResourceStream` or `WritableResourceStream` instead of - `DuplexResourceStream`. - - > BC note: This class was previously called `Stream`. The `Stream` class still - exists for BC reasons and will be removed in future versions of this package. - -* Feature / BC break: Add `WritableResourceStream` (previously called `Buffer`) - (#84 by @clue) - - ```php - // old - $stream = new Buffer(STDOUT, $loop); - - // new - $stream = new WritableResourceStream(STDOUT, $loop); - ``` - -* Feature: Add `ReadableResourceStream` - (#83 by @clue) - - ```php - $stream = new ReadableResourceStream(STDIN, $loop); - ``` - -* Fix / BC Break: Enforce using non-blocking I/O - (#46 by @clue) - - > BC note: This is known to affect process pipes on Windows which do not - support non-blocking I/O and could thus block the whole EventLoop previously. - -* Feature / Fix / BC break: Consistent semantics for - `DuplexStreamInterface::end()` to ensure it SHOULD also end readable side - (#86 by @clue) - -* Fix: Do not use unbuffered reads on pipe streams for legacy PHP < 5.4 - (#80 by @clue) - -## 0.5.0 (2017-03-08) - -* Feature / BC break: Consistent `end` event semantics (EOF) - (#70 by @clue) - - The `end` event will now only be emitted for a *successful* end, not if the - stream closes due to an unrecoverable `error` event or if you call `close()` - explicitly. - If you want to detect when the stream closes (terminates), use the `close` - event instead. - -* BC break: Remove custom (undocumented) `full-drain` event from `Buffer` - (#63 and #68 by @clue) - - > The `full-drain` event was undocumented and mostly used internally. - Relying on this event has attracted some low-quality code in the past, so - we've removed this from the public API in order to work out a better - solution instead. - If you want to detect when the buffer finishes flushing data to the stream, - you may want to look into its `end()` method or the `close` event instead. - -* Feature / BC break: Consistent event semantics and documentation, - explicitly state *when* events will be emitted and *which* arguments they - receive. - (#73 and #69 by @clue) - - The documentation now explicitly defines each event and its arguments. - Custom events and event arguments are still supported. - Most notably, all defined events only receive inherently required event - arguments and no longer transmit the instance they are emitted on for - consistency and performance reasons. - - ```php - // old (inconsistent and not supported by all implementations) - $stream->on('data', function ($data, $stream) { - // process $data - }); - - // new (consistent throughout the whole ecosystem) - $stream->on('data', function ($data) use ($stream) { - // process $data - }); - ``` - - > This mostly adds documentation (and thus some stricter, consistent - definitions) for the existing behavior, it does NOT define any major - changes otherwise. - Most existing code should be compatible with these changes, unless - it relied on some undocumented/unintended semantics. - -* Feature / BC break: Consistent method semantics and documentation - (#72 by @clue) - - > This mostly adds documentation (and thus some stricter, consistent - definitions) for the existing behavior, it does NOT define any major - changes otherwise. - Most existing code should be compatible with these changes, unless - it relied on some undocumented/unintended semantics. - -* Feature: Consistent `pipe()` semantics for closed and closing streams - (#71 from @clue) - - The source stream will now always be paused via `pause()` when the - destination stream closes. Also, properly stop piping if the source - stream closes and remove all event forwarding. - -* Improve test suite by adding PHPUnit to `require-dev` and improving coverage. - (#74 and #75 by @clue, #66 by @nawarian) - -## 0.4.6 (2017-01-25) - -* Feature: The `Buffer` can now be injected into the `Stream` (or be used standalone) - (#62 by @clue) - -* Fix: Forward `close` event only once for `CompositeStream` and `ThroughStream` - (#60 by @clue) - -* Fix: Consistent `close` event behavior for `Buffer` - (#61 by @clue) - -## 0.4.5 (2016-11-13) - -* Feature: Support setting read buffer size to `null` (infinite) - (#42 by @clue) - -* Fix: Do not emit `full-drain` event if `Buffer` is closed during `drain` event - (#55 by @clue) - -* Vastly improved performance by factor of 10x to 20x. - Raise default buffer sizes to 64 KiB and simplify and improve error handling - and unneeded function calls. - (#53, #55, #56 by @clue) - -## 0.4.4 (2016-08-22) - -* Bug fix: Emit `error` event and close `Stream` when accessing the underlying - stream resource fails with a permanent error. - (#52 and #40 by @clue, #25 by @lysenkobv) - -* Bug fix: Do not emit empty `data` event if nothing has been read (stream reached EOF) - (#39 by @clue) - -* Bug fix: Ignore empty writes to `Buffer` - (#51 by @clue) - -* Add benchmarking script to measure throughput in CI - (#41 by @clue) - -## 0.4.3 (2015-10-07) - -* Bug fix: Read buffer to 0 fixes error with libevent and large quantity of I/O (@mbonneau) -* Bug fix: No double-write during drain call (@arnaud-lb) -* Bug fix: Support HHVM (@clue) -* Adjust compatibility to 5.3 (@clue) - -## 0.4.2 (2014-09-09) - -* Added DuplexStreamInterface -* Stream sets stream resources to non-blocking -* Fixed potential race condition in pipe - -## 0.4.1 (2014-04-13) - -* Bug fix: v0.3.4 changes merged for v0.4.1 - -## 0.3.4 (2014-03-30) - -* Bug fix: [Stream] Fixed 100% CPU spike from non-empty write buffer on closed stream - -## 0.4.0 (2014-02-02) - -* BC break: Bump minimum PHP version to PHP 5.4, remove 5.3 specific hacks -* BC break: Update to Evenement 2.0 -* Dependency: Autoloading and filesystem structure now PSR-4 instead of PSR-0 - -## 0.3.3 (2013-07-08) - -* Bug fix: [Stream] Correctly detect closed connections - -## 0.3.2 (2013-05-10) - -* Bug fix: [Stream] Make sure CompositeStream is closed properly - -## 0.3.1 (2013-04-21) - -* Bug fix: [Stream] Allow any `ReadableStreamInterface` on `BufferedSink::createPromise()` - -## 0.3.0 (2013-04-14) - -* Feature: [Stream] Factory method for BufferedSink - -## 0.2.6 (2012-12-26) - -* Version bump - -## 0.2.5 (2012-11-26) - -* Feature: Make BufferedSink trigger progress events on the promise (@jsor) - -## 0.2.4 (2012-11-18) - -* Feature: Added ThroughStream, CompositeStream, ReadableStream and WritableStream -* Feature: Added BufferedSink - -## 0.2.3 (2012-11-14) - -* Version bump - -## 0.2.2 (2012-10-28) - -* Version bump - -## 0.2.1 (2012-10-14) - -* Bug fix: Check for EOF in `Buffer::write()` - -## 0.2.0 (2012-09-10) - -* Version bump - -## 0.1.1 (2012-07-12) - -* Bug fix: Testing and functional against PHP >= 5.3.3 and <= 5.3.8 - -## 0.1.0 (2012-07-11) - -* First tagged release diff --git a/digital_doctor/vendor/react/stream/LICENSE b/digital_doctor/vendor/react/stream/LICENSE deleted file mode 100644 index d6f8901..0000000 --- a/digital_doctor/vendor/react/stream/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2012 Christian Lück, Cees-Jan Kiewiet, Jan Sorgalla, Chris Boden, Igor Wiedler - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/digital_doctor/vendor/react/stream/README.md b/digital_doctor/vendor/react/stream/README.md deleted file mode 100644 index 9c0468a..0000000 --- a/digital_doctor/vendor/react/stream/README.md +++ /dev/null @@ -1,1249 +0,0 @@ -# Stream - -[![CI status](https://github.com/reactphp/stream/actions/workflows/ci.yml/badge.svg)](https://github.com/reactphp/stream/actions) -[![installs on Packagist](https://img.shields.io/packagist/dt/react/stream?color=blue&label=installs%20on%20Packagist)](https://packagist.org/packages/react/stream) - -Event-driven readable and writable streams for non-blocking I/O in [ReactPHP](https://reactphp.org/). - -In order to make the [EventLoop](https://github.com/reactphp/event-loop) -easier to use, this component introduces the powerful concept of "streams". -Streams allow you to efficiently process huge amounts of data (such as a multi -Gigabyte file download) in small chunks without having to store everything in -memory at once. -They are very similar to the streams found in PHP itself, -but have an interface more suited for async, non-blocking I/O. - -**Table of contents** - -* [Stream usage](#stream-usage) - * [ReadableStreamInterface](#readablestreaminterface) - * [data event](#data-event) - * [end event](#end-event) - * [error event](#error-event) - * [close event](#close-event) - * [isReadable()](#isreadable) - * [pause()](#pause) - * [resume()](#resume) - * [pipe()](#pipe) - * [close()](#close) - * [WritableStreamInterface](#writablestreaminterface) - * [drain event](#drain-event) - * [pipe event](#pipe-event) - * [error event](#error-event-1) - * [close event](#close-event-1) - * [isWritable()](#iswritable) - * [write()](#write) - * [end()](#end) - * [close()](#close-1) - * [DuplexStreamInterface](#duplexstreaminterface) -* [Creating streams](#creating-streams) - * [ReadableResourceStream](#readableresourcestream) - * [WritableResourceStream](#writableresourcestream) - * [DuplexResourceStream](#duplexresourcestream) - * [ThroughStream](#throughstream) - * [CompositeStream](#compositestream) -* [Usage](#usage) -* [Install](#install) -* [Tests](#tests) -* [License](#license) -* [More](#more) - -## Stream usage - -ReactPHP uses the concept of "streams" throughout its ecosystem to provide a -consistent higher-level abstraction for processing streams of arbitrary data -contents and size. -While a stream itself is a quite low-level concept, it can be used as a powerful -abstraction to build higher-level components and protocols on top. - -If you're new to this concept, it helps to think of them as a water pipe: -You can consume water from a source or you can produce water and forward (pipe) -it to any destination (sink). - -Similarly, streams can either be - -* readable (such as `STDIN` terminal input) or -* writable (such as `STDOUT` terminal output) or -* duplex (both readable *and* writable, such as a TCP/IP connection) - -Accordingly, this package defines the following three interfaces - -* [`ReadableStreamInterface`](#readablestreaminterface) -* [`WritableStreamInterface`](#writablestreaminterface) -* [`DuplexStreamInterface`](#duplexstreaminterface) - -### ReadableStreamInterface - -The `ReadableStreamInterface` is responsible for providing an interface for -read-only streams and the readable side of duplex streams. - -Besides defining a few methods, this interface also implements the -`EventEmitterInterface` which allows you to react to certain events. - -The event callback functions MUST be a valid `callable` that obeys strict -parameter definitions and MUST accept event parameters exactly as documented. -The event callback functions MUST NOT throw an `Exception`. -The return value of the event callback functions will be ignored and has no -effect, so for performance reasons you're recommended to not return any -excessive data structures. - -Every implementation of this interface MUST follow these event semantics in -order to be considered a well-behaving stream. - -> Note that higher-level implementations of this interface may choose to - define additional events with dedicated semantics not defined as part of - this low-level stream specification. Conformance with these event semantics - is out of scope for this interface, so you may also have to refer to the - documentation of such a higher-level implementation. - -#### data event - -The `data` event will be emitted whenever some data was read/received -from this source stream. -The event receives a single mixed argument for incoming data. - -```php -$stream->on('data', function ($data) { - echo $data; -}); -``` - -This event MAY be emitted any number of times, which may be zero times if -this stream does not send any data at all. -It SHOULD not be emitted after an `end` or `close` event. - -The given `$data` argument may be of mixed type, but it's usually -recommended it SHOULD be a `string` value or MAY use a type that allows -representation as a `string` for maximum compatibility. - -Many common streams (such as a TCP/IP connection or a file-based stream) -will emit the raw (binary) payload data that is received over the wire as -chunks of `string` values. - -Due to the stream-based nature of this, the sender may send any number -of chunks with varying sizes. There are no guarantees that these chunks -will be received with the exact same framing the sender intended to send. -In other words, many lower-level protocols (such as TCP/IP) transfer the -data in chunks that may be anywhere between single-byte values to several -dozens of kilobytes. You may want to apply a higher-level protocol to -these low-level data chunks in order to achieve proper message framing. - -#### end event - -The `end` event will be emitted once the source stream has successfully -reached the end of the stream (EOF). - -```php -$stream->on('end', function () { - echo 'END'; -}); -``` - -This event SHOULD be emitted once or never at all, depending on whether -a successful end was detected. -It SHOULD NOT be emitted after a previous `end` or `close` event. -It MUST NOT be emitted if the stream closes due to a non-successful -end, such as after a previous `error` event. - -After the stream is ended, it MUST switch to non-readable mode, -see also `isReadable()`. - -This event will only be emitted if the *end* was reached successfully, -not if the stream was interrupted by an unrecoverable error or explicitly -closed. Not all streams know this concept of a "successful end". -Many use-cases involve detecting when the stream closes (terminates) -instead, in this case you should use the `close` event. -After the stream emits an `end` event, it SHOULD usually be followed by a -`close` event. - -Many common streams (such as a TCP/IP connection or a file-based stream) -will emit this event if either the remote side closes the connection or -a file handle was successfully read until reaching its end (EOF). - -Note that this event should not be confused with the `end()` method. -This event defines a successful end *reading* from a source stream, while -the `end()` method defines *writing* a successful end to a destination -stream. - -#### error event - -The `error` event will be emitted once a fatal error occurs, usually while -trying to read from this stream. -The event receives a single `Exception` argument for the error instance. - -```php -$server->on('error', function (Exception $e) { - echo 'Error: ' . $e->getMessage() . PHP_EOL; -}); -``` - -This event SHOULD be emitted once the stream detects a fatal error, such -as a fatal transmission error or after an unexpected `data` or premature -`end` event. -It SHOULD NOT be emitted after a previous `error`, `end` or `close` event. -It MUST NOT be emitted if this is not a fatal error condition, such as -a temporary network issue that did not cause any data to be lost. - -After the stream errors, it MUST close the stream and SHOULD thus be -followed by a `close` event and then switch to non-readable mode, see -also `close()` and `isReadable()`. - -Many common streams (such as a TCP/IP connection or a file-based stream) -only deal with data transmission and do not make assumption about data -boundaries (such as unexpected `data` or premature `end` events). -In other words, many lower-level protocols (such as TCP/IP) may choose -to only emit this for a fatal transmission error once and will then -close (terminate) the stream in response. - -If this stream is a `DuplexStreamInterface`, you should also notice -how the writable side of the stream also implements an `error` event. -In other words, an error may occur while either reading or writing the -stream which should result in the same error processing. - -#### close event - -The `close` event will be emitted once the stream closes (terminates). - -```php -$stream->on('close', function () { - echo 'CLOSED'; -}); -``` - -This event SHOULD be emitted once or never at all, depending on whether -the stream ever terminates. -It SHOULD NOT be emitted after a previous `close` event. - -After the stream is closed, it MUST switch to non-readable mode, -see also `isReadable()`. - -Unlike the `end` event, this event SHOULD be emitted whenever the stream -closes, irrespective of whether this happens implicitly due to an -unrecoverable error or explicitly when either side closes the stream. -If you only want to detect a *successful* end, you should use the `end` -event instead. - -Many common streams (such as a TCP/IP connection or a file-based stream) -will likely choose to emit this event after reading a *successful* `end` -event or after a fatal transmission `error` event. - -If this stream is a `DuplexStreamInterface`, you should also notice -how the writable side of the stream also implements a `close` event. -In other words, after receiving this event, the stream MUST switch into -non-writable AND non-readable mode, see also `isWritable()`. -Note that this event should not be confused with the `end` event. - -#### isReadable() - -The `isReadable(): bool` method can be used to -check whether this stream is in a readable state (not closed already). - -This method can be used to check if the stream still accepts incoming -data events or if it is ended or closed already. -Once the stream is non-readable, no further `data` or `end` events SHOULD -be emitted. - -```php -assert($stream->isReadable() === false); - -$stream->on('data', assertNeverCalled()); -$stream->on('end', assertNeverCalled()); -``` - -A successfully opened stream always MUST start in readable mode. - -Once the stream ends or closes, it MUST switch to non-readable mode. -This can happen any time, explicitly through `close()` or -implicitly due to a remote close or an unrecoverable transmission error. -Once a stream has switched to non-readable mode, it MUST NOT transition -back to readable mode. - -If this stream is a `DuplexStreamInterface`, you should also notice -how the writable side of the stream also implements an `isWritable()` -method. Unless this is a half-open duplex stream, they SHOULD usually -have the same return value. - -#### pause() - -The `pause(): void` method can be used to -pause reading incoming data events. - -Removes the data source file descriptor from the event loop. This -allows you to throttle incoming data. - -Unless otherwise noted, a successfully opened stream SHOULD NOT start -in paused state. - -Once the stream is paused, no futher `data` or `end` events SHOULD -be emitted. - -```php -$stream->pause(); - -$stream->on('data', assertShouldNeverCalled()); -$stream->on('end', assertShouldNeverCalled()); -``` - -This method is advisory-only, though generally not recommended, the -stream MAY continue emitting `data` events. - -You can continue processing events by calling `resume()` again. - -Note that both methods can be called any number of times, in particular -calling `pause()` more than once SHOULD NOT have any effect. - -See also `resume()`. - -#### resume() - -The `resume(): void` method can be used to -resume reading incoming data events. - -Re-attach the data source after a previous `pause()`. - -```php -$stream->pause(); - -Loop::addTimer(1.0, function () use ($stream) { - $stream->resume(); -}); -``` - -Note that both methods can be called any number of times, in particular -calling `resume()` without a prior `pause()` SHOULD NOT have any effect. - -See also `pause()`. - -#### pipe() - -The `pipe(WritableStreamInterface $dest, array $options = [])` method can be used to -pipe all the data from this readable source into the given writable destination. - -Automatically sends all incoming data to the destination. -Automatically throttles the source based on what the destination can handle. - -```php -$source->pipe($dest); -``` - -Similarly, you can also pipe an instance implementing `DuplexStreamInterface` -into itself in order to write back all the data that is received. -This may be a useful feature for a TCP/IP echo service: - -```php -$connection->pipe($connection); -``` - -This method returns the destination stream as-is, which can be used to -set up chains of piped streams: - -```php -$source->pipe($decodeGzip)->pipe($filterBadWords)->pipe($dest); -``` - -By default, this will call `end()` on the destination stream once the -source stream emits an `end` event. This can be disabled like this: - -```php -$source->pipe($dest, array('end' => false)); -``` - -Note that this only applies to the `end` event. -If an `error` or explicit `close` event happens on the source stream, -you'll have to manually close the destination stream: - -```php -$source->pipe($dest); -$source->on('close', function () use ($dest) { - $dest->end('BYE!'); -}); -``` - -If the source stream is not readable (closed state), then this is a NO-OP. - -```php -$source->close(); -$source->pipe($dest); // NO-OP -``` - -If the destinantion stream is not writable (closed state), then this will simply -throttle (pause) the source stream: - -```php -$dest->close(); -$source->pipe($dest); // calls $source->pause() -``` - -Similarly, if the destination stream is closed while the pipe is still -active, it will also throttle (pause) the source stream: - -```php -$source->pipe($dest); -$dest->close(); // calls $source->pause() -``` - -Once the pipe is set up successfully, the destination stream MUST emit -a `pipe` event with this source stream an event argument. - -#### close() - -The `close(): void` method can be used to -close the stream (forcefully). - -This method can be used to (forcefully) close the stream. - -```php -$stream->close(); -``` - -Once the stream is closed, it SHOULD emit a `close` event. -Note that this event SHOULD NOT be emitted more than once, in particular -if this method is called multiple times. - -After calling this method, the stream MUST switch into a non-readable -mode, see also `isReadable()`. -This means that no further `data` or `end` events SHOULD be emitted. - -```php -$stream->close(); -assert($stream->isReadable() === false); - -$stream->on('data', assertNeverCalled()); -$stream->on('end', assertNeverCalled()); -``` - -If this stream is a `DuplexStreamInterface`, you should also notice -how the writable side of the stream also implements a `close()` method. -In other words, after calling this method, the stream MUST switch into -non-writable AND non-readable mode, see also `isWritable()`. -Note that this method should not be confused with the `end()` method. - -### WritableStreamInterface - -The `WritableStreamInterface` is responsible for providing an interface for -write-only streams and the writable side of duplex streams. - -Besides defining a few methods, this interface also implements the -`EventEmitterInterface` which allows you to react to certain events. - -The event callback functions MUST be a valid `callable` that obeys strict -parameter definitions and MUST accept event parameters exactly as documented. -The event callback functions MUST NOT throw an `Exception`. -The return value of the event callback functions will be ignored and has no -effect, so for performance reasons you're recommended to not return any -excessive data structures. - -Every implementation of this interface MUST follow these event semantics in -order to be considered a well-behaving stream. - -> Note that higher-level implementations of this interface may choose to - define additional events with dedicated semantics not defined as part of - this low-level stream specification. Conformance with these event semantics - is out of scope for this interface, so you may also have to refer to the - documentation of such a higher-level implementation. - -#### drain event - -The `drain` event will be emitted whenever the write buffer became full -previously and is now ready to accept more data. - -```php -$stream->on('drain', function () use ($stream) { - echo 'Stream is now ready to accept more data'; -}); -``` - -This event SHOULD be emitted once every time the buffer became full -previously and is now ready to accept more data. -In other words, this event MAY be emitted any number of times, which may -be zero times if the buffer never became full in the first place. -This event SHOULD NOT be emitted if the buffer has not become full -previously. - -This event is mostly used internally, see also `write()` for more details. - -#### pipe event - -The `pipe` event will be emitted whenever a readable stream is `pipe()`d -into this stream. -The event receives a single `ReadableStreamInterface` argument for the -source stream. - -```php -$stream->on('pipe', function (ReadableStreamInterface $source) use ($stream) { - echo 'Now receiving piped data'; - - // explicitly close target if source emits an error - $source->on('error', function () use ($stream) { - $stream->close(); - }); -}); - -$source->pipe($stream); -``` - -This event MUST be emitted once for each readable stream that is -successfully piped into this destination stream. -In other words, this event MAY be emitted any number of times, which may -be zero times if no stream is ever piped into this stream. -This event MUST NOT be emitted if either the source is not readable -(closed already) or this destination is not writable (closed already). - -This event is mostly used internally, see also `pipe()` for more details. - -#### error event - -The `error` event will be emitted once a fatal error occurs, usually while -trying to write to this stream. -The event receives a single `Exception` argument for the error instance. - -```php -$stream->on('error', function (Exception $e) { - echo 'Error: ' . $e->getMessage() . PHP_EOL; -}); -``` - -This event SHOULD be emitted once the stream detects a fatal error, such -as a fatal transmission error. -It SHOULD NOT be emitted after a previous `error` or `close` event. -It MUST NOT be emitted if this is not a fatal error condition, such as -a temporary network issue that did not cause any data to be lost. - -After the stream errors, it MUST close the stream and SHOULD thus be -followed by a `close` event and then switch to non-writable mode, see -also `close()` and `isWritable()`. - -Many common streams (such as a TCP/IP connection or a file-based stream) -only deal with data transmission and may choose -to only emit this for a fatal transmission error once and will then -close (terminate) the stream in response. - -If this stream is a `DuplexStreamInterface`, you should also notice -how the readable side of the stream also implements an `error` event. -In other words, an error may occur while either reading or writing the -stream which should result in the same error processing. - -#### close event - -The `close` event will be emitted once the stream closes (terminates). - -```php -$stream->on('close', function () { - echo 'CLOSED'; -}); -``` - -This event SHOULD be emitted once or never at all, depending on whether -the stream ever terminates. -It SHOULD NOT be emitted after a previous `close` event. - -After the stream is closed, it MUST switch to non-writable mode, -see also `isWritable()`. - -This event SHOULD be emitted whenever the stream closes, irrespective of -whether this happens implicitly due to an unrecoverable error or -explicitly when either side closes the stream. - -Many common streams (such as a TCP/IP connection or a file-based stream) -will likely choose to emit this event after flushing the buffer from -the `end()` method, after receiving a *successful* `end` event or after -a fatal transmission `error` event. - -If this stream is a `DuplexStreamInterface`, you should also notice -how the readable side of the stream also implements a `close` event. -In other words, after receiving this event, the stream MUST switch into -non-writable AND non-readable mode, see also `isReadable()`. -Note that this event should not be confused with the `end` event. - -#### isWritable() - -The `isWritable(): bool` method can be used to -check whether this stream is in a writable state (not closed already). - -This method can be used to check if the stream still accepts writing -any data or if it is ended or closed already. -Writing any data to a non-writable stream is a NO-OP: - -```php -assert($stream->isWritable() === false); - -$stream->write('end'); // NO-OP -$stream->end('end'); // NO-OP -``` - -A successfully opened stream always MUST start in writable mode. - -Once the stream ends or closes, it MUST switch to non-writable mode. -This can happen any time, explicitly through `end()` or `close()` or -implicitly due to a remote close or an unrecoverable transmission error. -Once a stream has switched to non-writable mode, it MUST NOT transition -back to writable mode. - -If this stream is a `DuplexStreamInterface`, you should also notice -how the readable side of the stream also implements an `isReadable()` -method. Unless this is a half-open duplex stream, they SHOULD usually -have the same return value. - -#### write() - -The `write(mixed $data): bool` method can be used to -write some data into the stream. - -A successful write MUST be confirmed with a boolean `true`, which means -that either the data was written (flushed) immediately or is buffered and -scheduled for a future write. Note that this interface gives you no -control over explicitly flushing the buffered data, as finding the -appropriate time for this is beyond the scope of this interface and left -up to the implementation of this interface. - -Many common streams (such as a TCP/IP connection or file-based stream) -may choose to buffer all given data and schedule a future flush by using -an underlying EventLoop to check when the resource is actually writable. - -If a stream cannot handle writing (or flushing) the data, it SHOULD emit -an `error` event and MAY `close()` the stream if it can not recover from -this error. - -If the internal buffer is full after adding `$data`, then `write()` -SHOULD return `false`, indicating that the caller should stop sending -data until the buffer drains. -The stream SHOULD send a `drain` event once the buffer is ready to accept -more data. - -Similarly, if the stream is not writable (already in a closed state) -it MUST NOT process the given `$data` and SHOULD return `false`, -indicating that the caller should stop sending data. - -The given `$data` argument MAY be of mixed type, but it's usually -recommended it SHOULD be a `string` value or MAY use a type that allows -representation as a `string` for maximum compatibility. - -Many common streams (such as a TCP/IP connection or a file-based stream) -will only accept the raw (binary) payload data that is transferred over -the wire as chunks of `string` values. - -Due to the stream-based nature of this, the sender may send any number -of chunks with varying sizes. There are no guarantees that these chunks -will be received with the exact same framing the sender intended to send. -In other words, many lower-level protocols (such as TCP/IP) transfer the -data in chunks that may be anywhere between single-byte values to several -dozens of kilobytes. You may want to apply a higher-level protocol to -these low-level data chunks in order to achieve proper message framing. - -#### end() - -The `end(mixed $data = null): void` method can be used to -successfully end the stream (after optionally sending some final data). - -This method can be used to successfully end the stream, i.e. close -the stream after sending out all data that is currently buffered. - -```php -$stream->write('hello'); -$stream->write('world'); -$stream->end(); -``` - -If there's no data currently buffered and nothing to be flushed, then -this method MAY `close()` the stream immediately. - -If there's still data in the buffer that needs to be flushed first, then -this method SHOULD try to write out this data and only then `close()` -the stream. -Once the stream is closed, it SHOULD emit a `close` event. - -Note that this interface gives you no control over explicitly flushing -the buffered data, as finding the appropriate time for this is beyond the -scope of this interface and left up to the implementation of this -interface. - -Many common streams (such as a TCP/IP connection or file-based stream) -may choose to buffer all given data and schedule a future flush by using -an underlying EventLoop to check when the resource is actually writable. - -You can optionally pass some final data that is written to the stream -before ending the stream. If a non-`null` value is given as `$data`, then -this method will behave just like calling `write($data)` before ending -with no data. - -```php -// shorter version -$stream->end('bye'); - -// same as longer version -$stream->write('bye'); -$stream->end(); -``` - -After calling this method, the stream MUST switch into a non-writable -mode, see also `isWritable()`. -This means that no further writes are possible, so any additional -`write()` or `end()` calls have no effect. - -```php -$stream->end(); -assert($stream->isWritable() === false); - -$stream->write('nope'); // NO-OP -$stream->end(); // NO-OP -``` - -If this stream is a `DuplexStreamInterface`, calling this method SHOULD -also end its readable side, unless the stream supports half-open mode. -In other words, after calling this method, these streams SHOULD switch -into non-writable AND non-readable mode, see also `isReadable()`. -This implies that in this case, the stream SHOULD NOT emit any `data` -or `end` events anymore. -Streams MAY choose to use the `pause()` method logic for this, but -special care may have to be taken to ensure a following call to the -`resume()` method SHOULD NOT continue emitting readable events. - -Note that this method should not be confused with the `close()` method. - -#### close() - -The `close(): void` method can be used to -close the stream (forcefully). - -This method can be used to forcefully close the stream, i.e. close -the stream without waiting for any buffered data to be flushed. -If there's still data in the buffer, this data SHOULD be discarded. - -```php -$stream->close(); -``` - -Once the stream is closed, it SHOULD emit a `close` event. -Note that this event SHOULD NOT be emitted more than once, in particular -if this method is called multiple times. - -After calling this method, the stream MUST switch into a non-writable -mode, see also `isWritable()`. -This means that no further writes are possible, so any additional -`write()` or `end()` calls have no effect. - -```php -$stream->close(); -assert($stream->isWritable() === false); - -$stream->write('nope'); // NO-OP -$stream->end(); // NO-OP -``` - -Note that this method should not be confused with the `end()` method. -Unlike the `end()` method, this method does not take care of any existing -buffers and simply discards any buffer contents. -Likewise, this method may also be called after calling `end()` on a -stream in order to stop waiting for the stream to flush its final data. - -```php -$stream->end(); -Loop::addTimer(1.0, function () use ($stream) { - $stream->close(); -}); -``` - -If this stream is a `DuplexStreamInterface`, you should also notice -how the readable side of the stream also implements a `close()` method. -In other words, after calling this method, the stream MUST switch into -non-writable AND non-readable mode, see also `isReadable()`. - -### DuplexStreamInterface - -The `DuplexStreamInterface` is responsible for providing an interface for -duplex streams (both readable and writable). - -It builds on top of the existing interfaces for readable and writable streams -and follows the exact same method and event semantics. -If you're new to this concept, you should look into the -`ReadableStreamInterface` and `WritableStreamInterface` first. - -Besides defining a few methods, this interface also implements the -`EventEmitterInterface` which allows you to react to the same events defined -on the `ReadbleStreamInterface` and `WritableStreamInterface`. - -The event callback functions MUST be a valid `callable` that obeys strict -parameter definitions and MUST accept event parameters exactly as documented. -The event callback functions MUST NOT throw an `Exception`. -The return value of the event callback functions will be ignored and has no -effect, so for performance reasons you're recommended to not return any -excessive data structures. - -Every implementation of this interface MUST follow these event semantics in -order to be considered a well-behaving stream. - -> Note that higher-level implementations of this interface may choose to - define additional events with dedicated semantics not defined as part of - this low-level stream specification. Conformance with these event semantics - is out of scope for this interface, so you may also have to refer to the - documentation of such a higher-level implementation. - -See also [`ReadableStreamInterface`](#readablestreaminterface) and -[`WritableStreamInterface`](#writablestreaminterface) for more details. - -## Creating streams - -ReactPHP uses the concept of "streams" throughout its ecosystem, so that -many higher-level consumers of this package only deal with -[stream usage](#stream-usage). -This implies that stream instances are most often created within some -higher-level components and many consumers never actually have to deal with -creating a stream instance. - -* Use [react/socket](https://github.com/reactphp/socket) - if you want to accept incoming or establish outgoing plaintext TCP/IP or - secure TLS socket connection streams. -* Use [react/http](https://github.com/reactphp/http) - if you want to receive an incoming HTTP request body streams. -* Use [react/child-process](https://github.com/reactphp/child-process) - if you want to communicate with child processes via process pipes such as - STDIN, STDOUT, STDERR etc. -* Use experimental [react/filesystem](https://github.com/reactphp/filesystem) - if you want to read from / write to the filesystem. -* See also the last chapter for [more real-world applications](#more). - -However, if you are writing a lower-level component or want to create a stream -instance from a stream resource, then the following chapter is for you. - -> Note that the following examples use `fopen()` and `stream_socket_client()` - for illustration purposes only. - These functions SHOULD NOT be used in a truly async program because each call - may take several seconds to complete and would block the EventLoop otherwise. - Additionally, the `fopen()` call will return a file handle on some platforms - which may or may not be supported by all EventLoop implementations. - As an alternative, you may want to use higher-level libraries listed above. - -### ReadableResourceStream - -The `ReadableResourceStream` is a concrete implementation of the -[`ReadableStreamInterface`](#readablestreaminterface) for PHP's stream resources. - -This can be used to represent a read-only resource like a file stream opened in -readable mode or a stream such as `STDIN`: - -```php -$stream = new ReadableResourceStream(STDIN); -$stream->on('data', function ($chunk) { - echo $chunk; -}); -$stream->on('end', function () { - echo 'END'; -}); -``` - -See also [`ReadableStreamInterface`](#readablestreaminterface) for more details. - -The first parameter given to the constructor MUST be a valid stream resource -that is opened in reading mode (e.g. `fopen()` mode `r`). -Otherwise, it will throw an `InvalidArgumentException`: - -```php -// throws InvalidArgumentException -$stream = new ReadableResourceStream(false); -``` - -See also the [`DuplexResourceStream`](#readableresourcestream) for read-and-write -stream resources otherwise. - -Internally, this class tries to enable non-blocking mode on the stream resource -which may not be supported for all stream resources. -Most notably, this is not supported by pipes on Windows (STDIN etc.). -If this fails, it will throw a `RuntimeException`: - -```php -// throws RuntimeException on Windows -$stream = new ReadableResourceStream(STDIN); -``` - -Once the constructor is called with a valid stream resource, this class will -take care of the underlying stream resource. -You SHOULD only use its public API and SHOULD NOT interfere with the underlying -stream resource manually. - -This class takes an optional `LoopInterface|null $loop` parameter that can be used to -pass the event loop instance to use for this object. You can use a `null` value -here in order to use the [default loop](https://github.com/reactphp/event-loop#loop). -This value SHOULD NOT be given unless you're sure you want to explicitly use a -given event loop instance. - -This class takes an optional `int|null $readChunkSize` parameter that controls -the maximum buffer size in bytes to read at once from the stream. -You can use a `null` value here in order to apply its default value. -This value SHOULD NOT be changed unless you know what you're doing. -This can be a positive number which means that up to X bytes will be read -at once from the underlying stream resource. Note that the actual number -of bytes read may be lower if the stream resource has less than X bytes -currently available. -This can be `-1` which means "read everything available" from the -underlying stream resource. -This should read until the stream resource is not readable anymore -(i.e. underlying buffer drained), note that this does not neccessarily -mean it reached EOF. - -```php -$stream = new ReadableResourceStream(STDIN, null, 8192); -``` - -> PHP bug warning: If the PHP process has explicitly been started without a - `STDIN` stream, then trying to read from `STDIN` may return data from - another stream resource. This does not happen if you start this with an empty - stream like `php test.php < /dev/null` instead of `php test.php <&-`. - See [#81](https://github.com/reactphp/stream/issues/81) for more details. - -> Changelog: As of v1.2.0 the `$loop` parameter can be omitted (or skipped with a - `null` value) to use the [default loop](https://github.com/reactphp/event-loop#loop). - -### WritableResourceStream - -The `WritableResourceStream` is a concrete implementation of the -[`WritableStreamInterface`](#writablestreaminterface) for PHP's stream resources. - -This can be used to represent a write-only resource like a file stream opened in -writable mode or a stream such as `STDOUT` or `STDERR`: - -```php -$stream = new WritableResourceStream(STDOUT); -$stream->write('hello!'); -$stream->end(); -``` - -See also [`WritableStreamInterface`](#writablestreaminterface) for more details. - -The first parameter given to the constructor MUST be a valid stream resource -that is opened for writing. -Otherwise, it will throw an `InvalidArgumentException`: - -```php -// throws InvalidArgumentException -$stream = new WritableResourceStream(false); -``` - -See also the [`DuplexResourceStream`](#readableresourcestream) for read-and-write -stream resources otherwise. - -Internally, this class tries to enable non-blocking mode on the stream resource -which may not be supported for all stream resources. -Most notably, this is not supported by pipes on Windows (STDOUT, STDERR etc.). -If this fails, it will throw a `RuntimeException`: - -```php -// throws RuntimeException on Windows -$stream = new WritableResourceStream(STDOUT); -``` - -Once the constructor is called with a valid stream resource, this class will -take care of the underlying stream resource. -You SHOULD only use its public API and SHOULD NOT interfere with the underlying -stream resource manually. - -Any `write()` calls to this class will not be performed instantly, but will -be performed asynchronously, once the EventLoop reports the stream resource is -ready to accept data. -For this, it uses an in-memory buffer string to collect all outstanding writes. -This buffer has a soft-limit applied which defines how much data it is willing -to accept before the caller SHOULD stop sending further data. - -This class takes an optional `LoopInterface|null $loop` parameter that can be used to -pass the event loop instance to use for this object. You can use a `null` value -here in order to use the [default loop](https://github.com/reactphp/event-loop#loop). -This value SHOULD NOT be given unless you're sure you want to explicitly use a -given event loop instance. - -This class takes an optional `int|null $writeBufferSoftLimit` parameter that controls -this maximum buffer size in bytes. -You can use a `null` value here in order to apply its default value. -This value SHOULD NOT be changed unless you know what you're doing. - -```php -$stream = new WritableResourceStream(STDOUT, null, 8192); -``` - -This class takes an optional `int|null $writeChunkSize` parameter that controls -this maximum buffer size in bytes to write at once to the stream. -You can use a `null` value here in order to apply its default value. -This value SHOULD NOT be changed unless you know what you're doing. -This can be a positive number which means that up to X bytes will be written -at once to the underlying stream resource. Note that the actual number -of bytes written may be lower if the stream resource has less than X bytes -currently available. -This can be `-1` which means "write everything available" to the -underlying stream resource. - -```php -$stream = new WritableResourceStream(STDOUT, null, null, 8192); -``` - -See also [`write()`](#write) for more details. - -> Changelog: As of v1.2.0 the `$loop` parameter can be omitted (or skipped with a - `null` value) to use the [default loop](https://github.com/reactphp/event-loop#loop). - -### DuplexResourceStream - -The `DuplexResourceStream` is a concrete implementation of the -[`DuplexStreamInterface`](#duplexstreaminterface) for PHP's stream resources. - -This can be used to represent a read-and-write resource like a file stream opened -in read and write mode mode or a stream such as a TCP/IP connection: - -```php -$conn = stream_socket_client('tcp://google.com:80'); -$stream = new DuplexResourceStream($conn); -$stream->write('hello!'); -$stream->end(); -``` - -See also [`DuplexStreamInterface`](#duplexstreaminterface) for more details. - -The first parameter given to the constructor MUST be a valid stream resource -that is opened for reading *and* writing. -Otherwise, it will throw an `InvalidArgumentException`: - -```php -// throws InvalidArgumentException -$stream = new DuplexResourceStream(false); -``` - -See also the [`ReadableResourceStream`](#readableresourcestream) for read-only -and the [`WritableResourceStream`](#writableresourcestream) for write-only -stream resources otherwise. - -Internally, this class tries to enable non-blocking mode on the stream resource -which may not be supported for all stream resources. -Most notably, this is not supported by pipes on Windows (STDOUT, STDERR etc.). -If this fails, it will throw a `RuntimeException`: - -```php -// throws RuntimeException on Windows -$stream = new DuplexResourceStream(STDOUT); -``` - -Once the constructor is called with a valid stream resource, this class will -take care of the underlying stream resource. -You SHOULD only use its public API and SHOULD NOT interfere with the underlying -stream resource manually. - -This class takes an optional `LoopInterface|null $loop` parameter that can be used to -pass the event loop instance to use for this object. You can use a `null` value -here in order to use the [default loop](https://github.com/reactphp/event-loop#loop). -This value SHOULD NOT be given unless you're sure you want to explicitly use a -given event loop instance. - -This class takes an optional `int|null $readChunkSize` parameter that controls -the maximum buffer size in bytes to read at once from the stream. -You can use a `null` value here in order to apply its default value. -This value SHOULD NOT be changed unless you know what you're doing. -This can be a positive number which means that up to X bytes will be read -at once from the underlying stream resource. Note that the actual number -of bytes read may be lower if the stream resource has less than X bytes -currently available. -This can be `-1` which means "read everything available" from the -underlying stream resource. -This should read until the stream resource is not readable anymore -(i.e. underlying buffer drained), note that this does not neccessarily -mean it reached EOF. - -```php -$conn = stream_socket_client('tcp://google.com:80'); -$stream = new DuplexResourceStream($conn, null, 8192); -``` - -Any `write()` calls to this class will not be performed instantly, but will -be performed asynchronously, once the EventLoop reports the stream resource is -ready to accept data. -For this, it uses an in-memory buffer string to collect all outstanding writes. -This buffer has a soft-limit applied which defines how much data it is willing -to accept before the caller SHOULD stop sending further data. - -This class takes another optional `WritableStreamInterface|null $buffer` parameter -that controls this write behavior of this stream. -You can use a `null` value here in order to apply its default value. -This value SHOULD NOT be changed unless you know what you're doing. - -If you want to change the write buffer soft limit, you can pass an instance of -[`WritableResourceStream`](#writableresourcestream) like this: - -```php -$conn = stream_socket_client('tcp://google.com:80'); -$buffer = new WritableResourceStream($conn, null, 8192); -$stream = new DuplexResourceStream($conn, null, null, $buffer); -``` - -See also [`WritableResourceStream`](#writableresourcestream) for more details. - -> Changelog: As of v1.2.0 the `$loop` parameter can be omitted (or skipped with a - `null` value) to use the [default loop](https://github.com/reactphp/event-loop#loop). - -### ThroughStream - -The `ThroughStream` implements the -[`DuplexStreamInterface`](#duplexstreaminterface) and will simply pass any data -you write to it through to its readable end. - -```php -$through = new ThroughStream(); -$through->on('data', $this->expectCallableOnceWith('hello')); - -$through->write('hello'); -``` - -Similarly, the [`end()` method](#end) will end the stream and emit an -[`end` event](#end-event) and then [`close()`](#close-1) the stream. -The [`close()` method](#close-1) will close the stream and emit a -[`close` event](#close-event). -Accordingly, this is can also be used in a [`pipe()`](#pipe) context like this: - -```php -$through = new ThroughStream(); -$source->pipe($through)->pipe($dest); -``` - -Optionally, its constructor accepts any callable function which will then be -used to *filter* any data written to it. This function receives a single data -argument as passed to the writable side and must return the data as it will be -passed to its readable end: - -```php -$through = new ThroughStream('strtoupper'); -$source->pipe($through)->pipe($dest); -``` - -Note that this class makes no assumptions about any data types. This can be -used to convert data, for example for transforming any structured data into -a newline-delimited JSON (NDJSON) stream like this: - -```php -$through = new ThroughStream(function ($data) { - return json_encode($data) . PHP_EOL; -}); -$through->on('data', $this->expectCallableOnceWith("[2, true]\n")); - -$through->write(array(2, true)); -``` - -The callback function is allowed to throw an `Exception`. In this case, -the stream will emit an `error` event and then [`close()`](#close-1) the stream. - -```php -$through = new ThroughStream(function ($data) { - if (!is_string($data)) { - throw new \UnexpectedValueException('Only strings allowed'); - } - return $data; -}); -$through->on('error', $this->expectCallableOnce())); -$through->on('close', $this->expectCallableOnce())); -$through->on('data', $this->expectCallableNever())); - -$through->write(2); -``` - -### CompositeStream - -The `CompositeStream` implements the -[`DuplexStreamInterface`](#duplexstreaminterface) and can be used to create a -single duplex stream from two individual streams implementing -[`ReadableStreamInterface`](#readablestreaminterface) and -[`WritableStreamInterface`](#writablestreaminterface) respectively. - -This is useful for some APIs which may require a single -[`DuplexStreamInterface`](#duplexstreaminterface) or simply because it's often -more convenient to work with a single stream instance like this: - -```php -$stdin = new ReadableResourceStream(STDIN); -$stdout = new WritableResourceStream(STDOUT); - -$stdio = new CompositeStream($stdin, $stdout); - -$stdio->on('data', function ($chunk) use ($stdio) { - $stdio->write('You said: ' . $chunk); -}); -``` - -This is a well-behaving stream which forwards all stream events from the -underlying streams and forwards all streams calls to the underlying streams. - -If you `write()` to the duplex stream, it will simply `write()` to the -writable side and return its status. - -If you `end()` the duplex stream, it will `end()` the writable side and will -`pause()` the readable side. - -If you `close()` the duplex stream, both input streams will be closed. -If either of the two input streams emits a `close` event, the duplex stream -will also close. -If either of the two input streams is already closed while constructing the -duplex stream, it will `close()` the other side and return a closed stream. - -## Usage - -The following example can be used to pipe the contents of a source file into -a destination file without having to ever read the whole file into memory: - -```php -$source = new React\Stream\ReadableResourceStream(fopen('source.txt', 'r')); -$dest = new React\Stream\WritableResourceStream(fopen('destination.txt', 'w')); - -$source->pipe($dest); -``` - -> Note that this example uses `fopen()` for illustration purposes only. - This should not be used in a truly async program because the filesystem is - inherently blocking and each call could potentially take several seconds. - See also [creating streams](#creating-streams) for more sophisticated - examples. - -## Install - -The recommended way to install this library is [through Composer](https://getcomposer.org). -[New to Composer?](https://getcomposer.org/doc/00-intro.md) - -This project follows [SemVer](https://semver.org/). -This will install the latest supported version: - -```bash -composer require react/stream:^1.4 -``` - -See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades. - -This project aims to run on any platform and thus does not require any PHP -extensions and supports running on legacy PHP 5.3 through current PHP 8+ and HHVM. -It's *highly recommended to use PHP 7+* for this project due to its vast -performance improvements. - -## Tests - -To run the test suite, you first need to clone this repo and then install all -dependencies [through Composer](https://getcomposer.org): - -```bash -composer install -``` - -To run the test suite, go to the project root and run: - -```bash -vendor/bin/phpunit -``` - -The test suite also contains a number of functional integration tests that rely -on a stable internet connection. -If you do not want to run these, they can simply be skipped like this: - -```bash -vendor/bin/phpunit --exclude-group internet -``` - -## License - -MIT, see [LICENSE file](LICENSE). - -## More - -* See [creating streams](#creating-streams) for more information on how streams - are created in real-world applications. -* See our [users wiki](https://github.com/reactphp/react/wiki/Users) and the - [dependents on Packagist](https://packagist.org/packages/react/stream/dependents) - for a list of packages that use streams in real-world applications. diff --git a/digital_doctor/vendor/react/stream/composer.json b/digital_doctor/vendor/react/stream/composer.json deleted file mode 100644 index 09d8b71..0000000 --- a/digital_doctor/vendor/react/stream/composer.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "name": "react/stream", - "description": "Event-driven readable and writable streams for non-blocking I/O in ReactPHP", - "keywords": ["event-driven", "readable", "writable", "stream", "non-blocking", "io", "pipe", "ReactPHP"], - "license": "MIT", - "authors": [ - { - "name": "Christian Lück", - "homepage": "https://clue.engineering/", - "email": "christian@clue.engineering" - }, - { - "name": "Cees-Jan Kiewiet", - "homepage": "https://wyrihaximus.net/", - "email": "reactphp@ceesjankiewiet.nl" - }, - { - "name": "Jan Sorgalla", - "homepage": "https://sorgalla.com/", - "email": "jsorgalla@gmail.com" - }, - { - "name": "Chris Boden", - "homepage": "https://cboden.dev/", - "email": "cboden@gmail.com" - } - ], - "require": { - "php": ">=5.3.8", - "react/event-loop": "^1.2", - "evenement/evenement": "^3.0 || ^2.0 || ^1.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", - "clue/stream-filter": "~1.2" - }, - "autoload": { - "psr-4": { - "React\\Stream\\": "src/" - } - }, - "autoload-dev": { - "psr-4": { - "React\\Tests\\Stream\\": "tests/" - } - } -} diff --git a/digital_doctor/vendor/react/stream/src/CompositeStream.php b/digital_doctor/vendor/react/stream/src/CompositeStream.php deleted file mode 100644 index dde091d..0000000 --- a/digital_doctor/vendor/react/stream/src/CompositeStream.php +++ /dev/null @@ -1,83 +0,0 @@ -readable = $readable; - $this->writable = $writable; - - if (!$readable->isReadable() || !$writable->isWritable()) { - $this->close(); - return; - } - - Util::forwardEvents($this->readable, $this, array('data', 'end', 'error')); - Util::forwardEvents($this->writable, $this, array('drain', 'error', 'pipe')); - - $this->readable->on('close', array($this, 'close')); - $this->writable->on('close', array($this, 'close')); - } - - public function isReadable() - { - return $this->readable->isReadable(); - } - - public function pause() - { - $this->readable->pause(); - } - - public function resume() - { - if (!$this->writable->isWritable()) { - return; - } - - $this->readable->resume(); - } - - public function pipe(WritableStreamInterface $dest, array $options = array()) - { - return Util::pipe($this, $dest, $options); - } - - public function isWritable() - { - return $this->writable->isWritable(); - } - - public function write($data) - { - return $this->writable->write($data); - } - - public function end($data = null) - { - $this->readable->pause(); - $this->writable->end($data); - } - - public function close() - { - if ($this->closed) { - return; - } - - $this->closed = true; - $this->readable->close(); - $this->writable->close(); - - $this->emit('close'); - $this->removeAllListeners(); - } -} diff --git a/digital_doctor/vendor/react/stream/src/DuplexResourceStream.php b/digital_doctor/vendor/react/stream/src/DuplexResourceStream.php deleted file mode 100644 index d6de55c..0000000 --- a/digital_doctor/vendor/react/stream/src/DuplexResourceStream.php +++ /dev/null @@ -1,240 +0,0 @@ -isLegacyPipe($stream)) { - \stream_set_read_buffer($stream, 0); - } - - if ($buffer === null) { - $buffer = new WritableResourceStream($stream, $loop); - } - - $this->stream = $stream; - $this->loop = $loop ?: Loop::get(); - $this->bufferSize = ($readChunkSize === null) ? 65536 : (int)$readChunkSize; - $this->buffer = $buffer; - - $that = $this; - - $this->buffer->on('error', function ($error) use ($that) { - $that->emit('error', array($error)); - }); - - $this->buffer->on('close', array($this, 'close')); - - $this->buffer->on('drain', function () use ($that) { - $that->emit('drain'); - }); - - $this->resume(); - } - - public function isReadable() - { - return $this->readable; - } - - public function isWritable() - { - return $this->writable; - } - - public function pause() - { - if ($this->listening) { - $this->loop->removeReadStream($this->stream); - $this->listening = false; - } - } - - public function resume() - { - if (!$this->listening && $this->readable) { - $this->loop->addReadStream($this->stream, array($this, 'handleData')); - $this->listening = true; - } - } - - public function write($data) - { - if (!$this->writable) { - return false; - } - - return $this->buffer->write($data); - } - - public function close() - { - if (!$this->writable && !$this->closing) { - return; - } - - $this->closing = false; - - $this->readable = false; - $this->writable = false; - - $this->emit('close'); - $this->pause(); - $this->buffer->close(); - $this->removeAllListeners(); - - if (\is_resource($this->stream)) { - \fclose($this->stream); - } - } - - public function end($data = null) - { - if (!$this->writable) { - return; - } - - $this->closing = true; - - $this->readable = false; - $this->writable = false; - $this->pause(); - - $this->buffer->end($data); - } - - public function pipe(WritableStreamInterface $dest, array $options = array()) - { - return Util::pipe($this, $dest, $options); - } - - /** @internal */ - public function handleData($stream) - { - $error = null; - \set_error_handler(function ($errno, $errstr, $errfile, $errline) use (&$error) { - $error = new \ErrorException( - $errstr, - 0, - $errno, - $errfile, - $errline - ); - }); - - $data = \stream_get_contents($stream, $this->bufferSize); - - \restore_error_handler(); - - if ($error !== null) { - $this->emit('error', array(new \RuntimeException('Unable to read from stream: ' . $error->getMessage(), 0, $error))); - $this->close(); - return; - } - - if ($data !== '') { - $this->emit('data', array($data)); - } elseif (\feof($this->stream)) { - // no data read => we reached the end and close the stream - $this->emit('end'); - $this->close(); - } - } - - /** - * Returns whether this is a pipe resource in a legacy environment - * - * This works around a legacy PHP bug (#61019) that was fixed in PHP 5.4.28+ - * and PHP 5.5.12+ and newer. - * - * @param resource $resource - * @return bool - * @link https://github.com/reactphp/child-process/issues/40 - * - * @codeCoverageIgnore - */ - private function isLegacyPipe($resource) - { - if (\PHP_VERSION_ID < 50428 || (\PHP_VERSION_ID >= 50500 && \PHP_VERSION_ID < 50512)) { - $meta = \stream_get_meta_data($resource); - - if (isset($meta['stream_type']) && $meta['stream_type'] === 'STDIO') { - return true; - } - } - return false; - } -} diff --git a/digital_doctor/vendor/react/stream/src/DuplexStreamInterface.php b/digital_doctor/vendor/react/stream/src/DuplexStreamInterface.php deleted file mode 100644 index 631ce31..0000000 --- a/digital_doctor/vendor/react/stream/src/DuplexStreamInterface.php +++ /dev/null @@ -1,39 +0,0 @@ - Note that higher-level implementations of this interface may choose to - * define additional events with dedicated semantics not defined as part of - * this low-level stream specification. Conformance with these event semantics - * is out of scope for this interface, so you may also have to refer to the - * documentation of such a higher-level implementation. - * - * @see ReadableStreamInterface - * @see WritableStreamInterface - */ -interface DuplexStreamInterface extends ReadableStreamInterface, WritableStreamInterface -{ -} diff --git a/digital_doctor/vendor/react/stream/src/ReadableResourceStream.php b/digital_doctor/vendor/react/stream/src/ReadableResourceStream.php deleted file mode 100644 index 823360a..0000000 --- a/digital_doctor/vendor/react/stream/src/ReadableResourceStream.php +++ /dev/null @@ -1,188 +0,0 @@ -isLegacyPipe($stream)) { - \stream_set_read_buffer($stream, 0); - } - - $this->stream = $stream; - $this->loop = $loop ?: Loop::get(); - $this->bufferSize = ($readChunkSize === null) ? 65536 : (int)$readChunkSize; - - $this->resume(); - } - - public function isReadable() - { - return !$this->closed; - } - - public function pause() - { - if ($this->listening) { - $this->loop->removeReadStream($this->stream); - $this->listening = false; - } - } - - public function resume() - { - if (!$this->listening && !$this->closed) { - $this->loop->addReadStream($this->stream, array($this, 'handleData')); - $this->listening = true; - } - } - - public function pipe(WritableStreamInterface $dest, array $options = array()) - { - return Util::pipe($this, $dest, $options); - } - - public function close() - { - if ($this->closed) { - return; - } - - $this->closed = true; - - $this->emit('close'); - $this->pause(); - $this->removeAllListeners(); - - if (\is_resource($this->stream)) { - \fclose($this->stream); - } - } - - /** @internal */ - public function handleData() - { - $error = null; - \set_error_handler(function ($errno, $errstr, $errfile, $errline) use (&$error) { - $error = new \ErrorException( - $errstr, - 0, - $errno, - $errfile, - $errline - ); - }); - - $data = \stream_get_contents($this->stream, $this->bufferSize); - - \restore_error_handler(); - - if ($error !== null) { - $this->emit('error', array(new \RuntimeException('Unable to read from stream: ' . $error->getMessage(), 0, $error))); - $this->close(); - return; - } - - if ($data !== '') { - $this->emit('data', array($data)); - } elseif (\feof($this->stream)) { - // no data read => we reached the end and close the stream - $this->emit('end'); - $this->close(); - } - } - - /** - * Returns whether this is a pipe resource in a legacy environment - * - * This works around a legacy PHP bug (#61019) that was fixed in PHP 5.4.28+ - * and PHP 5.5.12+ and newer. - * - * @param resource $resource - * @return bool - * @link https://github.com/reactphp/child-process/issues/40 - * - * @codeCoverageIgnore - */ - private function isLegacyPipe($resource) - { - if (\PHP_VERSION_ID < 50428 || (\PHP_VERSION_ID >= 50500 && \PHP_VERSION_ID < 50512)) { - $meta = \stream_get_meta_data($resource); - - if (isset($meta['stream_type']) && $meta['stream_type'] === 'STDIO') { - return true; - } - } - return false; - } -} diff --git a/digital_doctor/vendor/react/stream/src/ReadableStreamInterface.php b/digital_doctor/vendor/react/stream/src/ReadableStreamInterface.php deleted file mode 100644 index fa3d59c..0000000 --- a/digital_doctor/vendor/react/stream/src/ReadableStreamInterface.php +++ /dev/null @@ -1,362 +0,0 @@ -on('data', function ($data) { - * echo $data; - * }); - * ``` - * - * This event MAY be emitted any number of times, which may be zero times if - * this stream does not send any data at all. - * It SHOULD not be emitted after an `end` or `close` event. - * - * The given `$data` argument may be of mixed type, but it's usually - * recommended it SHOULD be a `string` value or MAY use a type that allows - * representation as a `string` for maximum compatibility. - * - * Many common streams (such as a TCP/IP connection or a file-based stream) - * will emit the raw (binary) payload data that is received over the wire as - * chunks of `string` values. - * - * Due to the stream-based nature of this, the sender may send any number - * of chunks with varying sizes. There are no guarantees that these chunks - * will be received with the exact same framing the sender intended to send. - * In other words, many lower-level protocols (such as TCP/IP) transfer the - * data in chunks that may be anywhere between single-byte values to several - * dozens of kilobytes. You may want to apply a higher-level protocol to - * these low-level data chunks in order to achieve proper message framing. - * - * end event: - * The `end` event will be emitted once the source stream has successfully - * reached the end of the stream (EOF). - * - * ```php - * $stream->on('end', function () { - * echo 'END'; - * }); - * ``` - * - * This event SHOULD be emitted once or never at all, depending on whether - * a successful end was detected. - * It SHOULD NOT be emitted after a previous `end` or `close` event. - * It MUST NOT be emitted if the stream closes due to a non-successful - * end, such as after a previous `error` event. - * - * After the stream is ended, it MUST switch to non-readable mode, - * see also `isReadable()`. - * - * This event will only be emitted if the *end* was reached successfully, - * not if the stream was interrupted by an unrecoverable error or explicitly - * closed. Not all streams know this concept of a "successful end". - * Many use-cases involve detecting when the stream closes (terminates) - * instead, in this case you should use the `close` event. - * After the stream emits an `end` event, it SHOULD usually be followed by a - * `close` event. - * - * Many common streams (such as a TCP/IP connection or a file-based stream) - * will emit this event if either the remote side closes the connection or - * a file handle was successfully read until reaching its end (EOF). - * - * Note that this event should not be confused with the `end()` method. - * This event defines a successful end *reading* from a source stream, while - * the `end()` method defines *writing* a successful end to a destination - * stream. - * - * error event: - * The `error` event will be emitted once a fatal error occurs, usually while - * trying to read from this stream. - * The event receives a single `Exception` argument for the error instance. - * - * ```php - * $stream->on('error', function (Exception $e) { - * echo 'Error: ' . $e->getMessage() . PHP_EOL; - * }); - * ``` - * - * This event SHOULD be emitted once the stream detects a fatal error, such - * as a fatal transmission error or after an unexpected `data` or premature - * `end` event. - * It SHOULD NOT be emitted after a previous `error`, `end` or `close` event. - * It MUST NOT be emitted if this is not a fatal error condition, such as - * a temporary network issue that did not cause any data to be lost. - * - * After the stream errors, it MUST close the stream and SHOULD thus be - * followed by a `close` event and then switch to non-readable mode, see - * also `close()` and `isReadable()`. - * - * Many common streams (such as a TCP/IP connection or a file-based stream) - * only deal with data transmission and do not make assumption about data - * boundaries (such as unexpected `data` or premature `end` events). - * In other words, many lower-level protocols (such as TCP/IP) may choose - * to only emit this for a fatal transmission error once and will then - * close (terminate) the stream in response. - * - * If this stream is a `DuplexStreamInterface`, you should also notice - * how the writable side of the stream also implements an `error` event. - * In other words, an error may occur while either reading or writing the - * stream which should result in the same error processing. - * - * close event: - * The `close` event will be emitted once the stream closes (terminates). - * - * ```php - * $stream->on('close', function () { - * echo 'CLOSED'; - * }); - * ``` - * - * This event SHOULD be emitted once or never at all, depending on whether - * the stream ever terminates. - * It SHOULD NOT be emitted after a previous `close` event. - * - * After the stream is closed, it MUST switch to non-readable mode, - * see also `isReadable()`. - * - * Unlike the `end` event, this event SHOULD be emitted whenever the stream - * closes, irrespective of whether this happens implicitly due to an - * unrecoverable error or explicitly when either side closes the stream. - * If you only want to detect a *successful* end, you should use the `end` - * event instead. - * - * Many common streams (such as a TCP/IP connection or a file-based stream) - * will likely choose to emit this event after reading a *successful* `end` - * event or after a fatal transmission `error` event. - * - * If this stream is a `DuplexStreamInterface`, you should also notice - * how the writable side of the stream also implements a `close` event. - * In other words, after receiving this event, the stream MUST switch into - * non-writable AND non-readable mode, see also `isWritable()`. - * Note that this event should not be confused with the `end` event. - * - * The event callback functions MUST be a valid `callable` that obeys strict - * parameter definitions and MUST accept event parameters exactly as documented. - * The event callback functions MUST NOT throw an `Exception`. - * The return value of the event callback functions will be ignored and has no - * effect, so for performance reasons you're recommended to not return any - * excessive data structures. - * - * Every implementation of this interface MUST follow these event semantics in - * order to be considered a well-behaving stream. - * - * > Note that higher-level implementations of this interface may choose to - * define additional events with dedicated semantics not defined as part of - * this low-level stream specification. Conformance with these event semantics - * is out of scope for this interface, so you may also have to refer to the - * documentation of such a higher-level implementation. - * - * @see EventEmitterInterface - */ -interface ReadableStreamInterface extends EventEmitterInterface -{ - /** - * Checks whether this stream is in a readable state (not closed already). - * - * This method can be used to check if the stream still accepts incoming - * data events or if it is ended or closed already. - * Once the stream is non-readable, no further `data` or `end` events SHOULD - * be emitted. - * - * ```php - * assert($stream->isReadable() === false); - * - * $stream->on('data', assertNeverCalled()); - * $stream->on('end', assertNeverCalled()); - * ``` - * - * A successfully opened stream always MUST start in readable mode. - * - * Once the stream ends or closes, it MUST switch to non-readable mode. - * This can happen any time, explicitly through `close()` or - * implicitly due to a remote close or an unrecoverable transmission error. - * Once a stream has switched to non-readable mode, it MUST NOT transition - * back to readable mode. - * - * If this stream is a `DuplexStreamInterface`, you should also notice - * how the writable side of the stream also implements an `isWritable()` - * method. Unless this is a half-open duplex stream, they SHOULD usually - * have the same return value. - * - * @return bool - */ - public function isReadable(); - - /** - * Pauses reading incoming data events. - * - * Removes the data source file descriptor from the event loop. This - * allows you to throttle incoming data. - * - * Unless otherwise noted, a successfully opened stream SHOULD NOT start - * in paused state. - * - * Once the stream is paused, no futher `data` or `end` events SHOULD - * be emitted. - * - * ```php - * $stream->pause(); - * - * $stream->on('data', assertShouldNeverCalled()); - * $stream->on('end', assertShouldNeverCalled()); - * ``` - * - * This method is advisory-only, though generally not recommended, the - * stream MAY continue emitting `data` events. - * - * You can continue processing events by calling `resume()` again. - * - * Note that both methods can be called any number of times, in particular - * calling `pause()` more than once SHOULD NOT have any effect. - * - * @see self::resume() - * @return void - */ - public function pause(); - - /** - * Resumes reading incoming data events. - * - * Re-attach the data source after a previous `pause()`. - * - * ```php - * $stream->pause(); - * - * Loop::addTimer(1.0, function () use ($stream) { - * $stream->resume(); - * }); - * ``` - * - * Note that both methods can be called any number of times, in particular - * calling `resume()` without a prior `pause()` SHOULD NOT have any effect. - * - * @see self::pause() - * @return void - */ - public function resume(); - - /** - * Pipes all the data from this readable source into the given writable destination. - * - * Automatically sends all incoming data to the destination. - * Automatically throttles the source based on what the destination can handle. - * - * ```php - * $source->pipe($dest); - * ``` - * - * Similarly, you can also pipe an instance implementing `DuplexStreamInterface` - * into itself in order to write back all the data that is received. - * This may be a useful feature for a TCP/IP echo service: - * - * ```php - * $connection->pipe($connection); - * ``` - * - * This method returns the destination stream as-is, which can be used to - * set up chains of piped streams: - * - * ```php - * $source->pipe($decodeGzip)->pipe($filterBadWords)->pipe($dest); - * ``` - * - * By default, this will call `end()` on the destination stream once the - * source stream emits an `end` event. This can be disabled like this: - * - * ```php - * $source->pipe($dest, array('end' => false)); - * ``` - * - * Note that this only applies to the `end` event. - * If an `error` or explicit `close` event happens on the source stream, - * you'll have to manually close the destination stream: - * - * ```php - * $source->pipe($dest); - * $source->on('close', function () use ($dest) { - * $dest->end('BYE!'); - * }); - * ``` - * - * If the source stream is not readable (closed state), then this is a NO-OP. - * - * ```php - * $source->close(); - * $source->pipe($dest); // NO-OP - * ``` - * - * If the destinantion stream is not writable (closed state), then this will simply - * throttle (pause) the source stream: - * - * ```php - * $dest->close(); - * $source->pipe($dest); // calls $source->pause() - * ``` - * - * Similarly, if the destination stream is closed while the pipe is still - * active, it will also throttle (pause) the source stream: - * - * ```php - * $source->pipe($dest); - * $dest->close(); // calls $source->pause() - * ``` - * - * Once the pipe is set up successfully, the destination stream MUST emit - * a `pipe` event with this source stream an event argument. - * - * @param WritableStreamInterface $dest - * @param array $options - * @return WritableStreamInterface $dest stream as-is - */ - public function pipe(WritableStreamInterface $dest, array $options = array()); - - /** - * Closes the stream (forcefully). - * - * This method can be used to (forcefully) close the stream. - * - * ```php - * $stream->close(); - * ``` - * - * Once the stream is closed, it SHOULD emit a `close` event. - * Note that this event SHOULD NOT be emitted more than once, in particular - * if this method is called multiple times. - * - * After calling this method, the stream MUST switch into a non-readable - * mode, see also `isReadable()`. - * This means that no further `data` or `end` events SHOULD be emitted. - * - * ```php - * $stream->close(); - * assert($stream->isReadable() === false); - * - * $stream->on('data', assertNeverCalled()); - * $stream->on('end', assertNeverCalled()); - * ``` - * - * If this stream is a `DuplexStreamInterface`, you should also notice - * how the writable side of the stream also implements a `close()` method. - * In other words, after calling this method, the stream MUST switch into - * non-writable AND non-readable mode, see also `isWritable()`. - * Note that this method should not be confused with the `end()` method. - * - * @return void - * @see WritableStreamInterface::close() - */ - public function close(); -} diff --git a/digital_doctor/vendor/react/stream/src/ThroughStream.php b/digital_doctor/vendor/react/stream/src/ThroughStream.php deleted file mode 100644 index 3b4fbb7..0000000 --- a/digital_doctor/vendor/react/stream/src/ThroughStream.php +++ /dev/null @@ -1,195 +0,0 @@ -on('data', $this->expectCallableOnceWith('hello')); - * - * $through->write('hello'); - * ``` - * - * Similarly, the [`end()` method](#end) will end the stream and emit an - * [`end` event](#end-event) and then [`close()`](#close-1) the stream. - * The [`close()` method](#close-1) will close the stream and emit a - * [`close` event](#close-event). - * Accordingly, this is can also be used in a [`pipe()`](#pipe) context like this: - * - * ```php - * $through = new ThroughStream(); - * $source->pipe($through)->pipe($dest); - * ``` - * - * Optionally, its constructor accepts any callable function which will then be - * used to *filter* any data written to it. This function receives a single data - * argument as passed to the writable side and must return the data as it will be - * passed to its readable end: - * - * ```php - * $through = new ThroughStream('strtoupper'); - * $source->pipe($through)->pipe($dest); - * ``` - * - * Note that this class makes no assumptions about any data types. This can be - * used to convert data, for example for transforming any structured data into - * a newline-delimited JSON (NDJSON) stream like this: - * - * ```php - * $through = new ThroughStream(function ($data) { - * return json_encode($data) . PHP_EOL; - * }); - * $through->on('data', $this->expectCallableOnceWith("[2, true]\n")); - * - * $through->write(array(2, true)); - * ``` - * - * The callback function is allowed to throw an `Exception`. In this case, - * the stream will emit an `error` event and then [`close()`](#close-1) the stream. - * - * ```php - * $through = new ThroughStream(function ($data) { - * if (!is_string($data)) { - * throw new \UnexpectedValueException('Only strings allowed'); - * } - * return $data; - * }); - * $through->on('error', $this->expectCallableOnce())); - * $through->on('close', $this->expectCallableOnce())); - * $through->on('data', $this->expectCallableNever())); - * - * $through->write(2); - * ``` - * - * @see WritableStreamInterface::write() - * @see WritableStreamInterface::end() - * @see DuplexStreamInterface::close() - * @see WritableStreamInterface::pipe() - */ -final class ThroughStream extends EventEmitter implements DuplexStreamInterface -{ - private $readable = true; - private $writable = true; - private $closed = false; - private $paused = false; - private $drain = false; - private $callback; - - public function __construct($callback = null) - { - if ($callback !== null && !\is_callable($callback)) { - throw new InvalidArgumentException('Invalid transformation callback given'); - } - - $this->callback = $callback; - } - - public function pause() - { - // only allow pause if still readable, false otherwise - $this->paused = $this->readable; - } - - public function resume() - { - $this->paused = false; - - // emit drain event if previous write was paused (throttled) - if ($this->drain) { - $this->drain = false; - $this->emit('drain'); - } - } - - public function pipe(WritableStreamInterface $dest, array $options = array()) - { - return Util::pipe($this, $dest, $options); - } - - public function isReadable() - { - return $this->readable; - } - - public function isWritable() - { - return $this->writable; - } - - public function write($data) - { - if (!$this->writable) { - return false; - } - - if ($this->callback !== null) { - try { - $data = \call_user_func($this->callback, $data); - } catch (\Exception $e) { - $this->emit('error', array($e)); - $this->close(); - - return false; - } - } - - $this->emit('data', array($data)); - - // emit drain event on next resume if currently paused (throttled) - if ($this->paused) { - $this->drain = true; - } - - // continue writing if still writable and not paused (throttled), false otherwise - return $this->writable && !$this->paused; - } - - public function end($data = null) - { - if (!$this->writable) { - return; - } - - if (null !== $data) { - $this->write($data); - - // return if write() already caused the stream to close - if (!$this->writable) { - return; - } - } - - $this->readable = false; - $this->writable = false; - $this->paused = false; - $this->drain = false; - - $this->emit('end'); - $this->close(); - } - - public function close() - { - if ($this->closed) { - return; - } - - $this->readable = false; - $this->writable = false; - $this->paused = false; - $this->drain = false; - - $this->closed = true; - $this->callback = null; - - $this->emit('close'); - $this->removeAllListeners(); - } -} diff --git a/digital_doctor/vendor/react/stream/src/Util.php b/digital_doctor/vendor/react/stream/src/Util.php deleted file mode 100644 index 056b037..0000000 --- a/digital_doctor/vendor/react/stream/src/Util.php +++ /dev/null @@ -1,75 +0,0 @@ - NO-OP - if (!$source->isReadable()) { - return $dest; - } - - // destination not writable => just pause() source - if (!$dest->isWritable()) { - $source->pause(); - - return $dest; - } - - $dest->emit('pipe', array($source)); - - // forward all source data events as $dest->write() - $source->on('data', $dataer = function ($data) use ($source, $dest) { - $feedMore = $dest->write($data); - - if (false === $feedMore) { - $source->pause(); - } - }); - $dest->on('close', function () use ($source, $dataer) { - $source->removeListener('data', $dataer); - $source->pause(); - }); - - // forward destination drain as $source->resume() - $dest->on('drain', $drainer = function () use ($source) { - $source->resume(); - }); - $source->on('close', function () use ($dest, $drainer) { - $dest->removeListener('drain', $drainer); - }); - - // forward end event from source as $dest->end() - $end = isset($options['end']) ? $options['end'] : true; - if ($end) { - $source->on('end', $ender = function () use ($dest) { - $dest->end(); - }); - $dest->on('close', function () use ($source, $ender) { - $source->removeListener('end', $ender); - }); - } - - return $dest; - } - - public static function forwardEvents($source, $target, array $events) - { - foreach ($events as $event) { - $source->on($event, function () use ($event, $target) { - $target->emit($event, \func_get_args()); - }); - } - } -} diff --git a/digital_doctor/vendor/react/stream/src/WritableResourceStream.php b/digital_doctor/vendor/react/stream/src/WritableResourceStream.php deleted file mode 100644 index e3a7e74..0000000 --- a/digital_doctor/vendor/react/stream/src/WritableResourceStream.php +++ /dev/null @@ -1,178 +0,0 @@ -stream = $stream; - $this->loop = $loop ?: Loop::get(); - $this->softLimit = ($writeBufferSoftLimit === null) ? 65536 : (int)$writeBufferSoftLimit; - $this->writeChunkSize = ($writeChunkSize === null) ? -1 : (int)$writeChunkSize; - } - - public function isWritable() - { - return $this->writable; - } - - public function write($data) - { - if (!$this->writable) { - return false; - } - - $this->data .= $data; - - if (!$this->listening && $this->data !== '') { - $this->listening = true; - - $this->loop->addWriteStream($this->stream, array($this, 'handleWrite')); - } - - return !isset($this->data[$this->softLimit - 1]); - } - - public function end($data = null) - { - if (null !== $data) { - $this->write($data); - } - - $this->writable = false; - - // close immediately if buffer is already empty - // otherwise wait for buffer to flush first - if ($this->data === '') { - $this->close(); - } - } - - public function close() - { - if ($this->closed) { - return; - } - - if ($this->listening) { - $this->listening = false; - $this->loop->removeWriteStream($this->stream); - } - - $this->closed = true; - $this->writable = false; - $this->data = ''; - - $this->emit('close'); - $this->removeAllListeners(); - - if (\is_resource($this->stream)) { - \fclose($this->stream); - } - } - - /** @internal */ - public function handleWrite() - { - $error = null; - \set_error_handler(function ($_, $errstr) use (&$error) { - $error = $errstr; - }); - - if ($this->writeChunkSize === -1) { - $sent = \fwrite($this->stream, $this->data); - } else { - $sent = \fwrite($this->stream, $this->data, $this->writeChunkSize); - } - - \restore_error_handler(); - - // Only report errors if *nothing* could be sent and an error has been raised. - // Ignore non-fatal warnings if *some* data could be sent. - // Any hard (permanent) error will fail to send any data at all. - // Sending excessive amounts of data will only flush *some* data and then - // report a temporary error (EAGAIN) which we do not raise here in order - // to keep the stream open for further tries to write. - // Should this turn out to be a permanent error later, it will eventually - // send *nothing* and we can detect this. - if (($sent === 0 || $sent === false) && $error !== null) { - $this->emit('error', array(new \RuntimeException('Unable to write to stream: ' . $error))); - $this->close(); - - return; - } - - $exceeded = isset($this->data[$this->softLimit - 1]); - $this->data = (string) \substr($this->data, $sent); - - // buffer has been above limit and is now below limit - if ($exceeded && !isset($this->data[$this->softLimit - 1])) { - $this->emit('drain'); - } - - // buffer is now completely empty => stop trying to write - if ($this->data === '') { - // stop waiting for resource to be writable - if ($this->listening) { - $this->loop->removeWriteStream($this->stream); - $this->listening = false; - } - - // buffer is end()ing and now completely empty => close buffer - if (!$this->writable) { - $this->close(); - } - } - } -} diff --git a/digital_doctor/vendor/react/stream/src/WritableStreamInterface.php b/digital_doctor/vendor/react/stream/src/WritableStreamInterface.php deleted file mode 100644 index e262592..0000000 --- a/digital_doctor/vendor/react/stream/src/WritableStreamInterface.php +++ /dev/null @@ -1,347 +0,0 @@ -on('drain', function () use ($stream) { - * echo 'Stream is now ready to accept more data'; - * }); - * ``` - * - * This event SHOULD be emitted once every time the buffer became full - * previously and is now ready to accept more data. - * In other words, this event MAY be emitted any number of times, which may - * be zero times if the buffer never became full in the first place. - * This event SHOULD NOT be emitted if the buffer has not become full - * previously. - * - * This event is mostly used internally, see also `write()` for more details. - * - * pipe event: - * The `pipe` event will be emitted whenever a readable stream is `pipe()`d - * into this stream. - * The event receives a single `ReadableStreamInterface` argument for the - * source stream. - * - * ```php - * $stream->on('pipe', function (ReadableStreamInterface $source) use ($stream) { - * echo 'Now receiving piped data'; - * - * // explicitly close target if source emits an error - * $source->on('error', function () use ($stream) { - * $stream->close(); - * }); - * }); - * - * $source->pipe($stream); - * ``` - * - * This event MUST be emitted once for each readable stream that is - * successfully piped into this destination stream. - * In other words, this event MAY be emitted any number of times, which may - * be zero times if no stream is ever piped into this stream. - * This event MUST NOT be emitted if either the source is not readable - * (closed already) or this destination is not writable (closed already). - * - * This event is mostly used internally, see also `pipe()` for more details. - * - * error event: - * The `error` event will be emitted once a fatal error occurs, usually while - * trying to write to this stream. - * The event receives a single `Exception` argument for the error instance. - * - * ```php - * $stream->on('error', function (Exception $e) { - * echo 'Error: ' . $e->getMessage() . PHP_EOL; - * }); - * ``` - * - * This event SHOULD be emitted once the stream detects a fatal error, such - * as a fatal transmission error. - * It SHOULD NOT be emitted after a previous `error` or `close` event. - * It MUST NOT be emitted if this is not a fatal error condition, such as - * a temporary network issue that did not cause any data to be lost. - * - * After the stream errors, it MUST close the stream and SHOULD thus be - * followed by a `close` event and then switch to non-writable mode, see - * also `close()` and `isWritable()`. - * - * Many common streams (such as a TCP/IP connection or a file-based stream) - * only deal with data transmission and may choose - * to only emit this for a fatal transmission error once and will then - * close (terminate) the stream in response. - * - * If this stream is a `DuplexStreamInterface`, you should also notice - * how the readable side of the stream also implements an `error` event. - * In other words, an error may occur while either reading or writing the - * stream which should result in the same error processing. - * - * close event: - * The `close` event will be emitted once the stream closes (terminates). - * - * ```php - * $stream->on('close', function () { - * echo 'CLOSED'; - * }); - * ``` - * - * This event SHOULD be emitted once or never at all, depending on whether - * the stream ever terminates. - * It SHOULD NOT be emitted after a previous `close` event. - * - * After the stream is closed, it MUST switch to non-writable mode, - * see also `isWritable()`. - * - * This event SHOULD be emitted whenever the stream closes, irrespective of - * whether this happens implicitly due to an unrecoverable error or - * explicitly when either side closes the stream. - * - * Many common streams (such as a TCP/IP connection or a file-based stream) - * will likely choose to emit this event after flushing the buffer from - * the `end()` method, after receiving a *successful* `end` event or after - * a fatal transmission `error` event. - * - * If this stream is a `DuplexStreamInterface`, you should also notice - * how the readable side of the stream also implements a `close` event. - * In other words, after receiving this event, the stream MUST switch into - * non-writable AND non-readable mode, see also `isReadable()`. - * Note that this event should not be confused with the `end` event. - * - * The event callback functions MUST be a valid `callable` that obeys strict - * parameter definitions and MUST accept event parameters exactly as documented. - * The event callback functions MUST NOT throw an `Exception`. - * The return value of the event callback functions will be ignored and has no - * effect, so for performance reasons you're recommended to not return any - * excessive data structures. - * - * Every implementation of this interface MUST follow these event semantics in - * order to be considered a well-behaving stream. - * - * > Note that higher-level implementations of this interface may choose to - * define additional events with dedicated semantics not defined as part of - * this low-level stream specification. Conformance with these event semantics - * is out of scope for this interface, so you may also have to refer to the - * documentation of such a higher-level implementation. - * - * @see EventEmitterInterface - * @see DuplexStreamInterface - */ -interface WritableStreamInterface extends EventEmitterInterface -{ - /** - * Checks whether this stream is in a writable state (not closed already). - * - * This method can be used to check if the stream still accepts writing - * any data or if it is ended or closed already. - * Writing any data to a non-writable stream is a NO-OP: - * - * ```php - * assert($stream->isWritable() === false); - * - * $stream->write('end'); // NO-OP - * $stream->end('end'); // NO-OP - * ``` - * - * A successfully opened stream always MUST start in writable mode. - * - * Once the stream ends or closes, it MUST switch to non-writable mode. - * This can happen any time, explicitly through `end()` or `close()` or - * implicitly due to a remote close or an unrecoverable transmission error. - * Once a stream has switched to non-writable mode, it MUST NOT transition - * back to writable mode. - * - * If this stream is a `DuplexStreamInterface`, you should also notice - * how the readable side of the stream also implements an `isReadable()` - * method. Unless this is a half-open duplex stream, they SHOULD usually - * have the same return value. - * - * @return bool - */ - public function isWritable(); - - /** - * Write some data into the stream. - * - * A successful write MUST be confirmed with a boolean `true`, which means - * that either the data was written (flushed) immediately or is buffered and - * scheduled for a future write. Note that this interface gives you no - * control over explicitly flushing the buffered data, as finding the - * appropriate time for this is beyond the scope of this interface and left - * up to the implementation of this interface. - * - * Many common streams (such as a TCP/IP connection or file-based stream) - * may choose to buffer all given data and schedule a future flush by using - * an underlying EventLoop to check when the resource is actually writable. - * - * If a stream cannot handle writing (or flushing) the data, it SHOULD emit - * an `error` event and MAY `close()` the stream if it can not recover from - * this error. - * - * If the internal buffer is full after adding `$data`, then `write()` - * SHOULD return `false`, indicating that the caller should stop sending - * data until the buffer drains. - * The stream SHOULD send a `drain` event once the buffer is ready to accept - * more data. - * - * Similarly, if the stream is not writable (already in a closed state) - * it MUST NOT process the given `$data` and SHOULD return `false`, - * indicating that the caller should stop sending data. - * - * The given `$data` argument MAY be of mixed type, but it's usually - * recommended it SHOULD be a `string` value or MAY use a type that allows - * representation as a `string` for maximum compatibility. - * - * Many common streams (such as a TCP/IP connection or a file-based stream) - * will only accept the raw (binary) payload data that is transferred over - * the wire as chunks of `string` values. - * - * Due to the stream-based nature of this, the sender may send any number - * of chunks with varying sizes. There are no guarantees that these chunks - * will be received with the exact same framing the sender intended to send. - * In other words, many lower-level protocols (such as TCP/IP) transfer the - * data in chunks that may be anywhere between single-byte values to several - * dozens of kilobytes. You may want to apply a higher-level protocol to - * these low-level data chunks in order to achieve proper message framing. - * - * @param mixed|string $data - * @return bool - */ - public function write($data); - - /** - * Successfully ends the stream (after optionally sending some final data). - * - * This method can be used to successfully end the stream, i.e. close - * the stream after sending out all data that is currently buffered. - * - * ```php - * $stream->write('hello'); - * $stream->write('world'); - * $stream->end(); - * ``` - * - * If there's no data currently buffered and nothing to be flushed, then - * this method MAY `close()` the stream immediately. - * - * If there's still data in the buffer that needs to be flushed first, then - * this method SHOULD try to write out this data and only then `close()` - * the stream. - * Once the stream is closed, it SHOULD emit a `close` event. - * - * Note that this interface gives you no control over explicitly flushing - * the buffered data, as finding the appropriate time for this is beyond the - * scope of this interface and left up to the implementation of this - * interface. - * - * Many common streams (such as a TCP/IP connection or file-based stream) - * may choose to buffer all given data and schedule a future flush by using - * an underlying EventLoop to check when the resource is actually writable. - * - * You can optionally pass some final data that is written to the stream - * before ending the stream. If a non-`null` value is given as `$data`, then - * this method will behave just like calling `write($data)` before ending - * with no data. - * - * ```php - * // shorter version - * $stream->end('bye'); - * - * // same as longer version - * $stream->write('bye'); - * $stream->end(); - * ``` - * - * After calling this method, the stream MUST switch into a non-writable - * mode, see also `isWritable()`. - * This means that no further writes are possible, so any additional - * `write()` or `end()` calls have no effect. - * - * ```php - * $stream->end(); - * assert($stream->isWritable() === false); - * - * $stream->write('nope'); // NO-OP - * $stream->end(); // NO-OP - * ``` - * - * If this stream is a `DuplexStreamInterface`, calling this method SHOULD - * also end its readable side, unless the stream supports half-open mode. - * In other words, after calling this method, these streams SHOULD switch - * into non-writable AND non-readable mode, see also `isReadable()`. - * This implies that in this case, the stream SHOULD NOT emit any `data` - * or `end` events anymore. - * Streams MAY choose to use the `pause()` method logic for this, but - * special care may have to be taken to ensure a following call to the - * `resume()` method SHOULD NOT continue emitting readable events. - * - * Note that this method should not be confused with the `close()` method. - * - * @param mixed|string|null $data - * @return void - */ - public function end($data = null); - - /** - * Closes the stream (forcefully). - * - * This method can be used to forcefully close the stream, i.e. close - * the stream without waiting for any buffered data to be flushed. - * If there's still data in the buffer, this data SHOULD be discarded. - * - * ```php - * $stream->close(); - * ``` - * - * Once the stream is closed, it SHOULD emit a `close` event. - * Note that this event SHOULD NOT be emitted more than once, in particular - * if this method is called multiple times. - * - * After calling this method, the stream MUST switch into a non-writable - * mode, see also `isWritable()`. - * This means that no further writes are possible, so any additional - * `write()` or `end()` calls have no effect. - * - * ```php - * $stream->close(); - * assert($stream->isWritable() === false); - * - * $stream->write('nope'); // NO-OP - * $stream->end(); // NO-OP - * ``` - * - * Note that this method should not be confused with the `end()` method. - * Unlike the `end()` method, this method does not take care of any existing - * buffers and simply discards any buffer contents. - * Likewise, this method may also be called after calling `end()` on a - * stream in order to stop waiting for the stream to flush its final data. - * - * ```php - * $stream->end(); - * Loop::addTimer(1.0, function () use ($stream) { - * $stream->close(); - * }); - * ``` - * - * If this stream is a `DuplexStreamInterface`, you should also notice - * how the readable side of the stream also implements a `close()` method. - * In other words, after calling this method, the stream MUST switch into - * non-writable AND non-readable mode, see also `isReadable()`. - * - * @return void - * @see ReadableStreamInterface::close() - */ - public function close(); -} diff --git a/digital_doctor/vendor/symfony/deprecation-contracts/LICENSE b/digital_doctor/vendor/symfony/deprecation-contracts/LICENSE index 0ed3a24..406242f 100644 --- a/digital_doctor/vendor/symfony/deprecation-contracts/LICENSE +++ b/digital_doctor/vendor/symfony/deprecation-contracts/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2020-present Fabien Potencier +Copyright (c) 2020-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/digital_doctor/vendor/symfony/http-foundation/AcceptHeader.php b/digital_doctor/vendor/symfony/http-foundation/AcceptHeader.php deleted file mode 100644 index 057c6b5..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/AcceptHeader.php +++ /dev/null @@ -1,168 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -// Help opcache.preload discover always-needed symbols -class_exists(AcceptHeaderItem::class); - -/** - * Represents an Accept-* header. - * - * An accept header is compound with a list of items, - * sorted by descending quality. - * - * @author Jean-François Simon - */ -class AcceptHeader -{ - /** - * @var AcceptHeaderItem[] - */ - private $items = []; - - /** - * @var bool - */ - private $sorted = true; - - /** - * @param AcceptHeaderItem[] $items - */ - public function __construct(array $items) - { - foreach ($items as $item) { - $this->add($item); - } - } - - /** - * Builds an AcceptHeader instance from a string. - * - * @return self - */ - public static function fromString(?string $headerValue) - { - $index = 0; - - $parts = HeaderUtils::split($headerValue ?? '', ',;='); - - return new self(array_map(function ($subParts) use (&$index) { - $part = array_shift($subParts); - $attributes = HeaderUtils::combine($subParts); - - $item = new AcceptHeaderItem($part[0], $attributes); - $item->setIndex($index++); - - return $item; - }, $parts)); - } - - /** - * Returns header value's string representation. - * - * @return string - */ - public function __toString() - { - return implode(',', $this->items); - } - - /** - * Tests if header has given value. - * - * @return bool - */ - public function has(string $value) - { - return isset($this->items[$value]); - } - - /** - * Returns given value's item, if exists. - * - * @return AcceptHeaderItem|null - */ - public function get(string $value) - { - return $this->items[$value] ?? $this->items[explode('/', $value)[0].'/*'] ?? $this->items['*/*'] ?? $this->items['*'] ?? null; - } - - /** - * Adds an item. - * - * @return $this - */ - public function add(AcceptHeaderItem $item) - { - $this->items[$item->getValue()] = $item; - $this->sorted = false; - - return $this; - } - - /** - * Returns all items. - * - * @return AcceptHeaderItem[] - */ - public function all() - { - $this->sort(); - - return $this->items; - } - - /** - * Filters items on their value using given regex. - * - * @return self - */ - public function filter(string $pattern) - { - return new self(array_filter($this->items, function (AcceptHeaderItem $item) use ($pattern) { - return preg_match($pattern, $item->getValue()); - })); - } - - /** - * Returns first item. - * - * @return AcceptHeaderItem|null - */ - public function first() - { - $this->sort(); - - return !empty($this->items) ? reset($this->items) : null; - } - - /** - * Sorts items by descending quality. - */ - private function sort(): void - { - if (!$this->sorted) { - uasort($this->items, function (AcceptHeaderItem $a, AcceptHeaderItem $b) { - $qA = $a->getQuality(); - $qB = $b->getQuality(); - - if ($qA === $qB) { - return $a->getIndex() > $b->getIndex() ? 1 : -1; - } - - return $qA > $qB ? -1 : 1; - }); - - $this->sorted = true; - } - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/AcceptHeaderItem.php b/digital_doctor/vendor/symfony/http-foundation/AcceptHeaderItem.php deleted file mode 100644 index 8b86eee..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/AcceptHeaderItem.php +++ /dev/null @@ -1,177 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * Represents an Accept-* header item. - * - * @author Jean-François Simon - */ -class AcceptHeaderItem -{ - private $value; - private $quality = 1.0; - private $index = 0; - private $attributes = []; - - public function __construct(string $value, array $attributes = []) - { - $this->value = $value; - foreach ($attributes as $name => $value) { - $this->setAttribute($name, $value); - } - } - - /** - * Builds an AcceptHeaderInstance instance from a string. - * - * @return self - */ - public static function fromString(?string $itemValue) - { - $parts = HeaderUtils::split($itemValue ?? '', ';='); - - $part = array_shift($parts); - $attributes = HeaderUtils::combine($parts); - - return new self($part[0], $attributes); - } - - /** - * Returns header value's string representation. - * - * @return string - */ - public function __toString() - { - $string = $this->value.($this->quality < 1 ? ';q='.$this->quality : ''); - if (\count($this->attributes) > 0) { - $string .= '; '.HeaderUtils::toString($this->attributes, ';'); - } - - return $string; - } - - /** - * Set the item value. - * - * @return $this - */ - public function setValue(string $value) - { - $this->value = $value; - - return $this; - } - - /** - * Returns the item value. - * - * @return string - */ - public function getValue() - { - return $this->value; - } - - /** - * Set the item quality. - * - * @return $this - */ - public function setQuality(float $quality) - { - $this->quality = $quality; - - return $this; - } - - /** - * Returns the item quality. - * - * @return float - */ - public function getQuality() - { - return $this->quality; - } - - /** - * Set the item index. - * - * @return $this - */ - public function setIndex(int $index) - { - $this->index = $index; - - return $this; - } - - /** - * Returns the item index. - * - * @return int - */ - public function getIndex() - { - return $this->index; - } - - /** - * Tests if an attribute exists. - * - * @return bool - */ - public function hasAttribute(string $name) - { - return isset($this->attributes[$name]); - } - - /** - * Returns an attribute by its name. - * - * @param mixed $default - * - * @return mixed - */ - public function getAttribute(string $name, $default = null) - { - return $this->attributes[$name] ?? $default; - } - - /** - * Returns all attributes. - * - * @return array - */ - public function getAttributes() - { - return $this->attributes; - } - - /** - * Set an attribute. - * - * @return $this - */ - public function setAttribute(string $name, string $value) - { - if ('q' === $name) { - $this->quality = (float) $value; - } else { - $this->attributes[$name] = $value; - } - - return $this; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/BinaryFileResponse.php b/digital_doctor/vendor/symfony/http-foundation/BinaryFileResponse.php deleted file mode 100644 index 1878caa..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/BinaryFileResponse.php +++ /dev/null @@ -1,414 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -use Symfony\Component\HttpFoundation\File\Exception\FileException; -use Symfony\Component\HttpFoundation\File\File; - -/** - * BinaryFileResponse represents an HTTP response delivering a file. - * - * @author Niklas Fiekas - * @author stealth35 - * @author Igor Wiedler - * @author Jordan Alliot - * @author Sergey Linnik - */ -class BinaryFileResponse extends Response -{ - protected static $trustXSendfileTypeHeader = false; - - /** - * @var File - */ - protected $file; - protected $offset = 0; - protected $maxlen = -1; - protected $deleteFileAfterSend = false; - protected $chunkSize = 16 * 1024; - - /** - * @param \SplFileInfo|string $file The file to stream - * @param int $status The response status code - * @param array $headers An array of response headers - * @param bool $public Files are public by default - * @param string|null $contentDisposition The type of Content-Disposition to set automatically with the filename - * @param bool $autoEtag Whether the ETag header should be automatically set - * @param bool $autoLastModified Whether the Last-Modified header should be automatically set - */ - public function __construct($file, int $status = 200, array $headers = [], bool $public = true, ?string $contentDisposition = null, bool $autoEtag = false, bool $autoLastModified = true) - { - parent::__construct(null, $status, $headers); - - $this->setFile($file, $contentDisposition, $autoEtag, $autoLastModified); - - if ($public) { - $this->setPublic(); - } - } - - /** - * @param \SplFileInfo|string $file The file to stream - * @param int $status The response status code - * @param array $headers An array of response headers - * @param bool $public Files are public by default - * @param string|null $contentDisposition The type of Content-Disposition to set automatically with the filename - * @param bool $autoEtag Whether the ETag header should be automatically set - * @param bool $autoLastModified Whether the Last-Modified header should be automatically set - * - * @return static - * - * @deprecated since Symfony 5.2, use __construct() instead. - */ - public static function create($file = null, int $status = 200, array $headers = [], bool $public = true, ?string $contentDisposition = null, bool $autoEtag = false, bool $autoLastModified = true) - { - trigger_deprecation('symfony/http-foundation', '5.2', 'The "%s()" method is deprecated, use "new %s()" instead.', __METHOD__, static::class); - - return new static($file, $status, $headers, $public, $contentDisposition, $autoEtag, $autoLastModified); - } - - /** - * Sets the file to stream. - * - * @param \SplFileInfo|string $file The file to stream - * - * @return $this - * - * @throws FileException - */ - public function setFile($file, ?string $contentDisposition = null, bool $autoEtag = false, bool $autoLastModified = true) - { - if (!$file instanceof File) { - if ($file instanceof \SplFileInfo) { - $file = new File($file->getPathname()); - } else { - $file = new File((string) $file); - } - } - - if (!$file->isReadable()) { - throw new FileException('File must be readable.'); - } - - $this->file = $file; - - if ($autoEtag) { - $this->setAutoEtag(); - } - - if ($autoLastModified) { - $this->setAutoLastModified(); - } - - if ($contentDisposition) { - $this->setContentDisposition($contentDisposition); - } - - return $this; - } - - /** - * Gets the file. - * - * @return File - */ - public function getFile() - { - return $this->file; - } - - /** - * Sets the response stream chunk size. - * - * @return $this - */ - public function setChunkSize(int $chunkSize): self - { - if ($chunkSize < 1 || $chunkSize > \PHP_INT_MAX) { - throw new \LogicException('The chunk size of a BinaryFileResponse cannot be less than 1 or greater than PHP_INT_MAX.'); - } - - $this->chunkSize = $chunkSize; - - return $this; - } - - /** - * Automatically sets the Last-Modified header according the file modification date. - * - * @return $this - */ - public function setAutoLastModified() - { - $this->setLastModified(\DateTime::createFromFormat('U', $this->file->getMTime())); - - return $this; - } - - /** - * Automatically sets the ETag header according to the checksum of the file. - * - * @return $this - */ - public function setAutoEtag() - { - $this->setEtag(base64_encode(hash_file('sha256', $this->file->getPathname(), true))); - - return $this; - } - - /** - * Sets the Content-Disposition header with the given filename. - * - * @param string $disposition ResponseHeaderBag::DISPOSITION_INLINE or ResponseHeaderBag::DISPOSITION_ATTACHMENT - * @param string $filename Optionally use this UTF-8 encoded filename instead of the real name of the file - * @param string $filenameFallback A fallback filename, containing only ASCII characters. Defaults to an automatically encoded filename - * - * @return $this - */ - public function setContentDisposition(string $disposition, string $filename = '', string $filenameFallback = '') - { - if ('' === $filename) { - $filename = $this->file->getFilename(); - } - - if ('' === $filenameFallback && (!preg_match('/^[\x20-\x7e]*$/', $filename) || str_contains($filename, '%'))) { - $encoding = mb_detect_encoding($filename, null, true) ?: '8bit'; - - for ($i = 0, $filenameLength = mb_strlen($filename, $encoding); $i < $filenameLength; ++$i) { - $char = mb_substr($filename, $i, 1, $encoding); - - if ('%' === $char || \ord($char) < 32 || \ord($char) > 126) { - $filenameFallback .= '_'; - } else { - $filenameFallback .= $char; - } - } - } - - $dispositionHeader = $this->headers->makeDisposition($disposition, $filename, $filenameFallback); - $this->headers->set('Content-Disposition', $dispositionHeader); - - return $this; - } - - /** - * {@inheritdoc} - */ - public function prepare(Request $request) - { - if ($this->isInformational() || $this->isEmpty()) { - parent::prepare($request); - - $this->maxlen = 0; - - return $this; - } - - if (!$this->headers->has('Content-Type')) { - $this->headers->set('Content-Type', $this->file->getMimeType() ?: 'application/octet-stream'); - } - - parent::prepare($request); - - $this->offset = 0; - $this->maxlen = -1; - - if (false === $fileSize = $this->file->getSize()) { - return $this; - } - $this->headers->remove('Transfer-Encoding'); - $this->headers->set('Content-Length', $fileSize); - - if (!$this->headers->has('Accept-Ranges')) { - // Only accept ranges on safe HTTP methods - $this->headers->set('Accept-Ranges', $request->isMethodSafe() ? 'bytes' : 'none'); - } - - if (self::$trustXSendfileTypeHeader && $request->headers->has('X-Sendfile-Type')) { - // Use X-Sendfile, do not send any content. - $type = $request->headers->get('X-Sendfile-Type'); - $path = $this->file->getRealPath(); - // Fall back to scheme://path for stream wrapped locations. - if (false === $path) { - $path = $this->file->getPathname(); - } - if ('x-accel-redirect' === strtolower($type)) { - // Do X-Accel-Mapping substitutions. - // @link https://www.nginx.com/resources/wiki/start/topics/examples/x-accel/#x-accel-redirect - $parts = HeaderUtils::split($request->headers->get('X-Accel-Mapping', ''), ',='); - foreach ($parts as $part) { - [$pathPrefix, $location] = $part; - if (substr($path, 0, \strlen($pathPrefix)) === $pathPrefix) { - $path = $location.substr($path, \strlen($pathPrefix)); - // Only set X-Accel-Redirect header if a valid URI can be produced - // as nginx does not serve arbitrary file paths. - $this->headers->set($type, $path); - $this->maxlen = 0; - break; - } - } - } else { - $this->headers->set($type, $path); - $this->maxlen = 0; - } - } elseif ($request->headers->has('Range') && $request->isMethod('GET')) { - // Process the range headers. - if (!$request->headers->has('If-Range') || $this->hasValidIfRangeHeader($request->headers->get('If-Range'))) { - $range = $request->headers->get('Range'); - - if (str_starts_with($range, 'bytes=')) { - [$start, $end] = explode('-', substr($range, 6), 2) + [1 => 0]; - - $end = ('' === $end) ? $fileSize - 1 : (int) $end; - - if ('' === $start) { - $start = $fileSize - $end; - $end = $fileSize - 1; - } else { - $start = (int) $start; - } - - if ($start <= $end) { - $end = min($end, $fileSize - 1); - if ($start < 0 || $start > $end) { - $this->setStatusCode(416); - $this->headers->set('Content-Range', sprintf('bytes */%s', $fileSize)); - } elseif ($end - $start < $fileSize - 1) { - $this->maxlen = $end < $fileSize ? $end - $start + 1 : -1; - $this->offset = $start; - - $this->setStatusCode(206); - $this->headers->set('Content-Range', sprintf('bytes %s-%s/%s', $start, $end, $fileSize)); - $this->headers->set('Content-Length', $end - $start + 1); - } - } - } - } - } - - if ($request->isMethod('HEAD')) { - $this->maxlen = 0; - } - - return $this; - } - - private function hasValidIfRangeHeader(?string $header): bool - { - if ($this->getEtag() === $header) { - return true; - } - - if (null === $lastModified = $this->getLastModified()) { - return false; - } - - return $lastModified->format('D, d M Y H:i:s').' GMT' === $header; - } - - /** - * {@inheritdoc} - */ - public function sendContent() - { - try { - if (!$this->isSuccessful()) { - return parent::sendContent(); - } - - if (0 === $this->maxlen) { - return $this; - } - - $out = fopen('php://output', 'w'); - $file = fopen($this->file->getPathname(), 'r'); - - ignore_user_abort(true); - - if (0 !== $this->offset) { - fseek($file, $this->offset); - } - - $length = $this->maxlen; - while ($length && !feof($file)) { - $read = $length > $this->chunkSize || 0 > $length ? $this->chunkSize : $length; - - if (false === $data = fread($file, $read)) { - break; - } - while ('' !== $data) { - $read = fwrite($out, $data); - if (false === $read || connection_aborted()) { - break 2; - } - if (0 < $length) { - $length -= $read; - } - $data = substr($data, $read); - } - } - - fclose($out); - fclose($file); - } finally { - if ($this->deleteFileAfterSend && is_file($this->file->getPathname())) { - unlink($this->file->getPathname()); - } - } - - return $this; - } - - /** - * {@inheritdoc} - * - * @throws \LogicException when the content is not null - */ - public function setContent(?string $content) - { - if (null !== $content) { - throw new \LogicException('The content cannot be set on a BinaryFileResponse instance.'); - } - - return $this; - } - - /** - * {@inheritdoc} - */ - public function getContent() - { - return false; - } - - /** - * Trust X-Sendfile-Type header. - */ - public static function trustXSendfileTypeHeader() - { - self::$trustXSendfileTypeHeader = true; - } - - /** - * If this is set to true, the file will be unlinked after the request is sent - * Note: If the X-Sendfile header is used, the deleteFileAfterSend setting will not be used. - * - * @return $this - */ - public function deleteFileAfterSend(bool $shouldDelete = true) - { - $this->deleteFileAfterSend = $shouldDelete; - - return $this; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/CHANGELOG.md b/digital_doctor/vendor/symfony/http-foundation/CHANGELOG.md deleted file mode 100644 index ad7607a..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/CHANGELOG.md +++ /dev/null @@ -1,296 +0,0 @@ -CHANGELOG -========= - -5.4 ---- - - * Deprecate passing `null` as `$requestIp` to `IpUtils::__checkIp()`, `IpUtils::__checkIp4()` or `IpUtils::__checkIp6()`, pass an empty string instead. - * Add the `litespeed_finish_request` method to work with Litespeed - * Deprecate `upload_progress.*` and `url_rewriter.tags` session options - * Allow setting session options via DSN - -5.3 ---- - - * Add the `SessionFactory`, `NativeSessionStorageFactory`, `PhpBridgeSessionStorageFactory` and `MockFileSessionStorageFactory` classes - * Calling `Request::getSession()` when there is no available session throws a `SessionNotFoundException` - * Add the `RequestStack::getSession` method - * Deprecate the `NamespacedAttributeBag` class - * Add `ResponseFormatSame` PHPUnit constraint - * Deprecate the `RequestStack::getMasterRequest()` method and add `getMainRequest()` as replacement - -5.2.0 ------ - - * added support for `X-Forwarded-Prefix` header - * added `HeaderUtils::parseQuery()`: it does the same as `parse_str()` but preserves dots in variable names - * added `File::getContent()` - * added ability to use comma separated ip addresses for `RequestMatcher::matchIps()` - * added `Request::toArray()` to parse a JSON request body to an array - * added `RateLimiter\RequestRateLimiterInterface` and `RateLimiter\AbstractRequestRateLimiter` - * deprecated not passing a `Closure` together with `FILTER_CALLBACK` to `ParameterBag::filter()`; wrap your filter in a closure instead. - * Deprecated the `Request::HEADER_X_FORWARDED_ALL` constant, use either `HEADER_X_FORWARDED_FOR | HEADER_X_FORWARDED_HOST | HEADER_X_FORWARDED_PORT | HEADER_X_FORWARDED_PROTO` or `HEADER_X_FORWARDED_AWS_ELB` or `HEADER_X_FORWARDED_TRAEFIK` constants instead. - * Deprecated `BinaryFileResponse::create()`, use `__construct()` instead - -5.1.0 ------ - - * added `Cookie::withValue`, `Cookie::withDomain`, `Cookie::withExpires`, - `Cookie::withPath`, `Cookie::withSecure`, `Cookie::withHttpOnly`, - `Cookie::withRaw`, `Cookie::withSameSite` - * Deprecate `Response::create()`, `JsonResponse::create()`, - `RedirectResponse::create()`, and `StreamedResponse::create()` methods (use - `__construct()` instead) - * added `Request::preferSafeContent()` and `Response::setContentSafe()` to handle "safe" HTTP preference - according to [RFC 8674](https://tools.ietf.org/html/rfc8674) - * made the Mime component an optional dependency - * added `MarshallingSessionHandler`, `IdentityMarshaller` - * made `Session` accept a callback to report when the session is being used - * Add support for all core cache control directives - * Added `Symfony\Component\HttpFoundation\InputBag` - * Deprecated retrieving non-string values using `InputBag::get()`, use `InputBag::all()` if you need access to the collection of values - -5.0.0 ------ - - * made `Cookie` auto-secure and lax by default - * removed classes in the `MimeType` namespace, use the Symfony Mime component instead - * removed method `UploadedFile::getClientSize()` and the related constructor argument - * made `Request::getSession()` throw if the session has not been set before - * removed `Response::HTTP_RESERVED_FOR_WEBDAV_ADVANCED_COLLECTIONS_EXPIRED_PROPOSAL` - * passing a null url when instantiating a `RedirectResponse` is not allowed - -4.4.0 ------ - - * passing arguments to `Request::isMethodSafe()` is deprecated. - * `ApacheRequest` is deprecated, use the `Request` class instead. - * passing a third argument to `HeaderBag::get()` is deprecated, use method `all()` instead - * [BC BREAK] `PdoSessionHandler` with MySQL changed the type of the lifetime column, - make sure to run `ALTER TABLE sessions MODIFY sess_lifetime INTEGER UNSIGNED NOT NULL` to - update your database. - * `PdoSessionHandler` now precalculates the expiry timestamp in the lifetime column, - make sure to run `CREATE INDEX EXPIRY ON sessions (sess_lifetime)` to update your database - to speed up garbage collection of expired sessions. - * added `SessionHandlerFactory` to create session handlers with a DSN - * added `IpUtils::anonymize()` to help with GDPR compliance. - -4.3.0 ------ - - * added PHPUnit constraints: `RequestAttributeValueSame`, `ResponseCookieValueSame`, `ResponseHasCookie`, - `ResponseHasHeader`, `ResponseHeaderSame`, `ResponseIsRedirected`, `ResponseIsSuccessful`, and `ResponseStatusCodeSame` - * deprecated `MimeTypeGuesserInterface` and `ExtensionGuesserInterface` in favor of `Symfony\Component\Mime\MimeTypesInterface`. - * deprecated `MimeType` and `MimeTypeExtensionGuesser` in favor of `Symfony\Component\Mime\MimeTypes`. - * deprecated `FileBinaryMimeTypeGuesser` in favor of `Symfony\Component\Mime\FileBinaryMimeTypeGuesser`. - * deprecated `FileinfoMimeTypeGuesser` in favor of `Symfony\Component\Mime\FileinfoMimeTypeGuesser`. - * added `UrlHelper` that allows to get an absolute URL and a relative path for a given path - -4.2.0 ------ - - * the default value of the "$secure" and "$samesite" arguments of Cookie's constructor - will respectively change from "false" to "null" and from "null" to "lax" in Symfony - 5.0, you should define their values explicitly or use "Cookie::create()" instead. - * added `matchPort()` in RequestMatcher - -4.1.3 ------ - - * [BC BREAK] Support for the IIS-only `X_ORIGINAL_URL` and `X_REWRITE_URL` - HTTP headers has been dropped for security reasons. - -4.1.0 ------ - - * Query string normalization uses `parse_str()` instead of custom parsing logic. - * Passing the file size to the constructor of the `UploadedFile` class is deprecated. - * The `getClientSize()` method of the `UploadedFile` class is deprecated. Use `getSize()` instead. - * added `RedisSessionHandler` to use Redis as a session storage - * The `get()` method of the `AcceptHeader` class now takes into account the - `*` and `*/*` default values (if they are present in the Accept HTTP header) - when looking for items. - * deprecated `Request::getSession()` when no session has been set. Use `Request::hasSession()` instead. - * added `CannotWriteFileException`, `ExtensionFileException`, `FormSizeFileException`, - `IniSizeFileException`, `NoFileException`, `NoTmpDirFileException`, `PartialFileException` to - handle failed `UploadedFile`. - * added `MigratingSessionHandler` for migrating between two session handlers without losing sessions - * added `HeaderUtils`. - -4.0.0 ------ - - * the `Request::setTrustedHeaderName()` and `Request::getTrustedHeaderName()` - methods have been removed - * the `Request::HEADER_CLIENT_IP` constant has been removed, use - `Request::HEADER_X_FORWARDED_FOR` instead - * the `Request::HEADER_CLIENT_HOST` constant has been removed, use - `Request::HEADER_X_FORWARDED_HOST` instead - * the `Request::HEADER_CLIENT_PROTO` constant has been removed, use - `Request::HEADER_X_FORWARDED_PROTO` instead - * the `Request::HEADER_CLIENT_PORT` constant has been removed, use - `Request::HEADER_X_FORWARDED_PORT` instead - * checking for cacheable HTTP methods using the `Request::isMethodSafe()` - method (by not passing `false` as its argument) is not supported anymore and - throws a `\BadMethodCallException` - * the `WriteCheckSessionHandler`, `NativeSessionHandler` and `NativeProxy` classes have been removed - * setting session save handlers that do not implement `\SessionHandlerInterface` in - `NativeSessionStorage::setSaveHandler()` is not supported anymore and throws a - `\TypeError` - -3.4.0 ------ - - * implemented PHP 7.0's `SessionUpdateTimestampHandlerInterface` with a new - `AbstractSessionHandler` base class and a new `StrictSessionHandler` wrapper - * deprecated the `WriteCheckSessionHandler`, `NativeSessionHandler` and `NativeProxy` classes - * deprecated setting session save handlers that do not implement `\SessionHandlerInterface` in `NativeSessionStorage::setSaveHandler()` - * deprecated using `MongoDbSessionHandler` with the legacy mongo extension; use it with the mongodb/mongodb package and ext-mongodb instead - * deprecated `MemcacheSessionHandler`; use `MemcachedSessionHandler` instead - -3.3.0 ------ - - * the `Request::setTrustedProxies()` method takes a new `$trustedHeaderSet` argument, - see https://symfony.com/doc/current/deployment/proxies.html for more info, - * deprecated the `Request::setTrustedHeaderName()` and `Request::getTrustedHeaderName()` methods, - * added `File\Stream`, to be passed to `BinaryFileResponse` when the size of the served file is unknown, - disabling `Range` and `Content-Length` handling, switching to chunked encoding instead - * added the `Cookie::fromString()` method that allows to create a cookie from a - raw header string - -3.1.0 ------ - - * Added support for creating `JsonResponse` with a string of JSON data - -3.0.0 ------ - - * The precedence of parameters returned from `Request::get()` changed from "GET, PATH, BODY" to "PATH, GET, BODY" - -2.8.0 ------ - - * Finding deep items in `ParameterBag::get()` is deprecated since version 2.8 and - will be removed in 3.0. - -2.6.0 ------ - - * PdoSessionHandler changes - - implemented different session locking strategies to prevent loss of data by concurrent access to the same session - - [BC BREAK] save session data in a binary column without base64_encode - - [BC BREAK] added lifetime column to the session table which allows to have different lifetimes for each session - - implemented lazy connections that are only opened when a session is used by either passing a dsn string - explicitly or falling back to session.save_path ini setting - - added a createTable method that initializes a correctly defined table depending on the database vendor - -2.5.0 ------ - - * added `JsonResponse::setEncodingOptions()` & `JsonResponse::getEncodingOptions()` for easier manipulation - of the options used while encoding data to JSON format. - -2.4.0 ------ - - * added RequestStack - * added Request::getEncodings() - * added accessors methods to session handlers - -2.3.0 ------ - - * added support for ranges of IPs in trusted proxies - * `UploadedFile::isValid` now returns false if the file was not uploaded via HTTP (in a non-test mode) - * Improved error-handling of `\Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler` - to ensure the supplied PDO handler throws Exceptions on error (as the class expects). Added related test cases - to verify that Exceptions are properly thrown when the PDO queries fail. - -2.2.0 ------ - - * fixed the Request::create() precedence (URI information always take precedence now) - * added Request::getTrustedProxies() - * deprecated Request::isProxyTrusted() - * [BC BREAK] JsonResponse does not turn a top level empty array to an object anymore, use an ArrayObject to enforce objects - * added a IpUtils class to check if an IP belongs to a CIDR - * added Request::getRealMethod() to get the "real" HTTP method (getMethod() returns the "intended" HTTP method) - * disabled _method request parameter support by default (call Request::enableHttpMethodParameterOverride() to - enable it, and Request::getHttpMethodParameterOverride() to check if it is supported) - * Request::splitHttpAcceptHeader() method is deprecated and will be removed in 2.3 - * Deprecated Flashbag::count() and \Countable interface, will be removed in 2.3 - -2.1.0 ------ - - * added Request::getSchemeAndHttpHost() and Request::getUserInfo() - * added a fluent interface to the Response class - * added Request::isProxyTrusted() - * added JsonResponse - * added a getTargetUrl method to RedirectResponse - * added support for streamed responses - * made Response::prepare() method the place to enforce HTTP specification - * [BC BREAK] moved management of the locale from the Session class to the Request class - * added a generic access to the PHP built-in filter mechanism: ParameterBag::filter() - * made FileBinaryMimeTypeGuesser command configurable - * added Request::getUser() and Request::getPassword() - * added support for the PATCH method in Request - * removed the ContentTypeMimeTypeGuesser class as it is deprecated and never used on PHP 5.3 - * added ResponseHeaderBag::makeDisposition() (implements RFC 6266) - * made mimetype to extension conversion configurable - * [BC BREAK] Moved all session related classes and interfaces into own namespace, as - `Symfony\Component\HttpFoundation\Session` and renamed classes accordingly. - Session handlers are located in the subnamespace `Symfony\Component\HttpFoundation\Session\Handler`. - * SessionHandlers must implement `\SessionHandlerInterface` or extend from the - `Symfony\Component\HttpFoundation\Storage\Handler\NativeSessionHandler` base class. - * Added internal storage driver proxy mechanism for forward compatibility with - PHP 5.4 `\SessionHandler` class. - * Added session handlers for custom Memcache, Memcached and Null session save handlers. - * [BC BREAK] Removed `NativeSessionStorage` and replaced with `NativeFileSessionHandler`. - * [BC BREAK] `SessionStorageInterface` methods removed: `write()`, `read()` and - `remove()`. Added `getBag()`, `registerBag()`. The `NativeSessionStorage` class - is a mediator for the session storage internals including the session handlers - which do the real work of participating in the internal PHP session workflow. - * [BC BREAK] Introduced mock implementations of `SessionStorage` to enable unit - and functional testing without starting real PHP sessions. Removed - `ArraySessionStorage`, and replaced with `MockArraySessionStorage` for unit - tests; removed `FilesystemSessionStorage`, and replaced with`MockFileSessionStorage` - for functional tests. These do not interact with global session ini - configuration values, session functions or `$_SESSION` superglobal. This means - they can be configured directly allowing multiple instances to work without - conflicting in the same PHP process. - * [BC BREAK] Removed the `close()` method from the `Session` class, as this is - now redundant. - * Deprecated the following methods from the Session class: `setFlash()`, `setFlashes()` - `getFlash()`, `hasFlash()`, and `removeFlash()`. Use `getFlashBag()` instead - which returns a `FlashBagInterface`. - * `Session->clear()` now only clears session attributes as before it cleared - flash messages and attributes. `Session->getFlashBag()->all()` clears flashes now. - * Session data is now managed by `SessionBagInterface` to better encapsulate - session data. - * Refactored session attribute and flash messages system to their own - `SessionBagInterface` implementations. - * Added `FlashBag`. Flashes expire when retrieved by `get()` or `all()`. This - implementation is ESI compatible. - * Added `AutoExpireFlashBag` (default) to replicate Symfony 2.0.x auto expire - behavior of messages auto expiring after one page page load. Messages must - be retrieved by `get()` or `all()`. - * Added `Symfony\Component\HttpFoundation\Attribute\AttributeBag` to replicate - attributes storage behavior from 2.0.x (default). - * Added `Symfony\Component\HttpFoundation\Attribute\NamespacedAttributeBag` for - namespace session attributes. - * Flash API can stores messages in an array so there may be multiple messages - per flash type. The old `Session` class API remains without BC break as it - will allow single messages as before. - * Added basic session meta-data to the session to record session create time, - last updated time, and the lifetime of the session cookie that was provided - to the client. - * Request::getClientIp() method doesn't take a parameter anymore but bases - itself on the trustProxy parameter. - * Added isMethod() to Request object. - * [BC BREAK] The methods `getPathInfo()`, `getBaseUrl()` and `getBasePath()` of - a `Request` now all return a raw value (vs a urldecoded value before). Any call - to one of these methods must be checked and wrapped in a `rawurldecode()` if - needed. diff --git a/digital_doctor/vendor/symfony/http-foundation/Cookie.php b/digital_doctor/vendor/symfony/http-foundation/Cookie.php deleted file mode 100644 index 3ff93b9..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Cookie.php +++ /dev/null @@ -1,422 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * Represents a cookie. - * - * @author Johannes M. Schmitt - */ -class Cookie -{ - public const SAMESITE_NONE = 'none'; - public const SAMESITE_LAX = 'lax'; - public const SAMESITE_STRICT = 'strict'; - - protected $name; - protected $value; - protected $domain; - protected $expire; - protected $path; - protected $secure; - protected $httpOnly; - - private $raw; - private $sameSite; - private $secureDefault = false; - - private const RESERVED_CHARS_LIST = "=,; \t\r\n\v\f"; - private const RESERVED_CHARS_FROM = ['=', ',', ';', ' ', "\t", "\r", "\n", "\v", "\f"]; - private const RESERVED_CHARS_TO = ['%3D', '%2C', '%3B', '%20', '%09', '%0D', '%0A', '%0B', '%0C']; - - /** - * Creates cookie from raw header string. - * - * @return static - */ - public static function fromString(string $cookie, bool $decode = false) - { - $data = [ - 'expires' => 0, - 'path' => '/', - 'domain' => null, - 'secure' => false, - 'httponly' => false, - 'raw' => !$decode, - 'samesite' => null, - ]; - - $parts = HeaderUtils::split($cookie, ';='); - $part = array_shift($parts); - - $name = $decode ? urldecode($part[0]) : $part[0]; - $value = isset($part[1]) ? ($decode ? urldecode($part[1]) : $part[1]) : null; - - $data = HeaderUtils::combine($parts) + $data; - $data['expires'] = self::expiresTimestamp($data['expires']); - - if (isset($data['max-age']) && ($data['max-age'] > 0 || $data['expires'] > time())) { - $data['expires'] = time() + (int) $data['max-age']; - } - - return new static($name, $value, $data['expires'], $data['path'], $data['domain'], $data['secure'], $data['httponly'], $data['raw'], $data['samesite']); - } - - public static function create(string $name, ?string $value = null, $expire = 0, ?string $path = '/', ?string $domain = null, ?bool $secure = null, bool $httpOnly = true, bool $raw = false, ?string $sameSite = self::SAMESITE_LAX): self - { - return new self($name, $value, $expire, $path, $domain, $secure, $httpOnly, $raw, $sameSite); - } - - /** - * @param string $name The name of the cookie - * @param string|null $value The value of the cookie - * @param int|string|\DateTimeInterface $expire The time the cookie expires - * @param string|null $path The path on the server in which the cookie will be available on - * @param string|null $domain The domain that the cookie is available to - * @param bool|null $secure Whether the client should send back the cookie only over HTTPS or null to auto-enable this when the request is already using HTTPS - * @param bool $httpOnly Whether the cookie will be made accessible only through the HTTP protocol - * @param bool $raw Whether the cookie value should be sent with no url encoding - * @param string|null $sameSite Whether the cookie will be available for cross-site requests - * - * @throws \InvalidArgumentException - */ - public function __construct(string $name, ?string $value = null, $expire = 0, ?string $path = '/', ?string $domain = null, ?bool $secure = null, bool $httpOnly = true, bool $raw = false, ?string $sameSite = 'lax') - { - // from PHP source code - if ($raw && false !== strpbrk($name, self::RESERVED_CHARS_LIST)) { - throw new \InvalidArgumentException(sprintf('The cookie name "%s" contains invalid characters.', $name)); - } - - if (empty($name)) { - throw new \InvalidArgumentException('The cookie name cannot be empty.'); - } - - $this->name = $name; - $this->value = $value; - $this->domain = $domain; - $this->expire = self::expiresTimestamp($expire); - $this->path = empty($path) ? '/' : $path; - $this->secure = $secure; - $this->httpOnly = $httpOnly; - $this->raw = $raw; - $this->sameSite = $this->withSameSite($sameSite)->sameSite; - } - - /** - * Creates a cookie copy with a new value. - * - * @return static - */ - public function withValue(?string $value): self - { - $cookie = clone $this; - $cookie->value = $value; - - return $cookie; - } - - /** - * Creates a cookie copy with a new domain that the cookie is available to. - * - * @return static - */ - public function withDomain(?string $domain): self - { - $cookie = clone $this; - $cookie->domain = $domain; - - return $cookie; - } - - /** - * Creates a cookie copy with a new time the cookie expires. - * - * @param int|string|\DateTimeInterface $expire - * - * @return static - */ - public function withExpires($expire = 0): self - { - $cookie = clone $this; - $cookie->expire = self::expiresTimestamp($expire); - - return $cookie; - } - - /** - * Converts expires formats to a unix timestamp. - * - * @param int|string|\DateTimeInterface $expire - */ - private static function expiresTimestamp($expire = 0): int - { - // convert expiration time to a Unix timestamp - if ($expire instanceof \DateTimeInterface) { - $expire = $expire->format('U'); - } elseif (!is_numeric($expire)) { - $expire = strtotime($expire); - - if (false === $expire) { - throw new \InvalidArgumentException('The cookie expiration time is not valid.'); - } - } - - return 0 < $expire ? (int) $expire : 0; - } - - /** - * Creates a cookie copy with a new path on the server in which the cookie will be available on. - * - * @return static - */ - public function withPath(string $path): self - { - $cookie = clone $this; - $cookie->path = '' === $path ? '/' : $path; - - return $cookie; - } - - /** - * Creates a cookie copy that only be transmitted over a secure HTTPS connection from the client. - * - * @return static - */ - public function withSecure(bool $secure = true): self - { - $cookie = clone $this; - $cookie->secure = $secure; - - return $cookie; - } - - /** - * Creates a cookie copy that be accessible only through the HTTP protocol. - * - * @return static - */ - public function withHttpOnly(bool $httpOnly = true): self - { - $cookie = clone $this; - $cookie->httpOnly = $httpOnly; - - return $cookie; - } - - /** - * Creates a cookie copy that uses no url encoding. - * - * @return static - */ - public function withRaw(bool $raw = true): self - { - if ($raw && false !== strpbrk($this->name, self::RESERVED_CHARS_LIST)) { - throw new \InvalidArgumentException(sprintf('The cookie name "%s" contains invalid characters.', $this->name)); - } - - $cookie = clone $this; - $cookie->raw = $raw; - - return $cookie; - } - - /** - * Creates a cookie copy with SameSite attribute. - * - * @return static - */ - public function withSameSite(?string $sameSite): self - { - if ('' === $sameSite) { - $sameSite = null; - } elseif (null !== $sameSite) { - $sameSite = strtolower($sameSite); - } - - if (!\in_array($sameSite, [self::SAMESITE_LAX, self::SAMESITE_STRICT, self::SAMESITE_NONE, null], true)) { - throw new \InvalidArgumentException('The "sameSite" parameter value is not valid.'); - } - - $cookie = clone $this; - $cookie->sameSite = $sameSite; - - return $cookie; - } - - /** - * Returns the cookie as a string. - * - * @return string - */ - public function __toString() - { - if ($this->isRaw()) { - $str = $this->getName(); - } else { - $str = str_replace(self::RESERVED_CHARS_FROM, self::RESERVED_CHARS_TO, $this->getName()); - } - - $str .= '='; - - if ('' === (string) $this->getValue()) { - $str .= 'deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; Max-Age=0'; - } else { - $str .= $this->isRaw() ? $this->getValue() : rawurlencode($this->getValue()); - - if (0 !== $this->getExpiresTime()) { - $str .= '; expires='.gmdate('D, d-M-Y H:i:s T', $this->getExpiresTime()).'; Max-Age='.$this->getMaxAge(); - } - } - - if ($this->getPath()) { - $str .= '; path='.$this->getPath(); - } - - if ($this->getDomain()) { - $str .= '; domain='.$this->getDomain(); - } - - if (true === $this->isSecure()) { - $str .= '; secure'; - } - - if (true === $this->isHttpOnly()) { - $str .= '; httponly'; - } - - if (null !== $this->getSameSite()) { - $str .= '; samesite='.$this->getSameSite(); - } - - return $str; - } - - /** - * Gets the name of the cookie. - * - * @return string - */ - public function getName() - { - return $this->name; - } - - /** - * Gets the value of the cookie. - * - * @return string|null - */ - public function getValue() - { - return $this->value; - } - - /** - * Gets the domain that the cookie is available to. - * - * @return string|null - */ - public function getDomain() - { - return $this->domain; - } - - /** - * Gets the time the cookie expires. - * - * @return int - */ - public function getExpiresTime() - { - return $this->expire; - } - - /** - * Gets the max-age attribute. - * - * @return int - */ - public function getMaxAge() - { - $maxAge = $this->expire - time(); - - return 0 >= $maxAge ? 0 : $maxAge; - } - - /** - * Gets the path on the server in which the cookie will be available on. - * - * @return string - */ - public function getPath() - { - return $this->path; - } - - /** - * Checks whether the cookie should only be transmitted over a secure HTTPS connection from the client. - * - * @return bool - */ - public function isSecure() - { - return $this->secure ?? $this->secureDefault; - } - - /** - * Checks whether the cookie will be made accessible only through the HTTP protocol. - * - * @return bool - */ - public function isHttpOnly() - { - return $this->httpOnly; - } - - /** - * Whether this cookie is about to be cleared. - * - * @return bool - */ - public function isCleared() - { - return 0 !== $this->expire && $this->expire < time(); - } - - /** - * Checks if the cookie value should be sent with no url encoding. - * - * @return bool - */ - public function isRaw() - { - return $this->raw; - } - - /** - * Gets the SameSite attribute. - * - * @return string|null - */ - public function getSameSite() - { - return $this->sameSite; - } - - /** - * @param bool $default The default value of the "secure" flag when it is set to null - */ - public function setSecureDefault(bool $default): void - { - $this->secureDefault = $default; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Exception/BadRequestException.php b/digital_doctor/vendor/symfony/http-foundation/Exception/BadRequestException.php deleted file mode 100644 index e4bb309..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Exception/BadRequestException.php +++ /dev/null @@ -1,19 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Exception; - -/** - * Raised when a user sends a malformed request. - */ -class BadRequestException extends \UnexpectedValueException implements RequestExceptionInterface -{ -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Exception/ConflictingHeadersException.php b/digital_doctor/vendor/symfony/http-foundation/Exception/ConflictingHeadersException.php deleted file mode 100644 index 5fcf5b4..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Exception/ConflictingHeadersException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Exception; - -/** - * The HTTP request contains headers with conflicting information. - * - * @author Magnus Nordlander - */ -class ConflictingHeadersException extends \UnexpectedValueException implements RequestExceptionInterface -{ -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Exception/JsonException.php b/digital_doctor/vendor/symfony/http-foundation/Exception/JsonException.php deleted file mode 100644 index 5990e76..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Exception/JsonException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Exception; - -/** - * Thrown by Request::toArray() when the content cannot be JSON-decoded. - * - * @author Tobias Nyholm - */ -final class JsonException extends \UnexpectedValueException implements RequestExceptionInterface -{ -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Exception/RequestExceptionInterface.php b/digital_doctor/vendor/symfony/http-foundation/Exception/RequestExceptionInterface.php deleted file mode 100644 index 478d0dc..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Exception/RequestExceptionInterface.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Exception; - -/** - * Interface for Request exceptions. - * - * Exceptions implementing this interface should trigger an HTTP 400 response in the application code. - */ -interface RequestExceptionInterface -{ -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Exception/SessionNotFoundException.php b/digital_doctor/vendor/symfony/http-foundation/Exception/SessionNotFoundException.php deleted file mode 100644 index 80a21bf..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Exception/SessionNotFoundException.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Exception; - -/** - * Raised when a session does not exist. This happens in the following cases: - * - the session is not enabled - * - attempt to read a session outside a request context (ie. cli script). - * - * @author Jérémy Derussé - */ -class SessionNotFoundException extends \LogicException implements RequestExceptionInterface -{ - public function __construct(string $message = 'There is currently no session available.', int $code = 0, ?\Throwable $previous = null) - { - parent::__construct($message, $code, $previous); - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Exception/SuspiciousOperationException.php b/digital_doctor/vendor/symfony/http-foundation/Exception/SuspiciousOperationException.php deleted file mode 100644 index ae7a5f1..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Exception/SuspiciousOperationException.php +++ /dev/null @@ -1,20 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Exception; - -/** - * Raised when a user has performed an operation that should be considered - * suspicious from a security perspective. - */ -class SuspiciousOperationException extends \UnexpectedValueException implements RequestExceptionInterface -{ -} diff --git a/digital_doctor/vendor/symfony/http-foundation/ExpressionRequestMatcher.php b/digital_doctor/vendor/symfony/http-foundation/ExpressionRequestMatcher.php deleted file mode 100644 index 26bed7d..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/ExpressionRequestMatcher.php +++ /dev/null @@ -1,47 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -use Symfony\Component\ExpressionLanguage\ExpressionLanguage; - -/** - * ExpressionRequestMatcher uses an expression to match a Request. - * - * @author Fabien Potencier - */ -class ExpressionRequestMatcher extends RequestMatcher -{ - private $language; - private $expression; - - public function setExpression(ExpressionLanguage $language, $expression) - { - $this->language = $language; - $this->expression = $expression; - } - - public function matches(Request $request) - { - if (!$this->language) { - throw new \LogicException('Unable to match the request as the expression language is not available.'); - } - - return $this->language->evaluate($this->expression, [ - 'request' => $request, - 'method' => $request->getMethod(), - 'path' => rawurldecode($request->getPathInfo()), - 'host' => $request->getHost(), - 'ip' => $request->getClientIp(), - 'attributes' => $request->attributes->all(), - ]) && parent::matches($request); - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/File/Exception/AccessDeniedException.php b/digital_doctor/vendor/symfony/http-foundation/File/Exception/AccessDeniedException.php deleted file mode 100644 index 136d2a9..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/File/Exception/AccessDeniedException.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when the access on a file was denied. - * - * @author Bernhard Schussek - */ -class AccessDeniedException extends FileException -{ - public function __construct(string $path) - { - parent::__construct(sprintf('The file %s could not be accessed', $path)); - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/File/Exception/CannotWriteFileException.php b/digital_doctor/vendor/symfony/http-foundation/File/Exception/CannotWriteFileException.php deleted file mode 100644 index c49f53a..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/File/Exception/CannotWriteFileException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an UPLOAD_ERR_CANT_WRITE error occurred with UploadedFile. - * - * @author Florent Mata - */ -class CannotWriteFileException extends FileException -{ -} diff --git a/digital_doctor/vendor/symfony/http-foundation/File/Exception/ExtensionFileException.php b/digital_doctor/vendor/symfony/http-foundation/File/Exception/ExtensionFileException.php deleted file mode 100644 index ed83499..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/File/Exception/ExtensionFileException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an UPLOAD_ERR_EXTENSION error occurred with UploadedFile. - * - * @author Florent Mata - */ -class ExtensionFileException extends FileException -{ -} diff --git a/digital_doctor/vendor/symfony/http-foundation/File/Exception/FileException.php b/digital_doctor/vendor/symfony/http-foundation/File/Exception/FileException.php deleted file mode 100644 index fad5133..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/File/Exception/FileException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an error occurred in the component File. - * - * @author Bernhard Schussek - */ -class FileException extends \RuntimeException -{ -} diff --git a/digital_doctor/vendor/symfony/http-foundation/File/Exception/FileNotFoundException.php b/digital_doctor/vendor/symfony/http-foundation/File/Exception/FileNotFoundException.php deleted file mode 100644 index 31bdf68..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/File/Exception/FileNotFoundException.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when a file was not found. - * - * @author Bernhard Schussek - */ -class FileNotFoundException extends FileException -{ - public function __construct(string $path) - { - parent::__construct(sprintf('The file "%s" does not exist', $path)); - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/File/Exception/FormSizeFileException.php b/digital_doctor/vendor/symfony/http-foundation/File/Exception/FormSizeFileException.php deleted file mode 100644 index 8741be0..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/File/Exception/FormSizeFileException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an UPLOAD_ERR_FORM_SIZE error occurred with UploadedFile. - * - * @author Florent Mata - */ -class FormSizeFileException extends FileException -{ -} diff --git a/digital_doctor/vendor/symfony/http-foundation/File/Exception/IniSizeFileException.php b/digital_doctor/vendor/symfony/http-foundation/File/Exception/IniSizeFileException.php deleted file mode 100644 index c8fde61..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/File/Exception/IniSizeFileException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an UPLOAD_ERR_INI_SIZE error occurred with UploadedFile. - * - * @author Florent Mata - */ -class IniSizeFileException extends FileException -{ -} diff --git a/digital_doctor/vendor/symfony/http-foundation/File/Exception/NoFileException.php b/digital_doctor/vendor/symfony/http-foundation/File/Exception/NoFileException.php deleted file mode 100644 index 4b48cc7..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/File/Exception/NoFileException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an UPLOAD_ERR_NO_FILE error occurred with UploadedFile. - * - * @author Florent Mata - */ -class NoFileException extends FileException -{ -} diff --git a/digital_doctor/vendor/symfony/http-foundation/File/Exception/NoTmpDirFileException.php b/digital_doctor/vendor/symfony/http-foundation/File/Exception/NoTmpDirFileException.php deleted file mode 100644 index bdead2d..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/File/Exception/NoTmpDirFileException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an UPLOAD_ERR_NO_TMP_DIR error occurred with UploadedFile. - * - * @author Florent Mata - */ -class NoTmpDirFileException extends FileException -{ -} diff --git a/digital_doctor/vendor/symfony/http-foundation/File/Exception/PartialFileException.php b/digital_doctor/vendor/symfony/http-foundation/File/Exception/PartialFileException.php deleted file mode 100644 index 4641efb..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/File/Exception/PartialFileException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an UPLOAD_ERR_PARTIAL error occurred with UploadedFile. - * - * @author Florent Mata - */ -class PartialFileException extends FileException -{ -} diff --git a/digital_doctor/vendor/symfony/http-foundation/File/Exception/UnexpectedTypeException.php b/digital_doctor/vendor/symfony/http-foundation/File/Exception/UnexpectedTypeException.php deleted file mode 100644 index 8533f99..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/File/Exception/UnexpectedTypeException.php +++ /dev/null @@ -1,20 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -class UnexpectedTypeException extends FileException -{ - public function __construct($value, string $expectedType) - { - parent::__construct(sprintf('Expected argument of type %s, %s given', $expectedType, get_debug_type($value))); - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/File/Exception/UploadException.php b/digital_doctor/vendor/symfony/http-foundation/File/Exception/UploadException.php deleted file mode 100644 index 7074e76..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/File/Exception/UploadException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an error occurred during file upload. - * - * @author Bernhard Schussek - */ -class UploadException extends FileException -{ -} diff --git a/digital_doctor/vendor/symfony/http-foundation/File/File.php b/digital_doctor/vendor/symfony/http-foundation/File/File.php deleted file mode 100644 index 2deb53d..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/File/File.php +++ /dev/null @@ -1,152 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File; - -use Symfony\Component\HttpFoundation\File\Exception\FileException; -use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; -use Symfony\Component\Mime\MimeTypes; - -/** - * A file in the file system. - * - * @author Bernhard Schussek - */ -class File extends \SplFileInfo -{ - /** - * Constructs a new file from the given path. - * - * @param string $path The path to the file - * @param bool $checkPath Whether to check the path or not - * - * @throws FileNotFoundException If the given path is not a file - */ - public function __construct(string $path, bool $checkPath = true) - { - if ($checkPath && !is_file($path)) { - throw new FileNotFoundException($path); - } - - parent::__construct($path); - } - - /** - * Returns the extension based on the mime type. - * - * If the mime type is unknown, returns null. - * - * This method uses the mime type as guessed by getMimeType() - * to guess the file extension. - * - * @return string|null - * - * @see MimeTypes - * @see getMimeType() - */ - public function guessExtension() - { - if (!class_exists(MimeTypes::class)) { - throw new \LogicException('You cannot guess the extension as the Mime component is not installed. Try running "composer require symfony/mime".'); - } - - return MimeTypes::getDefault()->getExtensions($this->getMimeType())[0] ?? null; - } - - /** - * Returns the mime type of the file. - * - * The mime type is guessed using a MimeTypeGuesserInterface instance, - * which uses finfo_file() then the "file" system binary, - * depending on which of those are available. - * - * @return string|null - * - * @see MimeTypes - */ - public function getMimeType() - { - if (!class_exists(MimeTypes::class)) { - throw new \LogicException('You cannot guess the mime type as the Mime component is not installed. Try running "composer require symfony/mime".'); - } - - return MimeTypes::getDefault()->guessMimeType($this->getPathname()); - } - - /** - * Moves the file to a new location. - * - * @return self - * - * @throws FileException if the target file could not be created - */ - public function move(string $directory, ?string $name = null) - { - $target = $this->getTargetFile($directory, $name); - - set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; }); - try { - $renamed = rename($this->getPathname(), $target); - } finally { - restore_error_handler(); - } - if (!$renamed) { - throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s).', $this->getPathname(), $target, strip_tags($error))); - } - - @chmod($target, 0666 & ~umask()); - - return $target; - } - - public function getContent(): string - { - $content = file_get_contents($this->getPathname()); - - if (false === $content) { - throw new FileException(sprintf('Could not get the content of the file "%s".', $this->getPathname())); - } - - return $content; - } - - /** - * @return self - */ - protected function getTargetFile(string $directory, ?string $name = null) - { - if (!is_dir($directory)) { - if (false === @mkdir($directory, 0777, true) && !is_dir($directory)) { - throw new FileException(sprintf('Unable to create the "%s" directory.', $directory)); - } - } elseif (!is_writable($directory)) { - throw new FileException(sprintf('Unable to write in the "%s" directory.', $directory)); - } - - $target = rtrim($directory, '/\\').\DIRECTORY_SEPARATOR.(null === $name ? $this->getBasename() : $this->getName($name)); - - return new self($target, false); - } - - /** - * Returns locale independent base name of the given path. - * - * @return string - */ - protected function getName(string $name) - { - $originalName = str_replace('\\', '/', $name); - $pos = strrpos($originalName, '/'); - $originalName = false === $pos ? $originalName : substr($originalName, $pos + 1); - - return $originalName; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/File/Stream.php b/digital_doctor/vendor/symfony/http-foundation/File/Stream.php deleted file mode 100644 index cef3e03..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/File/Stream.php +++ /dev/null @@ -1,31 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File; - -/** - * A PHP stream of unknown size. - * - * @author Nicolas Grekas - */ -class Stream extends File -{ - /** - * {@inheritdoc} - * - * @return int|false - */ - #[\ReturnTypeWillChange] - public function getSize() - { - return false; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/File/UploadedFile.php b/digital_doctor/vendor/symfony/http-foundation/File/UploadedFile.php deleted file mode 100644 index 6ff6e51..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/File/UploadedFile.php +++ /dev/null @@ -1,290 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File; - -use Symfony\Component\HttpFoundation\File\Exception\CannotWriteFileException; -use Symfony\Component\HttpFoundation\File\Exception\ExtensionFileException; -use Symfony\Component\HttpFoundation\File\Exception\FileException; -use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; -use Symfony\Component\HttpFoundation\File\Exception\FormSizeFileException; -use Symfony\Component\HttpFoundation\File\Exception\IniSizeFileException; -use Symfony\Component\HttpFoundation\File\Exception\NoFileException; -use Symfony\Component\HttpFoundation\File\Exception\NoTmpDirFileException; -use Symfony\Component\HttpFoundation\File\Exception\PartialFileException; -use Symfony\Component\Mime\MimeTypes; - -/** - * A file uploaded through a form. - * - * @author Bernhard Schussek - * @author Florian Eckerstorfer - * @author Fabien Potencier - */ -class UploadedFile extends File -{ - private $test; - private $originalName; - private $mimeType; - private $error; - - /** - * Accepts the information of the uploaded file as provided by the PHP global $_FILES. - * - * The file object is only created when the uploaded file is valid (i.e. when the - * isValid() method returns true). Otherwise the only methods that could be called - * on an UploadedFile instance are: - * - * * getClientOriginalName, - * * getClientMimeType, - * * isValid, - * * getError. - * - * Calling any other method on an non-valid instance will cause an unpredictable result. - * - * @param string $path The full temporary path to the file - * @param string $originalName The original file name of the uploaded file - * @param string|null $mimeType The type of the file as provided by PHP; null defaults to application/octet-stream - * @param int|null $error The error constant of the upload (one of PHP's UPLOAD_ERR_XXX constants); null defaults to UPLOAD_ERR_OK - * @param bool $test Whether the test mode is active - * Local files are used in test mode hence the code should not enforce HTTP uploads - * - * @throws FileException If file_uploads is disabled - * @throws FileNotFoundException If the file does not exist - */ - public function __construct(string $path, string $originalName, ?string $mimeType = null, ?int $error = null, bool $test = false) - { - $this->originalName = $this->getName($originalName); - $this->mimeType = $mimeType ?: 'application/octet-stream'; - $this->error = $error ?: \UPLOAD_ERR_OK; - $this->test = $test; - - parent::__construct($path, \UPLOAD_ERR_OK === $this->error); - } - - /** - * Returns the original file name. - * - * It is extracted from the request from which the file has been uploaded. - * This should not be considered as a safe value to use for a file name on your servers. - * - * @return string - */ - public function getClientOriginalName() - { - return $this->originalName; - } - - /** - * Returns the original file extension. - * - * It is extracted from the original file name that was uploaded. - * This should not be considered as a safe value to use for a file name on your servers. - * - * @return string - */ - public function getClientOriginalExtension() - { - return pathinfo($this->originalName, \PATHINFO_EXTENSION); - } - - /** - * Returns the file mime type. - * - * The client mime type is extracted from the request from which the file - * was uploaded, so it should not be considered as a safe value. - * - * For a trusted mime type, use getMimeType() instead (which guesses the mime - * type based on the file content). - * - * @return string - * - * @see getMimeType() - */ - public function getClientMimeType() - { - return $this->mimeType; - } - - /** - * Returns the extension based on the client mime type. - * - * If the mime type is unknown, returns null. - * - * This method uses the mime type as guessed by getClientMimeType() - * to guess the file extension. As such, the extension returned - * by this method cannot be trusted. - * - * For a trusted extension, use guessExtension() instead (which guesses - * the extension based on the guessed mime type for the file). - * - * @return string|null - * - * @see guessExtension() - * @see getClientMimeType() - */ - public function guessClientExtension() - { - if (!class_exists(MimeTypes::class)) { - throw new \LogicException('You cannot guess the extension as the Mime component is not installed. Try running "composer require symfony/mime".'); - } - - return MimeTypes::getDefault()->getExtensions($this->getClientMimeType())[0] ?? null; - } - - /** - * Returns the upload error. - * - * If the upload was successful, the constant UPLOAD_ERR_OK is returned. - * Otherwise one of the other UPLOAD_ERR_XXX constants is returned. - * - * @return int - */ - public function getError() - { - return $this->error; - } - - /** - * Returns whether the file has been uploaded with HTTP and no error occurred. - * - * @return bool - */ - public function isValid() - { - $isOk = \UPLOAD_ERR_OK === $this->error; - - return $this->test ? $isOk : $isOk && is_uploaded_file($this->getPathname()); - } - - /** - * Moves the file to a new location. - * - * @return File - * - * @throws FileException if, for any reason, the file could not have been moved - */ - public function move(string $directory, ?string $name = null) - { - if ($this->isValid()) { - if ($this->test) { - return parent::move($directory, $name); - } - - $target = $this->getTargetFile($directory, $name); - - set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; }); - try { - $moved = move_uploaded_file($this->getPathname(), $target); - } finally { - restore_error_handler(); - } - if (!$moved) { - throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s).', $this->getPathname(), $target, strip_tags($error))); - } - - @chmod($target, 0666 & ~umask()); - - return $target; - } - - switch ($this->error) { - case \UPLOAD_ERR_INI_SIZE: - throw new IniSizeFileException($this->getErrorMessage()); - case \UPLOAD_ERR_FORM_SIZE: - throw new FormSizeFileException($this->getErrorMessage()); - case \UPLOAD_ERR_PARTIAL: - throw new PartialFileException($this->getErrorMessage()); - case \UPLOAD_ERR_NO_FILE: - throw new NoFileException($this->getErrorMessage()); - case \UPLOAD_ERR_CANT_WRITE: - throw new CannotWriteFileException($this->getErrorMessage()); - case \UPLOAD_ERR_NO_TMP_DIR: - throw new NoTmpDirFileException($this->getErrorMessage()); - case \UPLOAD_ERR_EXTENSION: - throw new ExtensionFileException($this->getErrorMessage()); - } - - throw new FileException($this->getErrorMessage()); - } - - /** - * Returns the maximum size of an uploaded file as configured in php.ini. - * - * @return int|float The maximum size of an uploaded file in bytes (returns float if size > PHP_INT_MAX) - */ - public static function getMaxFilesize() - { - $sizePostMax = self::parseFilesize(\ini_get('post_max_size')); - $sizeUploadMax = self::parseFilesize(\ini_get('upload_max_filesize')); - - return min($sizePostMax ?: \PHP_INT_MAX, $sizeUploadMax ?: \PHP_INT_MAX); - } - - /** - * Returns the given size from an ini value in bytes. - * - * @return int|float Returns float if size > PHP_INT_MAX - */ - private static function parseFilesize(string $size) - { - if ('' === $size) { - return 0; - } - - $size = strtolower($size); - - $max = ltrim($size, '+'); - if (str_starts_with($max, '0x')) { - $max = \intval($max, 16); - } elseif (str_starts_with($max, '0')) { - $max = \intval($max, 8); - } else { - $max = (int) $max; - } - - switch (substr($size, -1)) { - case 't': $max *= 1024; - // no break - case 'g': $max *= 1024; - // no break - case 'm': $max *= 1024; - // no break - case 'k': $max *= 1024; - } - - return $max; - } - - /** - * Returns an informative upload error message. - * - * @return string - */ - public function getErrorMessage() - { - static $errors = [ - \UPLOAD_ERR_INI_SIZE => 'The file "%s" exceeds your upload_max_filesize ini directive (limit is %d KiB).', - \UPLOAD_ERR_FORM_SIZE => 'The file "%s" exceeds the upload limit defined in your form.', - \UPLOAD_ERR_PARTIAL => 'The file "%s" was only partially uploaded.', - \UPLOAD_ERR_NO_FILE => 'No file was uploaded.', - \UPLOAD_ERR_CANT_WRITE => 'The file "%s" could not be written on disk.', - \UPLOAD_ERR_NO_TMP_DIR => 'File could not be uploaded: missing temporary directory.', - \UPLOAD_ERR_EXTENSION => 'File upload was stopped by a PHP extension.', - ]; - - $errorCode = $this->error; - $maxFilesize = \UPLOAD_ERR_INI_SIZE === $errorCode ? self::getMaxFilesize() / 1024 : 0; - $message = $errors[$errorCode] ?? 'The file "%s" was not uploaded due to an unknown error.'; - - return sprintf($message, $this->getClientOriginalName(), $maxFilesize); - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/FileBag.php b/digital_doctor/vendor/symfony/http-foundation/FileBag.php deleted file mode 100644 index ff5ab77..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/FileBag.php +++ /dev/null @@ -1,140 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -use Symfony\Component\HttpFoundation\File\UploadedFile; - -/** - * FileBag is a container for uploaded files. - * - * @author Fabien Potencier - * @author Bulat Shakirzyanov - */ -class FileBag extends ParameterBag -{ - private const FILE_KEYS = ['error', 'name', 'size', 'tmp_name', 'type']; - - /** - * @param array|UploadedFile[] $parameters An array of HTTP files - */ - public function __construct(array $parameters = []) - { - $this->replace($parameters); - } - - /** - * {@inheritdoc} - */ - public function replace(array $files = []) - { - $this->parameters = []; - $this->add($files); - } - - /** - * {@inheritdoc} - */ - public function set(string $key, $value) - { - if (!\is_array($value) && !$value instanceof UploadedFile) { - throw new \InvalidArgumentException('An uploaded file must be an array or an instance of UploadedFile.'); - } - - parent::set($key, $this->convertFileInformation($value)); - } - - /** - * {@inheritdoc} - */ - public function add(array $files = []) - { - foreach ($files as $key => $file) { - $this->set($key, $file); - } - } - - /** - * Converts uploaded files to UploadedFile instances. - * - * @param array|UploadedFile $file A (multi-dimensional) array of uploaded file information - * - * @return UploadedFile[]|UploadedFile|null - */ - protected function convertFileInformation($file) - { - if ($file instanceof UploadedFile) { - return $file; - } - - $file = $this->fixPhpFilesArray($file); - $keys = array_keys($file); - sort($keys); - - if (self::FILE_KEYS == $keys) { - if (\UPLOAD_ERR_NO_FILE == $file['error']) { - $file = null; - } else { - $file = new UploadedFile($file['tmp_name'], $file['name'], $file['type'], $file['error'], false); - } - } else { - $file = array_map(function ($v) { return $v instanceof UploadedFile || \is_array($v) ? $this->convertFileInformation($v) : $v; }, $file); - if (array_keys($keys) === $keys) { - $file = array_filter($file); - } - } - - return $file; - } - - /** - * Fixes a malformed PHP $_FILES array. - * - * PHP has a bug that the format of the $_FILES array differs, depending on - * whether the uploaded file fields had normal field names or array-like - * field names ("normal" vs. "parent[child]"). - * - * This method fixes the array to look like the "normal" $_FILES array. - * - * It's safe to pass an already converted array, in which case this method - * just returns the original array unmodified. - * - * @return array - */ - protected function fixPhpFilesArray(array $data) - { - // Remove extra key added by PHP 8.1. - unset($data['full_path']); - $keys = array_keys($data); - sort($keys); - - if (self::FILE_KEYS != $keys || !isset($data['name']) || !\is_array($data['name'])) { - return $data; - } - - $files = $data; - foreach (self::FILE_KEYS as $k) { - unset($files[$k]); - } - - foreach ($data['name'] as $key => $name) { - $files[$key] = $this->fixPhpFilesArray([ - 'error' => $data['error'][$key], - 'name' => $name, - 'type' => $data['type'][$key], - 'tmp_name' => $data['tmp_name'][$key], - 'size' => $data['size'][$key], - ]); - } - - return $files; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/HeaderBag.php b/digital_doctor/vendor/symfony/http-foundation/HeaderBag.php deleted file mode 100644 index 43d5f63..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/HeaderBag.php +++ /dev/null @@ -1,295 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * HeaderBag is a container for HTTP headers. - * - * @author Fabien Potencier - * - * @implements \IteratorAggregate> - */ -class HeaderBag implements \IteratorAggregate, \Countable -{ - protected const UPPER = '_ABCDEFGHIJKLMNOPQRSTUVWXYZ'; - protected const LOWER = '-abcdefghijklmnopqrstuvwxyz'; - - /** - * @var array> - */ - protected $headers = []; - protected $cacheControl = []; - - public function __construct(array $headers = []) - { - foreach ($headers as $key => $values) { - $this->set($key, $values); - } - } - - /** - * Returns the headers as a string. - * - * @return string - */ - public function __toString() - { - if (!$headers = $this->all()) { - return ''; - } - - ksort($headers); - $max = max(array_map('strlen', array_keys($headers))) + 1; - $content = ''; - foreach ($headers as $name => $values) { - $name = ucwords($name, '-'); - foreach ($values as $value) { - $content .= sprintf("%-{$max}s %s\r\n", $name.':', $value); - } - } - - return $content; - } - - /** - * Returns the headers. - * - * @param string|null $key The name of the headers to return or null to get them all - * - * @return array>|array - */ - public function all(?string $key = null) - { - if (null !== $key) { - return $this->headers[strtr($key, self::UPPER, self::LOWER)] ?? []; - } - - return $this->headers; - } - - /** - * Returns the parameter keys. - * - * @return string[] - */ - public function keys() - { - return array_keys($this->all()); - } - - /** - * Replaces the current HTTP headers by a new set. - */ - public function replace(array $headers = []) - { - $this->headers = []; - $this->add($headers); - } - - /** - * Adds new headers the current HTTP headers set. - */ - public function add(array $headers) - { - foreach ($headers as $key => $values) { - $this->set($key, $values); - } - } - - /** - * Returns the first header by name or the default one. - * - * @return string|null - */ - public function get(string $key, ?string $default = null) - { - $headers = $this->all($key); - - if (!$headers) { - return $default; - } - - if (null === $headers[0]) { - return null; - } - - return (string) $headers[0]; - } - - /** - * Sets a header by name. - * - * @param string|string[]|null $values The value or an array of values - * @param bool $replace Whether to replace the actual value or not (true by default) - */ - public function set(string $key, $values, bool $replace = true) - { - $key = strtr($key, self::UPPER, self::LOWER); - - if (\is_array($values)) { - $values = array_values($values); - - if (true === $replace || !isset($this->headers[$key])) { - $this->headers[$key] = $values; - } else { - $this->headers[$key] = array_merge($this->headers[$key], $values); - } - } else { - if (true === $replace || !isset($this->headers[$key])) { - $this->headers[$key] = [$values]; - } else { - $this->headers[$key][] = $values; - } - } - - if ('cache-control' === $key) { - $this->cacheControl = $this->parseCacheControl(implode(', ', $this->headers[$key])); - } - } - - /** - * Returns true if the HTTP header is defined. - * - * @return bool - */ - public function has(string $key) - { - return \array_key_exists(strtr($key, self::UPPER, self::LOWER), $this->all()); - } - - /** - * Returns true if the given HTTP header contains the given value. - * - * @return bool - */ - public function contains(string $key, string $value) - { - return \in_array($value, $this->all($key)); - } - - /** - * Removes a header. - */ - public function remove(string $key) - { - $key = strtr($key, self::UPPER, self::LOWER); - - unset($this->headers[$key]); - - if ('cache-control' === $key) { - $this->cacheControl = []; - } - } - - /** - * Returns the HTTP header value converted to a date. - * - * @return \DateTimeInterface|null - * - * @throws \RuntimeException When the HTTP header is not parseable - */ - public function getDate(string $key, ?\DateTime $default = null) - { - if (null === $value = $this->get($key)) { - return $default; - } - - if (false === $date = \DateTime::createFromFormat(\DATE_RFC2822, $value)) { - throw new \RuntimeException(sprintf('The "%s" HTTP header is not parseable (%s).', $key, $value)); - } - - return $date; - } - - /** - * Adds a custom Cache-Control directive. - * - * @param bool|string $value The Cache-Control directive value - */ - public function addCacheControlDirective(string $key, $value = true) - { - $this->cacheControl[$key] = $value; - - $this->set('Cache-Control', $this->getCacheControlHeader()); - } - - /** - * Returns true if the Cache-Control directive is defined. - * - * @return bool - */ - public function hasCacheControlDirective(string $key) - { - return \array_key_exists($key, $this->cacheControl); - } - - /** - * Returns a Cache-Control directive value by name. - * - * @return bool|string|null - */ - public function getCacheControlDirective(string $key) - { - return $this->cacheControl[$key] ?? null; - } - - /** - * Removes a Cache-Control directive. - */ - public function removeCacheControlDirective(string $key) - { - unset($this->cacheControl[$key]); - - $this->set('Cache-Control', $this->getCacheControlHeader()); - } - - /** - * Returns an iterator for headers. - * - * @return \ArrayIterator> - */ - #[\ReturnTypeWillChange] - public function getIterator() - { - return new \ArrayIterator($this->headers); - } - - /** - * Returns the number of headers. - * - * @return int - */ - #[\ReturnTypeWillChange] - public function count() - { - return \count($this->headers); - } - - protected function getCacheControlHeader() - { - ksort($this->cacheControl); - - return HeaderUtils::toString($this->cacheControl, ','); - } - - /** - * Parses a Cache-Control HTTP header. - * - * @return array - */ - protected function parseCacheControl(string $header) - { - $parts = HeaderUtils::split($header, ',='); - - return HeaderUtils::combine($parts); - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/HeaderUtils.php b/digital_doctor/vendor/symfony/http-foundation/HeaderUtils.php deleted file mode 100644 index 110896e..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/HeaderUtils.php +++ /dev/null @@ -1,298 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * HTTP header utility functions. - * - * @author Christian Schmidt - */ -class HeaderUtils -{ - public const DISPOSITION_ATTACHMENT = 'attachment'; - public const DISPOSITION_INLINE = 'inline'; - - /** - * This class should not be instantiated. - */ - private function __construct() - { - } - - /** - * Splits an HTTP header by one or more separators. - * - * Example: - * - * HeaderUtils::split('da, en-gb;q=0.8', ',;') - * // => ['da'], ['en-gb', 'q=0.8']] - * - * @param string $separators List of characters to split on, ordered by - * precedence, e.g. ',', ';=', or ',;=' - * - * @return array Nested array with as many levels as there are characters in - * $separators - */ - public static function split(string $header, string $separators): array - { - if ('' === $separators) { - throw new \InvalidArgumentException('At least one separator must be specified.'); - } - - $quotedSeparators = preg_quote($separators, '/'); - - preg_match_all(' - / - (?!\s) - (?: - # quoted-string - "(?:[^"\\\\]|\\\\.)*(?:"|\\\\|$) - | - # token - [^"'.$quotedSeparators.']+ - )+ - (?['.$quotedSeparators.']) - \s* - /x', trim($header), $matches, \PREG_SET_ORDER); - - return self::groupParts($matches, $separators); - } - - /** - * Combines an array of arrays into one associative array. - * - * Each of the nested arrays should have one or two elements. The first - * value will be used as the keys in the associative array, and the second - * will be used as the values, or true if the nested array only contains one - * element. Array keys are lowercased. - * - * Example: - * - * HeaderUtils::combine([['foo', 'abc'], ['bar']]) - * // => ['foo' => 'abc', 'bar' => true] - */ - public static function combine(array $parts): array - { - $assoc = []; - foreach ($parts as $part) { - $name = strtolower($part[0]); - $value = $part[1] ?? true; - $assoc[$name] = $value; - } - - return $assoc; - } - - /** - * Joins an associative array into a string for use in an HTTP header. - * - * The key and value of each entry are joined with '=', and all entries - * are joined with the specified separator and an additional space (for - * readability). Values are quoted if necessary. - * - * Example: - * - * HeaderUtils::toString(['foo' => 'abc', 'bar' => true, 'baz' => 'a b c'], ',') - * // => 'foo=abc, bar, baz="a b c"' - */ - public static function toString(array $assoc, string $separator): string - { - $parts = []; - foreach ($assoc as $name => $value) { - if (true === $value) { - $parts[] = $name; - } else { - $parts[] = $name.'='.self::quote($value); - } - } - - return implode($separator.' ', $parts); - } - - /** - * Encodes a string as a quoted string, if necessary. - * - * If a string contains characters not allowed by the "token" construct in - * the HTTP specification, it is backslash-escaped and enclosed in quotes - * to match the "quoted-string" construct. - */ - public static function quote(string $s): string - { - if (preg_match('/^[a-z0-9!#$%&\'*.^_`|~-]+$/i', $s)) { - return $s; - } - - return '"'.addcslashes($s, '"\\"').'"'; - } - - /** - * Decodes a quoted string. - * - * If passed an unquoted string that matches the "token" construct (as - * defined in the HTTP specification), it is passed through verbatim. - */ - public static function unquote(string $s): string - { - return preg_replace('/\\\\(.)|"/', '$1', $s); - } - - /** - * Generates an HTTP Content-Disposition field-value. - * - * @param string $disposition One of "inline" or "attachment" - * @param string $filename A unicode string - * @param string $filenameFallback A string containing only ASCII characters that - * is semantically equivalent to $filename. If the filename is already ASCII, - * it can be omitted, or just copied from $filename - * - * @throws \InvalidArgumentException - * - * @see RFC 6266 - */ - public static function makeDisposition(string $disposition, string $filename, string $filenameFallback = ''): string - { - if (!\in_array($disposition, [self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE])) { - throw new \InvalidArgumentException(sprintf('The disposition must be either "%s" or "%s".', self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE)); - } - - if ('' === $filenameFallback) { - $filenameFallback = $filename; - } - - // filenameFallback is not ASCII. - if (!preg_match('/^[\x20-\x7e]*$/', $filenameFallback)) { - throw new \InvalidArgumentException('The filename fallback must only contain ASCII characters.'); - } - - // percent characters aren't safe in fallback. - if (str_contains($filenameFallback, '%')) { - throw new \InvalidArgumentException('The filename fallback cannot contain the "%" character.'); - } - - // path separators aren't allowed in either. - if (str_contains($filename, '/') || str_contains($filename, '\\') || str_contains($filenameFallback, '/') || str_contains($filenameFallback, '\\')) { - throw new \InvalidArgumentException('The filename and the fallback cannot contain the "/" and "\\" characters.'); - } - - $params = ['filename' => $filenameFallback]; - if ($filename !== $filenameFallback) { - $params['filename*'] = "utf-8''".rawurlencode($filename); - } - - return $disposition.'; '.self::toString($params, ';'); - } - - /** - * Like parse_str(), but preserves dots in variable names. - */ - public static function parseQuery(string $query, bool $ignoreBrackets = false, string $separator = '&'): array - { - $q = []; - - foreach (explode($separator, $query) as $v) { - if (false !== $i = strpos($v, "\0")) { - $v = substr($v, 0, $i); - } - - if (false === $i = strpos($v, '=')) { - $k = urldecode($v); - $v = ''; - } else { - $k = urldecode(substr($v, 0, $i)); - $v = substr($v, $i); - } - - if (false !== $i = strpos($k, "\0")) { - $k = substr($k, 0, $i); - } - - $k = ltrim($k, ' '); - - if ($ignoreBrackets) { - $q[$k][] = urldecode(substr($v, 1)); - - continue; - } - - if (false === $i = strpos($k, '[')) { - $q[] = bin2hex($k).$v; - } else { - $q[] = bin2hex(substr($k, 0, $i)).rawurlencode(substr($k, $i)).$v; - } - } - - if ($ignoreBrackets) { - return $q; - } - - parse_str(implode('&', $q), $q); - - $query = []; - - foreach ($q as $k => $v) { - if (false !== $i = strpos($k, '_')) { - $query[substr_replace($k, hex2bin(substr($k, 0, $i)).'[', 0, 1 + $i)] = $v; - } else { - $query[hex2bin($k)] = $v; - } - } - - return $query; - } - - private static function groupParts(array $matches, string $separators, bool $first = true): array - { - $separator = $separators[0]; - $separators = substr($separators, 1) ?: ''; - $i = 0; - - if ('' === $separators && !$first) { - $parts = ['']; - - foreach ($matches as $match) { - if (!$i && isset($match['separator'])) { - $i = 1; - $parts[1] = ''; - } else { - $parts[$i] .= self::unquote($match[0]); - } - } - - return $parts; - } - - $parts = []; - $partMatches = []; - - foreach ($matches as $match) { - if (($match['separator'] ?? null) === $separator) { - ++$i; - } else { - $partMatches[$i][] = $match; - } - } - - foreach ($partMatches as $matches) { - if ('' === $separators && '' !== $unquoted = self::unquote($matches[0][0])) { - $parts[] = $unquoted; - } elseif ($groupedParts = self::groupParts($matches, $separators, false)) { - $parts[] = $groupedParts; - } - } - - return $parts; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/InputBag.php b/digital_doctor/vendor/symfony/http-foundation/InputBag.php deleted file mode 100644 index 356fbbc..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/InputBag.php +++ /dev/null @@ -1,113 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -use Symfony\Component\HttpFoundation\Exception\BadRequestException; - -/** - * InputBag is a container for user input values such as $_GET, $_POST, $_REQUEST, and $_COOKIE. - * - * @author Saif Eddin Gmati - */ -final class InputBag extends ParameterBag -{ - /** - * Returns a scalar input value by name. - * - * @param string|int|float|bool|null $default The default value if the input key does not exist - * - * @return string|int|float|bool|null - */ - public function get(string $key, $default = null) - { - if (null !== $default && !\is_scalar($default) && !(\is_object($default) && method_exists($default, '__toString'))) { - trigger_deprecation('symfony/http-foundation', '5.1', 'Passing a non-scalar value as 2nd argument to "%s()" is deprecated, pass a scalar or null instead.', __METHOD__); - } - - $value = parent::get($key, $this); - - if (null !== $value && $this !== $value && !\is_scalar($value) && !(\is_object($value) && method_exists($value, '__toString'))) { - trigger_deprecation('symfony/http-foundation', '5.1', 'Retrieving a non-scalar value from "%s()" is deprecated, and will throw a "%s" exception in Symfony 6.0, use "%s::all($key)" instead.', __METHOD__, BadRequestException::class, __CLASS__); - } - - return $this === $value ? $default : $value; - } - - /** - * {@inheritdoc} - */ - public function all(?string $key = null): array - { - return parent::all($key); - } - - /** - * Replaces the current input values by a new set. - */ - public function replace(array $inputs = []) - { - $this->parameters = []; - $this->add($inputs); - } - - /** - * Adds input values. - */ - public function add(array $inputs = []) - { - foreach ($inputs as $input => $value) { - $this->set($input, $value); - } - } - - /** - * Sets an input by name. - * - * @param string|int|float|bool|array|null $value - */ - public function set(string $key, $value) - { - if (null !== $value && !\is_scalar($value) && !\is_array($value) && !method_exists($value, '__toString')) { - trigger_deprecation('symfony/http-foundation', '5.1', 'Passing "%s" as a 2nd Argument to "%s()" is deprecated, pass a scalar, array, or null instead.', get_debug_type($value), __METHOD__); - } - - $this->parameters[$key] = $value; - } - - /** - * {@inheritdoc} - */ - public function filter(string $key, $default = null, int $filter = \FILTER_DEFAULT, $options = []) - { - $value = $this->has($key) ? $this->all()[$key] : $default; - - // Always turn $options into an array - this allows filter_var option shortcuts. - if (!\is_array($options) && $options) { - $options = ['flags' => $options]; - } - - if (\is_array($value) && !(($options['flags'] ?? 0) & (\FILTER_REQUIRE_ARRAY | \FILTER_FORCE_ARRAY))) { - trigger_deprecation('symfony/http-foundation', '5.1', 'Filtering an array value with "%s()" without passing the FILTER_REQUIRE_ARRAY or FILTER_FORCE_ARRAY flag is deprecated', __METHOD__); - - if (!isset($options['flags'])) { - $options['flags'] = \FILTER_REQUIRE_ARRAY; - } - } - - if ((\FILTER_CALLBACK & $filter) && !(($options['options'] ?? null) instanceof \Closure)) { - trigger_deprecation('symfony/http-foundation', '5.2', 'Not passing a Closure together with FILTER_CALLBACK to "%s()" is deprecated. Wrap your filter in a closure instead.', __METHOD__); - // throw new \InvalidArgumentException(sprintf('A Closure must be passed to "%s()" when FILTER_CALLBACK is used, "%s" given.', __METHOD__, get_debug_type($options['options'] ?? null))); - } - - return filter_var($value, $filter, $options); - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/IpUtils.php b/digital_doctor/vendor/symfony/http-foundation/IpUtils.php deleted file mode 100644 index 49d9a9d..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/IpUtils.php +++ /dev/null @@ -1,216 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * Http utility functions. - * - * @author Fabien Potencier - */ -class IpUtils -{ - private static $checkedIps = []; - - /** - * This class should not be instantiated. - */ - private function __construct() - { - } - - /** - * Checks if an IPv4 or IPv6 address is contained in the list of given IPs or subnets. - * - * @param string|array $ips List of IPs or subnets (can be a string if only a single one) - * - * @return bool - */ - public static function checkIp(?string $requestIp, $ips) - { - if (null === $requestIp) { - trigger_deprecation('symfony/http-foundation', '5.4', 'Passing null as $requestIp to "%s()" is deprecated, pass an empty string instead.', __METHOD__); - - return false; - } - - if (!\is_array($ips)) { - $ips = [$ips]; - } - - $method = substr_count($requestIp, ':') > 1 ? 'checkIp6' : 'checkIp4'; - - foreach ($ips as $ip) { - if (self::$method($requestIp, $ip)) { - return true; - } - } - - return false; - } - - /** - * Compares two IPv4 addresses. - * In case a subnet is given, it checks if it contains the request IP. - * - * @param string $ip IPv4 address or subnet in CIDR notation - * - * @return bool Whether the request IP matches the IP, or whether the request IP is within the CIDR subnet - */ - public static function checkIp4(?string $requestIp, string $ip) - { - if (null === $requestIp) { - trigger_deprecation('symfony/http-foundation', '5.4', 'Passing null as $requestIp to "%s()" is deprecated, pass an empty string instead.', __METHOD__); - - return false; - } - - $cacheKey = $requestIp.'-'.$ip.'-v4'; - if (isset(self::$checkedIps[$cacheKey])) { - return self::$checkedIps[$cacheKey]; - } - - if (!filter_var($requestIp, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4)) { - return self::$checkedIps[$cacheKey] = false; - } - - if (str_contains($ip, '/')) { - [$address, $netmask] = explode('/', $ip, 2); - - if ('0' === $netmask) { - return self::$checkedIps[$cacheKey] = false !== filter_var($address, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4); - } - - if ($netmask < 0 || $netmask > 32) { - return self::$checkedIps[$cacheKey] = false; - } - } else { - $address = $ip; - $netmask = 32; - } - - if (false === ip2long($address)) { - return self::$checkedIps[$cacheKey] = false; - } - - return self::$checkedIps[$cacheKey] = 0 === substr_compare(sprintf('%032b', ip2long($requestIp)), sprintf('%032b', ip2long($address)), 0, $netmask); - } - - /** - * Compares two IPv6 addresses. - * In case a subnet is given, it checks if it contains the request IP. - * - * @author David Soria Parra - * - * @see https://github.com/dsp/v6tools - * - * @param string $ip IPv6 address or subnet in CIDR notation - * - * @return bool - * - * @throws \RuntimeException When IPV6 support is not enabled - */ - public static function checkIp6(?string $requestIp, string $ip) - { - if (null === $requestIp) { - trigger_deprecation('symfony/http-foundation', '5.4', 'Passing null as $requestIp to "%s()" is deprecated, pass an empty string instead.', __METHOD__); - - return false; - } - - $cacheKey = $requestIp.'-'.$ip.'-v6'; - if (isset(self::$checkedIps[$cacheKey])) { - return self::$checkedIps[$cacheKey]; - } - - if (!((\extension_loaded('sockets') && \defined('AF_INET6')) || @inet_pton('::1'))) { - throw new \RuntimeException('Unable to check Ipv6. Check that PHP was not compiled with option "disable-ipv6".'); - } - - // Check to see if we were given a IP4 $requestIp or $ip by mistake - if (!filter_var($requestIp, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) { - return self::$checkedIps[$cacheKey] = false; - } - - if (str_contains($ip, '/')) { - [$address, $netmask] = explode('/', $ip, 2); - - if (!filter_var($address, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) { - return self::$checkedIps[$cacheKey] = false; - } - - if ('0' === $netmask) { - return (bool) unpack('n*', @inet_pton($address)); - } - - if ($netmask < 1 || $netmask > 128) { - return self::$checkedIps[$cacheKey] = false; - } - } else { - if (!filter_var($ip, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) { - return self::$checkedIps[$cacheKey] = false; - } - - $address = $ip; - $netmask = 128; - } - - $bytesAddr = unpack('n*', @inet_pton($address)); - $bytesTest = unpack('n*', @inet_pton($requestIp)); - - if (!$bytesAddr || !$bytesTest) { - return self::$checkedIps[$cacheKey] = false; - } - - for ($i = 1, $ceil = ceil($netmask / 16); $i <= $ceil; ++$i) { - $left = $netmask - 16 * ($i - 1); - $left = ($left <= 16) ? $left : 16; - $mask = ~(0xFFFF >> $left) & 0xFFFF; - if (($bytesAddr[$i] & $mask) != ($bytesTest[$i] & $mask)) { - return self::$checkedIps[$cacheKey] = false; - } - } - - return self::$checkedIps[$cacheKey] = true; - } - - /** - * Anonymizes an IP/IPv6. - * - * Removes the last byte for v4 and the last 8 bytes for v6 IPs - */ - public static function anonymize(string $ip): string - { - $wrappedIPv6 = false; - if ('[' === substr($ip, 0, 1) && ']' === substr($ip, -1, 1)) { - $wrappedIPv6 = true; - $ip = substr($ip, 1, -1); - } - - $packedAddress = inet_pton($ip); - if (4 === \strlen($packedAddress)) { - $mask = '255.255.255.0'; - } elseif ($ip === inet_ntop($packedAddress & inet_pton('::ffff:ffff:ffff'))) { - $mask = '::ffff:ffff:ff00'; - } elseif ($ip === inet_ntop($packedAddress & inet_pton('::ffff:ffff'))) { - $mask = '::ffff:ff00'; - } else { - $mask = 'ffff:ffff:ffff:ffff:0000:0000:0000:0000'; - } - $ip = inet_ntop($packedAddress & inet_pton($mask)); - - if ($wrappedIPv6) { - $ip = '['.$ip.']'; - } - - return $ip; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/JsonResponse.php b/digital_doctor/vendor/symfony/http-foundation/JsonResponse.php deleted file mode 100644 index 51bdf19..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/JsonResponse.php +++ /dev/null @@ -1,221 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * Response represents an HTTP response in JSON format. - * - * Note that this class does not force the returned JSON content to be an - * object. It is however recommended that you do return an object as it - * protects yourself against XSSI and JSON-JavaScript Hijacking. - * - * @see https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/AJAX_Security_Cheat_Sheet.md#always-return-json-with-an-object-on-the-outside - * - * @author Igor Wiedler - */ -class JsonResponse extends Response -{ - protected $data; - protected $callback; - - // Encode <, >, ', &, and " characters in the JSON, making it also safe to be embedded into HTML. - // 15 === JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT - public const DEFAULT_ENCODING_OPTIONS = 15; - - protected $encodingOptions = self::DEFAULT_ENCODING_OPTIONS; - - /** - * @param mixed $data The response data - * @param int $status The response status code - * @param array $headers An array of response headers - * @param bool $json If the data is already a JSON string - */ - public function __construct($data = null, int $status = 200, array $headers = [], bool $json = false) - { - parent::__construct('', $status, $headers); - - if ($json && !\is_string($data) && !is_numeric($data) && !\is_callable([$data, '__toString'])) { - throw new \TypeError(sprintf('"%s": If $json is set to true, argument $data must be a string or object implementing __toString(), "%s" given.', __METHOD__, get_debug_type($data))); - } - - if (null === $data) { - $data = new \ArrayObject(); - } - - $json ? $this->setJson($data) : $this->setData($data); - } - - /** - * Factory method for chainability. - * - * Example: - * - * return JsonResponse::create(['key' => 'value']) - * ->setSharedMaxAge(300); - * - * @param mixed $data The JSON response data - * @param int $status The response status code - * @param array $headers An array of response headers - * - * @return static - * - * @deprecated since Symfony 5.1, use __construct() instead. - */ - public static function create($data = null, int $status = 200, array $headers = []) - { - trigger_deprecation('symfony/http-foundation', '5.1', 'The "%s()" method is deprecated, use "new %s()" instead.', __METHOD__, static::class); - - return new static($data, $status, $headers); - } - - /** - * Factory method for chainability. - * - * Example: - * - * return JsonResponse::fromJsonString('{"key": "value"}') - * ->setSharedMaxAge(300); - * - * @param string $data The JSON response string - * @param int $status The response status code - * @param array $headers An array of response headers - * - * @return static - */ - public static function fromJsonString(string $data, int $status = 200, array $headers = []) - { - return new static($data, $status, $headers, true); - } - - /** - * Sets the JSONP callback. - * - * @param string|null $callback The JSONP callback or null to use none - * - * @return $this - * - * @throws \InvalidArgumentException When the callback name is not valid - */ - public function setCallback(?string $callback = null) - { - if (null !== $callback) { - // partially taken from https://geekality.net/2011/08/03/valid-javascript-identifier/ - // partially taken from https://github.com/willdurand/JsonpCallbackValidator - // JsonpCallbackValidator is released under the MIT License. See https://github.com/willdurand/JsonpCallbackValidator/blob/v1.1.0/LICENSE for details. - // (c) William Durand - $pattern = '/^[$_\p{L}][$_\p{L}\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{200C}\x{200D}]*(?:\[(?:"(?:\\\.|[^"\\\])*"|\'(?:\\\.|[^\'\\\])*\'|\d+)\])*?$/u'; - $reserved = [ - 'break', 'do', 'instanceof', 'typeof', 'case', 'else', 'new', 'var', 'catch', 'finally', 'return', 'void', 'continue', 'for', 'switch', 'while', - 'debugger', 'function', 'this', 'with', 'default', 'if', 'throw', 'delete', 'in', 'try', 'class', 'enum', 'extends', 'super', 'const', 'export', - 'import', 'implements', 'let', 'private', 'public', 'yield', 'interface', 'package', 'protected', 'static', 'null', 'true', 'false', - ]; - $parts = explode('.', $callback); - foreach ($parts as $part) { - if (!preg_match($pattern, $part) || \in_array($part, $reserved, true)) { - throw new \InvalidArgumentException('The callback name is not valid.'); - } - } - } - - $this->callback = $callback; - - return $this->update(); - } - - /** - * Sets a raw string containing a JSON document to be sent. - * - * @return $this - */ - public function setJson(string $json) - { - $this->data = $json; - - return $this->update(); - } - - /** - * Sets the data to be sent as JSON. - * - * @param mixed $data - * - * @return $this - * - * @throws \InvalidArgumentException - */ - public function setData($data = []) - { - try { - $data = json_encode($data, $this->encodingOptions); - } catch (\Exception $e) { - if ('Exception' === \get_class($e) && str_starts_with($e->getMessage(), 'Failed calling ')) { - throw $e->getPrevious() ?: $e; - } - throw $e; - } - - if (\PHP_VERSION_ID >= 70300 && (\JSON_THROW_ON_ERROR & $this->encodingOptions)) { - return $this->setJson($data); - } - - if (\JSON_ERROR_NONE !== json_last_error()) { - throw new \InvalidArgumentException(json_last_error_msg()); - } - - return $this->setJson($data); - } - - /** - * Returns options used while encoding data to JSON. - * - * @return int - */ - public function getEncodingOptions() - { - return $this->encodingOptions; - } - - /** - * Sets options used while encoding data to JSON. - * - * @return $this - */ - public function setEncodingOptions(int $encodingOptions) - { - $this->encodingOptions = $encodingOptions; - - return $this->setData(json_decode($this->data)); - } - - /** - * Updates the content and headers according to the JSON data and callback. - * - * @return $this - */ - protected function update() - { - if (null !== $this->callback) { - // Not using application/javascript for compatibility reasons with older browsers. - $this->headers->set('Content-Type', 'text/javascript'); - - return $this->setContent(sprintf('/**/%s(%s);', $this->callback, $this->data)); - } - - // Only set the header when there is none or when it equals 'text/javascript' (from a previous update with callback) - // in order to not overwrite a custom definition. - if (!$this->headers->has('Content-Type') || 'text/javascript' === $this->headers->get('Content-Type')) { - $this->headers->set('Content-Type', 'application/json'); - } - - return $this->setContent($this->data); - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/LICENSE b/digital_doctor/vendor/symfony/http-foundation/LICENSE deleted file mode 100644 index 0138f8f..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2004-present Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/digital_doctor/vendor/symfony/http-foundation/ParameterBag.php b/digital_doctor/vendor/symfony/http-foundation/ParameterBag.php deleted file mode 100644 index b542292..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/ParameterBag.php +++ /dev/null @@ -1,228 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -use Symfony\Component\HttpFoundation\Exception\BadRequestException; - -/** - * ParameterBag is a container for key/value pairs. - * - * @author Fabien Potencier - * - * @implements \IteratorAggregate - */ -class ParameterBag implements \IteratorAggregate, \Countable -{ - /** - * Parameter storage. - */ - protected $parameters; - - public function __construct(array $parameters = []) - { - $this->parameters = $parameters; - } - - /** - * Returns the parameters. - * - * @param string|null $key The name of the parameter to return or null to get them all - * - * @return array - */ - public function all(/* ?string $key = null */) - { - $key = \func_num_args() > 0 ? func_get_arg(0) : null; - - if (null === $key) { - return $this->parameters; - } - - if (!\is_array($value = $this->parameters[$key] ?? [])) { - throw new BadRequestException(sprintf('Unexpected value for parameter "%s": expecting "array", got "%s".', $key, get_debug_type($value))); - } - - return $value; - } - - /** - * Returns the parameter keys. - * - * @return array - */ - public function keys() - { - return array_keys($this->parameters); - } - - /** - * Replaces the current parameters by a new set. - */ - public function replace(array $parameters = []) - { - $this->parameters = $parameters; - } - - /** - * Adds parameters. - */ - public function add(array $parameters = []) - { - $this->parameters = array_replace($this->parameters, $parameters); - } - - /** - * Returns a parameter by name. - * - * @param mixed $default The default value if the parameter key does not exist - * - * @return mixed - */ - public function get(string $key, $default = null) - { - return \array_key_exists($key, $this->parameters) ? $this->parameters[$key] : $default; - } - - /** - * Sets a parameter by name. - * - * @param mixed $value The value - */ - public function set(string $key, $value) - { - $this->parameters[$key] = $value; - } - - /** - * Returns true if the parameter is defined. - * - * @return bool - */ - public function has(string $key) - { - return \array_key_exists($key, $this->parameters); - } - - /** - * Removes a parameter. - */ - public function remove(string $key) - { - unset($this->parameters[$key]); - } - - /** - * Returns the alphabetic characters of the parameter value. - * - * @return string - */ - public function getAlpha(string $key, string $default = '') - { - return preg_replace('/[^[:alpha:]]/', '', $this->get($key, $default)); - } - - /** - * Returns the alphabetic characters and digits of the parameter value. - * - * @return string - */ - public function getAlnum(string $key, string $default = '') - { - return preg_replace('/[^[:alnum:]]/', '', $this->get($key, $default)); - } - - /** - * Returns the digits of the parameter value. - * - * @return string - */ - public function getDigits(string $key, string $default = '') - { - // we need to remove - and + because they're allowed in the filter - return str_replace(['-', '+'], '', $this->filter($key, $default, \FILTER_SANITIZE_NUMBER_INT)); - } - - /** - * Returns the parameter value converted to integer. - * - * @return int - */ - public function getInt(string $key, int $default = 0) - { - return (int) $this->get($key, $default); - } - - /** - * Returns the parameter value converted to boolean. - * - * @return bool - */ - public function getBoolean(string $key, bool $default = false) - { - return $this->filter($key, $default, \FILTER_VALIDATE_BOOLEAN); - } - - /** - * Filter key. - * - * @param mixed $default Default = null - * @param int $filter FILTER_* constant - * @param mixed $options Filter options - * - * @see https://php.net/filter-var - * - * @return mixed - */ - public function filter(string $key, $default = null, int $filter = \FILTER_DEFAULT, $options = []) - { - $value = $this->get($key, $default); - - // Always turn $options into an array - this allows filter_var option shortcuts. - if (!\is_array($options) && $options) { - $options = ['flags' => $options]; - } - - // Add a convenience check for arrays. - if (\is_array($value) && !isset($options['flags'])) { - $options['flags'] = \FILTER_REQUIRE_ARRAY; - } - - if ((\FILTER_CALLBACK & $filter) && !(($options['options'] ?? null) instanceof \Closure)) { - trigger_deprecation('symfony/http-foundation', '5.2', 'Not passing a Closure together with FILTER_CALLBACK to "%s()" is deprecated. Wrap your filter in a closure instead.', __METHOD__); - // throw new \InvalidArgumentException(sprintf('A Closure must be passed to "%s()" when FILTER_CALLBACK is used, "%s" given.', __METHOD__, get_debug_type($options['options'] ?? null))); - } - - return filter_var($value, $filter, $options); - } - - /** - * Returns an iterator for parameters. - * - * @return \ArrayIterator - */ - #[\ReturnTypeWillChange] - public function getIterator() - { - return new \ArrayIterator($this->parameters); - } - - /** - * Returns the number of parameters. - * - * @return int - */ - #[\ReturnTypeWillChange] - public function count() - { - return \count($this->parameters); - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/README.md b/digital_doctor/vendor/symfony/http-foundation/README.md deleted file mode 100644 index 424f2c4..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/README.md +++ /dev/null @@ -1,28 +0,0 @@ -HttpFoundation Component -======================== - -The HttpFoundation component defines an object-oriented layer for the HTTP -specification. - -Sponsor -------- - -The HttpFoundation component for Symfony 5.4/6.0 is [backed][1] by [Laravel][2]. - -Laravel is a PHP web development framework that is passionate about maximum developer -happiness. Laravel is built using a variety of bespoke and Symfony based components. - -Help Symfony by [sponsoring][3] its development! - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/components/http_foundation.html) - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) - -[1]: https://symfony.com/backers -[2]: https://laravel.com/ -[3]: https://symfony.com/sponsor diff --git a/digital_doctor/vendor/symfony/http-foundation/RateLimiter/AbstractRequestRateLimiter.php b/digital_doctor/vendor/symfony/http-foundation/RateLimiter/AbstractRequestRateLimiter.php deleted file mode 100644 index a6dd993..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/RateLimiter/AbstractRequestRateLimiter.php +++ /dev/null @@ -1,71 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\RateLimiter; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\RateLimiter\LimiterInterface; -use Symfony\Component\RateLimiter\Policy\NoLimiter; -use Symfony\Component\RateLimiter\RateLimit; - -/** - * An implementation of RequestRateLimiterInterface that - * fits most use-cases. - * - * @author Wouter de Jong - */ -abstract class AbstractRequestRateLimiter implements RequestRateLimiterInterface -{ - public function consume(Request $request): RateLimit - { - $limiters = $this->getLimiters($request); - if (0 === \count($limiters)) { - $limiters = [new NoLimiter()]; - } - - $minimalRateLimit = null; - foreach ($limiters as $limiter) { - $rateLimit = $limiter->consume(1); - - $minimalRateLimit = $minimalRateLimit ? self::getMinimalRateLimit($minimalRateLimit, $rateLimit) : $rateLimit; - } - - return $minimalRateLimit; - } - - public function reset(Request $request): void - { - foreach ($this->getLimiters($request) as $limiter) { - $limiter->reset(); - } - } - - /** - * @return LimiterInterface[] a set of limiters using keys extracted from the request - */ - abstract protected function getLimiters(Request $request): array; - - private static function getMinimalRateLimit(RateLimit $first, RateLimit $second): RateLimit - { - if ($first->isAccepted() !== $second->isAccepted()) { - return $first->isAccepted() ? $second : $first; - } - - $firstRemainingTokens = $first->getRemainingTokens(); - $secondRemainingTokens = $second->getRemainingTokens(); - - if ($firstRemainingTokens === $secondRemainingTokens) { - return $first->getRetryAfter() < $second->getRetryAfter() ? $second : $first; - } - - return $firstRemainingTokens > $secondRemainingTokens ? $second : $first; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/RateLimiter/RequestRateLimiterInterface.php b/digital_doctor/vendor/symfony/http-foundation/RateLimiter/RequestRateLimiterInterface.php deleted file mode 100644 index 4c87a40..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/RateLimiter/RequestRateLimiterInterface.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\RateLimiter; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\RateLimiter\RateLimit; - -/** - * A special type of limiter that deals with requests. - * - * This allows to limit on different types of information - * from the requests. - * - * @author Wouter de Jong - */ -interface RequestRateLimiterInterface -{ - public function consume(Request $request): RateLimit; - - public function reset(Request $request): void; -} diff --git a/digital_doctor/vendor/symfony/http-foundation/RedirectResponse.php b/digital_doctor/vendor/symfony/http-foundation/RedirectResponse.php deleted file mode 100644 index 7b89f0f..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/RedirectResponse.php +++ /dev/null @@ -1,110 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * RedirectResponse represents an HTTP response doing a redirect. - * - * @author Fabien Potencier - */ -class RedirectResponse extends Response -{ - protected $targetUrl; - - /** - * Creates a redirect response so that it conforms to the rules defined for a redirect status code. - * - * @param string $url The URL to redirect to. The URL should be a full URL, with schema etc., - * but practically every browser redirects on paths only as well - * @param int $status The status code (302 by default) - * @param array $headers The headers (Location is always set to the given URL) - * - * @throws \InvalidArgumentException - * - * @see https://tools.ietf.org/html/rfc2616#section-10.3 - */ - public function __construct(string $url, int $status = 302, array $headers = []) - { - parent::__construct('', $status, $headers); - - $this->setTargetUrl($url); - - if (!$this->isRedirect()) { - throw new \InvalidArgumentException(sprintf('The HTTP status code is not a redirect ("%s" given).', $status)); - } - - if (301 == $status && !\array_key_exists('cache-control', array_change_key_case($headers, \CASE_LOWER))) { - $this->headers->remove('cache-control'); - } - } - - /** - * Factory method for chainability. - * - * @param string $url The URL to redirect to - * - * @return static - * - * @deprecated since Symfony 5.1, use __construct() instead. - */ - public static function create($url = '', int $status = 302, array $headers = []) - { - trigger_deprecation('symfony/http-foundation', '5.1', 'The "%s()" method is deprecated, use "new %s()" instead.', __METHOD__, static::class); - - return new static($url, $status, $headers); - } - - /** - * Returns the target URL. - * - * @return string - */ - public function getTargetUrl() - { - return $this->targetUrl; - } - - /** - * Sets the redirect target of this response. - * - * @return $this - * - * @throws \InvalidArgumentException - */ - public function setTargetUrl(string $url) - { - if ('' === $url) { - throw new \InvalidArgumentException('Cannot redirect to an empty URL.'); - } - - $this->targetUrl = $url; - - $this->setContent( - sprintf(' - - - - - - Redirecting to %1$s - - - Redirecting to %1$s. - -', htmlspecialchars($url, \ENT_QUOTES, 'UTF-8'))); - - $this->headers->set('Location', $url); - $this->headers->set('Content-Type', 'text/html; charset=utf-8'); - - return $this; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Request.php b/digital_doctor/vendor/symfony/http-foundation/Request.php deleted file mode 100644 index 75db030..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Request.php +++ /dev/null @@ -1,2172 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -use Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException; -use Symfony\Component\HttpFoundation\Exception\JsonException; -use Symfony\Component\HttpFoundation\Exception\SessionNotFoundException; -use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException; -use Symfony\Component\HttpFoundation\Session\SessionInterface; - -// Help opcache.preload discover always-needed symbols -class_exists(AcceptHeader::class); -class_exists(FileBag::class); -class_exists(HeaderBag::class); -class_exists(HeaderUtils::class); -class_exists(InputBag::class); -class_exists(ParameterBag::class); -class_exists(ServerBag::class); - -/** - * Request represents an HTTP request. - * - * The methods dealing with URL accept / return a raw path (% encoded): - * * getBasePath - * * getBaseUrl - * * getPathInfo - * * getRequestUri - * * getUri - * * getUriForPath - * - * @author Fabien Potencier - */ -class Request -{ - public const HEADER_FORWARDED = 0b000001; // When using RFC 7239 - public const HEADER_X_FORWARDED_FOR = 0b000010; - public const HEADER_X_FORWARDED_HOST = 0b000100; - public const HEADER_X_FORWARDED_PROTO = 0b001000; - public const HEADER_X_FORWARDED_PORT = 0b010000; - public const HEADER_X_FORWARDED_PREFIX = 0b100000; - - /** @deprecated since Symfony 5.2, use either "HEADER_X_FORWARDED_FOR | HEADER_X_FORWARDED_HOST | HEADER_X_FORWARDED_PORT | HEADER_X_FORWARDED_PROTO" or "HEADER_X_FORWARDED_AWS_ELB" or "HEADER_X_FORWARDED_TRAEFIK" constants instead. */ - public const HEADER_X_FORWARDED_ALL = 0b1011110; // All "X-Forwarded-*" headers sent by "usual" reverse proxy - public const HEADER_X_FORWARDED_AWS_ELB = 0b0011010; // AWS ELB doesn't send X-Forwarded-Host - public const HEADER_X_FORWARDED_TRAEFIK = 0b0111110; // All "X-Forwarded-*" headers sent by Traefik reverse proxy - - public const METHOD_HEAD = 'HEAD'; - public const METHOD_GET = 'GET'; - public const METHOD_POST = 'POST'; - public const METHOD_PUT = 'PUT'; - public const METHOD_PATCH = 'PATCH'; - public const METHOD_DELETE = 'DELETE'; - public const METHOD_PURGE = 'PURGE'; - public const METHOD_OPTIONS = 'OPTIONS'; - public const METHOD_TRACE = 'TRACE'; - public const METHOD_CONNECT = 'CONNECT'; - - /** - * @var string[] - */ - protected static $trustedProxies = []; - - /** - * @var string[] - */ - protected static $trustedHostPatterns = []; - - /** - * @var string[] - */ - protected static $trustedHosts = []; - - protected static $httpMethodParameterOverride = false; - - /** - * Custom parameters. - * - * @var ParameterBag - */ - public $attributes; - - /** - * Request body parameters ($_POST). - * - * @var InputBag - */ - public $request; - - /** - * Query string parameters ($_GET). - * - * @var InputBag - */ - public $query; - - /** - * Server and execution environment parameters ($_SERVER). - * - * @var ServerBag - */ - public $server; - - /** - * Uploaded files ($_FILES). - * - * @var FileBag - */ - public $files; - - /** - * Cookies ($_COOKIE). - * - * @var InputBag - */ - public $cookies; - - /** - * Headers (taken from the $_SERVER). - * - * @var HeaderBag - */ - public $headers; - - /** - * @var string|resource|false|null - */ - protected $content; - - /** - * @var array - */ - protected $languages; - - /** - * @var array - */ - protected $charsets; - - /** - * @var array - */ - protected $encodings; - - /** - * @var array - */ - protected $acceptableContentTypes; - - /** - * @var string - */ - protected $pathInfo; - - /** - * @var string - */ - protected $requestUri; - - /** - * @var string - */ - protected $baseUrl; - - /** - * @var string - */ - protected $basePath; - - /** - * @var string - */ - protected $method; - - /** - * @var string - */ - protected $format; - - /** - * @var SessionInterface|callable(): SessionInterface - */ - protected $session; - - /** - * @var string|null - */ - protected $locale; - - /** - * @var string - */ - protected $defaultLocale = 'en'; - - /** - * @var array - */ - protected static $formats; - - protected static $requestFactory; - - /** - * @var string|null - */ - private $preferredFormat; - private $isHostValid = true; - private $isForwardedValid = true; - - /** - * @var bool|null - */ - private $isSafeContentPreferred; - - private static $trustedHeaderSet = -1; - - private const FORWARDED_PARAMS = [ - self::HEADER_X_FORWARDED_FOR => 'for', - self::HEADER_X_FORWARDED_HOST => 'host', - self::HEADER_X_FORWARDED_PROTO => 'proto', - self::HEADER_X_FORWARDED_PORT => 'host', - ]; - - /** - * Names for headers that can be trusted when - * using trusted proxies. - * - * The FORWARDED header is the standard as of rfc7239. - * - * The other headers are non-standard, but widely used - * by popular reverse proxies (like Apache mod_proxy or Amazon EC2). - */ - private const TRUSTED_HEADERS = [ - self::HEADER_FORWARDED => 'FORWARDED', - self::HEADER_X_FORWARDED_FOR => 'X_FORWARDED_FOR', - self::HEADER_X_FORWARDED_HOST => 'X_FORWARDED_HOST', - self::HEADER_X_FORWARDED_PROTO => 'X_FORWARDED_PROTO', - self::HEADER_X_FORWARDED_PORT => 'X_FORWARDED_PORT', - self::HEADER_X_FORWARDED_PREFIX => 'X_FORWARDED_PREFIX', - ]; - - /** @var bool */ - private $isIisRewrite = false; - - /** - * @param array $query The GET parameters - * @param array $request The POST parameters - * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) - * @param array $cookies The COOKIE parameters - * @param array $files The FILES parameters - * @param array $server The SERVER parameters - * @param string|resource|null $content The raw body data - */ - public function __construct(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null) - { - $this->initialize($query, $request, $attributes, $cookies, $files, $server, $content); - } - - /** - * Sets the parameters for this request. - * - * This method also re-initializes all properties. - * - * @param array $query The GET parameters - * @param array $request The POST parameters - * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) - * @param array $cookies The COOKIE parameters - * @param array $files The FILES parameters - * @param array $server The SERVER parameters - * @param string|resource|null $content The raw body data - */ - public function initialize(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null) - { - $this->request = new InputBag($request); - $this->query = new InputBag($query); - $this->attributes = new ParameterBag($attributes); - $this->cookies = new InputBag($cookies); - $this->files = new FileBag($files); - $this->server = new ServerBag($server); - $this->headers = new HeaderBag($this->server->getHeaders()); - - $this->content = $content; - $this->languages = null; - $this->charsets = null; - $this->encodings = null; - $this->acceptableContentTypes = null; - $this->pathInfo = null; - $this->requestUri = null; - $this->baseUrl = null; - $this->basePath = null; - $this->method = null; - $this->format = null; - } - - /** - * Creates a new request with values from PHP's super globals. - * - * @return static - */ - public static function createFromGlobals() - { - $request = self::createRequestFromFactory($_GET, $_POST, [], $_COOKIE, $_FILES, $_SERVER); - - if (str_starts_with($request->headers->get('CONTENT_TYPE', ''), 'application/x-www-form-urlencoded') - && \in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), ['PUT', 'DELETE', 'PATCH']) - ) { - parse_str($request->getContent(), $data); - $request->request = new InputBag($data); - } - - return $request; - } - - /** - * Creates a Request based on a given URI and configuration. - * - * The information contained in the URI always take precedence - * over the other information (server and parameters). - * - * @param string $uri The URI - * @param string $method The HTTP method - * @param array $parameters The query (GET) or request (POST) parameters - * @param array $cookies The request cookies ($_COOKIE) - * @param array $files The request files ($_FILES) - * @param array $server The server parameters ($_SERVER) - * @param string|resource|null $content The raw body data - * - * @return static - */ - public static function create(string $uri, string $method = 'GET', array $parameters = [], array $cookies = [], array $files = [], array $server = [], $content = null) - { - $server = array_replace([ - 'SERVER_NAME' => 'localhost', - 'SERVER_PORT' => 80, - 'HTTP_HOST' => 'localhost', - 'HTTP_USER_AGENT' => 'Symfony', - 'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', - 'HTTP_ACCEPT_LANGUAGE' => 'en-us,en;q=0.5', - 'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7', - 'REMOTE_ADDR' => '127.0.0.1', - 'SCRIPT_NAME' => '', - 'SCRIPT_FILENAME' => '', - 'SERVER_PROTOCOL' => 'HTTP/1.1', - 'REQUEST_TIME' => time(), - 'REQUEST_TIME_FLOAT' => microtime(true), - ], $server); - - $server['PATH_INFO'] = ''; - $server['REQUEST_METHOD'] = strtoupper($method); - - $components = parse_url($uri); - if (isset($components['host'])) { - $server['SERVER_NAME'] = $components['host']; - $server['HTTP_HOST'] = $components['host']; - } - - if (isset($components['scheme'])) { - if ('https' === $components['scheme']) { - $server['HTTPS'] = 'on'; - $server['SERVER_PORT'] = 443; - } else { - unset($server['HTTPS']); - $server['SERVER_PORT'] = 80; - } - } - - if (isset($components['port'])) { - $server['SERVER_PORT'] = $components['port']; - $server['HTTP_HOST'] .= ':'.$components['port']; - } - - if (isset($components['user'])) { - $server['PHP_AUTH_USER'] = $components['user']; - } - - if (isset($components['pass'])) { - $server['PHP_AUTH_PW'] = $components['pass']; - } - - if (!isset($components['path'])) { - $components['path'] = '/'; - } - - switch (strtoupper($method)) { - case 'POST': - case 'PUT': - case 'DELETE': - if (!isset($server['CONTENT_TYPE'])) { - $server['CONTENT_TYPE'] = 'application/x-www-form-urlencoded'; - } - // no break - case 'PATCH': - $request = $parameters; - $query = []; - break; - default: - $request = []; - $query = $parameters; - break; - } - - $queryString = ''; - if (isset($components['query'])) { - parse_str(html_entity_decode($components['query']), $qs); - - if ($query) { - $query = array_replace($qs, $query); - $queryString = http_build_query($query, '', '&'); - } else { - $query = $qs; - $queryString = $components['query']; - } - } elseif ($query) { - $queryString = http_build_query($query, '', '&'); - } - - $server['REQUEST_URI'] = $components['path'].('' !== $queryString ? '?'.$queryString : ''); - $server['QUERY_STRING'] = $queryString; - - return self::createRequestFromFactory($query, $request, [], $cookies, $files, $server, $content); - } - - /** - * Sets a callable able to create a Request instance. - * - * This is mainly useful when you need to override the Request class - * to keep BC with an existing system. It should not be used for any - * other purpose. - */ - public static function setFactory(?callable $callable) - { - self::$requestFactory = $callable; - } - - /** - * Clones a request and overrides some of its parameters. - * - * @param array|null $query The GET parameters - * @param array|null $request The POST parameters - * @param array|null $attributes The request attributes (parameters parsed from the PATH_INFO, ...) - * @param array|null $cookies The COOKIE parameters - * @param array|null $files The FILES parameters - * @param array|null $server The SERVER parameters - * - * @return static - */ - public function duplicate(?array $query = null, ?array $request = null, ?array $attributes = null, ?array $cookies = null, ?array $files = null, ?array $server = null) - { - $dup = clone $this; - if (null !== $query) { - $dup->query = new InputBag($query); - } - if (null !== $request) { - $dup->request = new InputBag($request); - } - if (null !== $attributes) { - $dup->attributes = new ParameterBag($attributes); - } - if (null !== $cookies) { - $dup->cookies = new InputBag($cookies); - } - if (null !== $files) { - $dup->files = new FileBag($files); - } - if (null !== $server) { - $dup->server = new ServerBag($server); - $dup->headers = new HeaderBag($dup->server->getHeaders()); - } - $dup->languages = null; - $dup->charsets = null; - $dup->encodings = null; - $dup->acceptableContentTypes = null; - $dup->pathInfo = null; - $dup->requestUri = null; - $dup->baseUrl = null; - $dup->basePath = null; - $dup->method = null; - $dup->format = null; - - if (!$dup->get('_format') && $this->get('_format')) { - $dup->attributes->set('_format', $this->get('_format')); - } - - if (!$dup->getRequestFormat(null)) { - $dup->setRequestFormat($this->getRequestFormat(null)); - } - - return $dup; - } - - /** - * Clones the current request. - * - * Note that the session is not cloned as duplicated requests - * are most of the time sub-requests of the main one. - */ - public function __clone() - { - $this->query = clone $this->query; - $this->request = clone $this->request; - $this->attributes = clone $this->attributes; - $this->cookies = clone $this->cookies; - $this->files = clone $this->files; - $this->server = clone $this->server; - $this->headers = clone $this->headers; - } - - /** - * Returns the request as a string. - * - * @return string - */ - public function __toString() - { - $content = $this->getContent(); - - $cookieHeader = ''; - $cookies = []; - - foreach ($this->cookies as $k => $v) { - $cookies[] = \is_array($v) ? http_build_query([$k => $v], '', '; ', \PHP_QUERY_RFC3986) : "$k=$v"; - } - - if ($cookies) { - $cookieHeader = 'Cookie: '.implode('; ', $cookies)."\r\n"; - } - - return - sprintf('%s %s %s', $this->getMethod(), $this->getRequestUri(), $this->server->get('SERVER_PROTOCOL'))."\r\n". - $this->headers. - $cookieHeader."\r\n". - $content; - } - - /** - * Overrides the PHP global variables according to this request instance. - * - * It overrides $_GET, $_POST, $_REQUEST, $_SERVER, $_COOKIE. - * $_FILES is never overridden, see rfc1867 - */ - public function overrideGlobals() - { - $this->server->set('QUERY_STRING', static::normalizeQueryString(http_build_query($this->query->all(), '', '&'))); - - $_GET = $this->query->all(); - $_POST = $this->request->all(); - $_SERVER = $this->server->all(); - $_COOKIE = $this->cookies->all(); - - foreach ($this->headers->all() as $key => $value) { - $key = strtoupper(str_replace('-', '_', $key)); - if (\in_array($key, ['CONTENT_TYPE', 'CONTENT_LENGTH', 'CONTENT_MD5'], true)) { - $_SERVER[$key] = implode(', ', $value); - } else { - $_SERVER['HTTP_'.$key] = implode(', ', $value); - } - } - - $request = ['g' => $_GET, 'p' => $_POST, 'c' => $_COOKIE]; - - $requestOrder = \ini_get('request_order') ?: \ini_get('variables_order'); - $requestOrder = preg_replace('#[^cgp]#', '', strtolower($requestOrder)) ?: 'gp'; - - $_REQUEST = [[]]; - - foreach (str_split($requestOrder) as $order) { - $_REQUEST[] = $request[$order]; - } - - $_REQUEST = array_merge(...$_REQUEST); - } - - /** - * Sets a list of trusted proxies. - * - * You should only list the reverse proxies that you manage directly. - * - * @param array $proxies A list of trusted proxies, the string 'REMOTE_ADDR' will be replaced with $_SERVER['REMOTE_ADDR'] - * @param int $trustedHeaderSet A bit field of Request::HEADER_*, to set which headers to trust from your proxies - */ - public static function setTrustedProxies(array $proxies, int $trustedHeaderSet) - { - if (self::HEADER_X_FORWARDED_ALL === $trustedHeaderSet) { - trigger_deprecation('symfony/http-foundation', '5.2', 'The "HEADER_X_FORWARDED_ALL" constant is deprecated, use either "HEADER_X_FORWARDED_FOR | HEADER_X_FORWARDED_HOST | HEADER_X_FORWARDED_PORT | HEADER_X_FORWARDED_PROTO" or "HEADER_X_FORWARDED_AWS_ELB" or "HEADER_X_FORWARDED_TRAEFIK" constants instead.'); - } - self::$trustedProxies = array_reduce($proxies, function ($proxies, $proxy) { - if ('REMOTE_ADDR' !== $proxy) { - $proxies[] = $proxy; - } elseif (isset($_SERVER['REMOTE_ADDR'])) { - $proxies[] = $_SERVER['REMOTE_ADDR']; - } - - return $proxies; - }, []); - self::$trustedHeaderSet = $trustedHeaderSet; - } - - /** - * Gets the list of trusted proxies. - * - * @return array - */ - public static function getTrustedProxies() - { - return self::$trustedProxies; - } - - /** - * Gets the set of trusted headers from trusted proxies. - * - * @return int A bit field of Request::HEADER_* that defines which headers are trusted from your proxies - */ - public static function getTrustedHeaderSet() - { - return self::$trustedHeaderSet; - } - - /** - * Sets a list of trusted host patterns. - * - * You should only list the hosts you manage using regexs. - * - * @param array $hostPatterns A list of trusted host patterns - */ - public static function setTrustedHosts(array $hostPatterns) - { - self::$trustedHostPatterns = array_map(function ($hostPattern) { - return sprintf('{%s}i', $hostPattern); - }, $hostPatterns); - // we need to reset trusted hosts on trusted host patterns change - self::$trustedHosts = []; - } - - /** - * Gets the list of trusted host patterns. - * - * @return array - */ - public static function getTrustedHosts() - { - return self::$trustedHostPatterns; - } - - /** - * Normalizes a query string. - * - * It builds a normalized query string, where keys/value pairs are alphabetized, - * have consistent escaping and unneeded delimiters are removed. - * - * @return string - */ - public static function normalizeQueryString(?string $qs) - { - if ('' === ($qs ?? '')) { - return ''; - } - - $qs = HeaderUtils::parseQuery($qs); - ksort($qs); - - return http_build_query($qs, '', '&', \PHP_QUERY_RFC3986); - } - - /** - * Enables support for the _method request parameter to determine the intended HTTP method. - * - * Be warned that enabling this feature might lead to CSRF issues in your code. - * Check that you are using CSRF tokens when required. - * If the HTTP method parameter override is enabled, an html-form with method "POST" can be altered - * and used to send a "PUT" or "DELETE" request via the _method request parameter. - * If these methods are not protected against CSRF, this presents a possible vulnerability. - * - * The HTTP method can only be overridden when the real HTTP method is POST. - */ - public static function enableHttpMethodParameterOverride() - { - self::$httpMethodParameterOverride = true; - } - - /** - * Checks whether support for the _method request parameter is enabled. - * - * @return bool - */ - public static function getHttpMethodParameterOverride() - { - return self::$httpMethodParameterOverride; - } - - /** - * Gets a "parameter" value from any bag. - * - * This method is mainly useful for libraries that want to provide some flexibility. If you don't need the - * flexibility in controllers, it is better to explicitly get request parameters from the appropriate - * public property instead (attributes, query, request). - * - * Order of precedence: PATH (routing placeholders or custom attributes), GET, POST - * - * @param mixed $default The default value if the parameter key does not exist - * - * @return mixed - * - * @internal since Symfony 5.4, use explicit input sources instead - */ - public function get(string $key, $default = null) - { - if ($this !== $result = $this->attributes->get($key, $this)) { - return $result; - } - - if ($this->query->has($key)) { - return $this->query->all()[$key]; - } - - if ($this->request->has($key)) { - return $this->request->all()[$key]; - } - - return $default; - } - - /** - * Gets the Session. - * - * @return SessionInterface - */ - public function getSession() - { - $session = $this->session; - if (!$session instanceof SessionInterface && null !== $session) { - $this->setSession($session = $session()); - } - - if (null === $session) { - throw new SessionNotFoundException('Session has not been set.'); - } - - return $session; - } - - /** - * Whether the request contains a Session which was started in one of the - * previous requests. - * - * @return bool - */ - public function hasPreviousSession() - { - // the check for $this->session avoids malicious users trying to fake a session cookie with proper name - return $this->hasSession() && $this->cookies->has($this->getSession()->getName()); - } - - /** - * Whether the request contains a Session object. - * - * This method does not give any information about the state of the session object, - * like whether the session is started or not. It is just a way to check if this Request - * is associated with a Session instance. - * - * @param bool $skipIfUninitialized When true, ignores factories injected by `setSessionFactory` - * - * @return bool - */ - public function hasSession(/* bool $skipIfUninitialized = false */) - { - $skipIfUninitialized = \func_num_args() > 0 ? func_get_arg(0) : false; - - return null !== $this->session && (!$skipIfUninitialized || $this->session instanceof SessionInterface); - } - - public function setSession(SessionInterface $session) - { - $this->session = $session; - } - - /** - * @internal - * - * @param callable(): SessionInterface $factory - */ - public function setSessionFactory(callable $factory) - { - $this->session = $factory; - } - - /** - * Returns the client IP addresses. - * - * In the returned array the most trusted IP address is first, and the - * least trusted one last. The "real" client IP address is the last one, - * but this is also the least trusted one. Trusted proxies are stripped. - * - * Use this method carefully; you should use getClientIp() instead. - * - * @return array - * - * @see getClientIp() - */ - public function getClientIps() - { - $ip = $this->server->get('REMOTE_ADDR'); - - if (!$this->isFromTrustedProxy()) { - return [$ip]; - } - - return $this->getTrustedValues(self::HEADER_X_FORWARDED_FOR, $ip) ?: [$ip]; - } - - /** - * Returns the client IP address. - * - * This method can read the client IP address from the "X-Forwarded-For" header - * when trusted proxies were set via "setTrustedProxies()". The "X-Forwarded-For" - * header value is a comma+space separated list of IP addresses, the left-most - * being the original client, and each successive proxy that passed the request - * adding the IP address where it received the request from. - * - * If your reverse proxy uses a different header name than "X-Forwarded-For", - * ("Client-Ip" for instance), configure it via the $trustedHeaderSet - * argument of the Request::setTrustedProxies() method instead. - * - * @return string|null - * - * @see getClientIps() - * @see https://wikipedia.org/wiki/X-Forwarded-For - */ - public function getClientIp() - { - $ipAddresses = $this->getClientIps(); - - return $ipAddresses[0]; - } - - /** - * Returns current script name. - * - * @return string - */ - public function getScriptName() - { - return $this->server->get('SCRIPT_NAME', $this->server->get('ORIG_SCRIPT_NAME', '')); - } - - /** - * Returns the path being requested relative to the executed script. - * - * The path info always starts with a /. - * - * Suppose this request is instantiated from /mysite on localhost: - * - * * http://localhost/mysite returns an empty string - * * http://localhost/mysite/about returns '/about' - * * http://localhost/mysite/enco%20ded returns '/enco%20ded' - * * http://localhost/mysite/about?var=1 returns '/about' - * - * @return string The raw path (i.e. not urldecoded) - */ - public function getPathInfo() - { - if (null === $this->pathInfo) { - $this->pathInfo = $this->preparePathInfo(); - } - - return $this->pathInfo; - } - - /** - * Returns the root path from which this request is executed. - * - * Suppose that an index.php file instantiates this request object: - * - * * http://localhost/index.php returns an empty string - * * http://localhost/index.php/page returns an empty string - * * http://localhost/web/index.php returns '/web' - * * http://localhost/we%20b/index.php returns '/we%20b' - * - * @return string The raw path (i.e. not urldecoded) - */ - public function getBasePath() - { - if (null === $this->basePath) { - $this->basePath = $this->prepareBasePath(); - } - - return $this->basePath; - } - - /** - * Returns the root URL from which this request is executed. - * - * The base URL never ends with a /. - * - * This is similar to getBasePath(), except that it also includes the - * script filename (e.g. index.php) if one exists. - * - * @return string The raw URL (i.e. not urldecoded) - */ - public function getBaseUrl() - { - $trustedPrefix = ''; - - // the proxy prefix must be prepended to any prefix being needed at the webserver level - if ($this->isFromTrustedProxy() && $trustedPrefixValues = $this->getTrustedValues(self::HEADER_X_FORWARDED_PREFIX)) { - $trustedPrefix = rtrim($trustedPrefixValues[0], '/'); - } - - return $trustedPrefix.$this->getBaseUrlReal(); - } - - /** - * Returns the real base URL received by the webserver from which this request is executed. - * The URL does not include trusted reverse proxy prefix. - * - * @return string The raw URL (i.e. not urldecoded) - */ - private function getBaseUrlReal(): string - { - if (null === $this->baseUrl) { - $this->baseUrl = $this->prepareBaseUrl(); - } - - return $this->baseUrl; - } - - /** - * Gets the request's scheme. - * - * @return string - */ - public function getScheme() - { - return $this->isSecure() ? 'https' : 'http'; - } - - /** - * Returns the port on which the request is made. - * - * This method can read the client port from the "X-Forwarded-Port" header - * when trusted proxies were set via "setTrustedProxies()". - * - * The "X-Forwarded-Port" header must contain the client port. - * - * @return int|string|null Can be a string if fetched from the server bag - */ - public function getPort() - { - if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_PORT)) { - $host = $host[0]; - } elseif ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_HOST)) { - $host = $host[0]; - } elseif (!$host = $this->headers->get('HOST')) { - return $this->server->get('SERVER_PORT'); - } - - if ('[' === $host[0]) { - $pos = strpos($host, ':', strrpos($host, ']')); - } else { - $pos = strrpos($host, ':'); - } - - if (false !== $pos && $port = substr($host, $pos + 1)) { - return (int) $port; - } - - return 'https' === $this->getScheme() ? 443 : 80; - } - - /** - * Returns the user. - * - * @return string|null - */ - public function getUser() - { - return $this->headers->get('PHP_AUTH_USER'); - } - - /** - * Returns the password. - * - * @return string|null - */ - public function getPassword() - { - return $this->headers->get('PHP_AUTH_PW'); - } - - /** - * Gets the user info. - * - * @return string|null A user name if any and, optionally, scheme-specific information about how to gain authorization to access the server - */ - public function getUserInfo() - { - $userinfo = $this->getUser(); - - $pass = $this->getPassword(); - if ('' != $pass) { - $userinfo .= ":$pass"; - } - - return $userinfo; - } - - /** - * Returns the HTTP host being requested. - * - * The port name will be appended to the host if it's non-standard. - * - * @return string - */ - public function getHttpHost() - { - $scheme = $this->getScheme(); - $port = $this->getPort(); - - if (('http' == $scheme && 80 == $port) || ('https' == $scheme && 443 == $port)) { - return $this->getHost(); - } - - return $this->getHost().':'.$port; - } - - /** - * Returns the requested URI (path and query string). - * - * @return string The raw URI (i.e. not URI decoded) - */ - public function getRequestUri() - { - if (null === $this->requestUri) { - $this->requestUri = $this->prepareRequestUri(); - } - - return $this->requestUri; - } - - /** - * Gets the scheme and HTTP host. - * - * If the URL was called with basic authentication, the user - * and the password are not added to the generated string. - * - * @return string - */ - public function getSchemeAndHttpHost() - { - return $this->getScheme().'://'.$this->getHttpHost(); - } - - /** - * Generates a normalized URI (URL) for the Request. - * - * @return string - * - * @see getQueryString() - */ - public function getUri() - { - if (null !== $qs = $this->getQueryString()) { - $qs = '?'.$qs; - } - - return $this->getSchemeAndHttpHost().$this->getBaseUrl().$this->getPathInfo().$qs; - } - - /** - * Generates a normalized URI for the given path. - * - * @param string $path A path to use instead of the current one - * - * @return string - */ - public function getUriForPath(string $path) - { - return $this->getSchemeAndHttpHost().$this->getBaseUrl().$path; - } - - /** - * Returns the path as relative reference from the current Request path. - * - * Only the URIs path component (no schema, host etc.) is relevant and must be given. - * Both paths must be absolute and not contain relative parts. - * Relative URLs from one resource to another are useful when generating self-contained downloadable document archives. - * Furthermore, they can be used to reduce the link size in documents. - * - * Example target paths, given a base path of "/a/b/c/d": - * - "/a/b/c/d" -> "" - * - "/a/b/c/" -> "./" - * - "/a/b/" -> "../" - * - "/a/b/c/other" -> "other" - * - "/a/x/y" -> "../../x/y" - * - * @return string - */ - public function getRelativeUriForPath(string $path) - { - // be sure that we are dealing with an absolute path - if (!isset($path[0]) || '/' !== $path[0]) { - return $path; - } - - if ($path === $basePath = $this->getPathInfo()) { - return ''; - } - - $sourceDirs = explode('/', isset($basePath[0]) && '/' === $basePath[0] ? substr($basePath, 1) : $basePath); - $targetDirs = explode('/', substr($path, 1)); - array_pop($sourceDirs); - $targetFile = array_pop($targetDirs); - - foreach ($sourceDirs as $i => $dir) { - if (isset($targetDirs[$i]) && $dir === $targetDirs[$i]) { - unset($sourceDirs[$i], $targetDirs[$i]); - } else { - break; - } - } - - $targetDirs[] = $targetFile; - $path = str_repeat('../', \count($sourceDirs)).implode('/', $targetDirs); - - // A reference to the same base directory or an empty subdirectory must be prefixed with "./". - // This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used - // as the first segment of a relative-path reference, as it would be mistaken for a scheme name - // (see https://tools.ietf.org/html/rfc3986#section-4.2). - return !isset($path[0]) || '/' === $path[0] - || false !== ($colonPos = strpos($path, ':')) && ($colonPos < ($slashPos = strpos($path, '/')) || false === $slashPos) - ? "./$path" : $path; - } - - /** - * Generates the normalized query string for the Request. - * - * It builds a normalized query string, where keys/value pairs are alphabetized - * and have consistent escaping. - * - * @return string|null - */ - public function getQueryString() - { - $qs = static::normalizeQueryString($this->server->get('QUERY_STRING')); - - return '' === $qs ? null : $qs; - } - - /** - * Checks whether the request is secure or not. - * - * This method can read the client protocol from the "X-Forwarded-Proto" header - * when trusted proxies were set via "setTrustedProxies()". - * - * The "X-Forwarded-Proto" header must contain the protocol: "https" or "http". - * - * @return bool - */ - public function isSecure() - { - if ($this->isFromTrustedProxy() && $proto = $this->getTrustedValues(self::HEADER_X_FORWARDED_PROTO)) { - return \in_array(strtolower($proto[0]), ['https', 'on', 'ssl', '1'], true); - } - - $https = $this->server->get('HTTPS'); - - return !empty($https) && 'off' !== strtolower($https); - } - - /** - * Returns the host name. - * - * This method can read the client host name from the "X-Forwarded-Host" header - * when trusted proxies were set via "setTrustedProxies()". - * - * The "X-Forwarded-Host" header must contain the client host name. - * - * @return string - * - * @throws SuspiciousOperationException when the host name is invalid or not trusted - */ - public function getHost() - { - if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_HOST)) { - $host = $host[0]; - } elseif (!$host = $this->headers->get('HOST')) { - if (!$host = $this->server->get('SERVER_NAME')) { - $host = $this->server->get('SERVER_ADDR', ''); - } - } - - // trim and remove port number from host - // host is lowercase as per RFC 952/2181 - $host = strtolower(preg_replace('/:\d+$/', '', trim($host))); - - // as the host can come from the user (HTTP_HOST and depending on the configuration, SERVER_NAME too can come from the user) - // check that it does not contain forbidden characters (see RFC 952 and RFC 2181) - // use preg_replace() instead of preg_match() to prevent DoS attacks with long host names - if ($host && '' !== preg_replace('/(?:^\[)?[a-zA-Z0-9-:\]_]+\.?/', '', $host)) { - if (!$this->isHostValid) { - return ''; - } - $this->isHostValid = false; - - throw new SuspiciousOperationException(sprintf('Invalid Host "%s".', $host)); - } - - if (\count(self::$trustedHostPatterns) > 0) { - // to avoid host header injection attacks, you should provide a list of trusted host patterns - - if (\in_array($host, self::$trustedHosts)) { - return $host; - } - - foreach (self::$trustedHostPatterns as $pattern) { - if (preg_match($pattern, $host)) { - self::$trustedHosts[] = $host; - - return $host; - } - } - - if (!$this->isHostValid) { - return ''; - } - $this->isHostValid = false; - - throw new SuspiciousOperationException(sprintf('Untrusted Host "%s".', $host)); - } - - return $host; - } - - /** - * Sets the request method. - */ - public function setMethod(string $method) - { - $this->method = null; - $this->server->set('REQUEST_METHOD', $method); - } - - /** - * Gets the request "intended" method. - * - * If the X-HTTP-Method-Override header is set, and if the method is a POST, - * then it is used to determine the "real" intended HTTP method. - * - * The _method request parameter can also be used to determine the HTTP method, - * but only if enableHttpMethodParameterOverride() has been called. - * - * The method is always an uppercased string. - * - * @return string - * - * @see getRealMethod() - */ - public function getMethod() - { - if (null !== $this->method) { - return $this->method; - } - - $this->method = strtoupper($this->server->get('REQUEST_METHOD', 'GET')); - - if ('POST' !== $this->method) { - return $this->method; - } - - $method = $this->headers->get('X-HTTP-METHOD-OVERRIDE'); - - if (!$method && self::$httpMethodParameterOverride) { - $method = $this->request->get('_method', $this->query->get('_method', 'POST')); - } - - if (!\is_string($method)) { - return $this->method; - } - - $method = strtoupper($method); - - if (\in_array($method, ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'PATCH', 'PURGE', 'TRACE'], true)) { - return $this->method = $method; - } - - if (!preg_match('/^[A-Z]++$/D', $method)) { - throw new SuspiciousOperationException(sprintf('Invalid method override "%s".', $method)); - } - - return $this->method = $method; - } - - /** - * Gets the "real" request method. - * - * @return string - * - * @see getMethod() - */ - public function getRealMethod() - { - return strtoupper($this->server->get('REQUEST_METHOD', 'GET')); - } - - /** - * Gets the mime type associated with the format. - * - * @return string|null - */ - public function getMimeType(string $format) - { - if (null === static::$formats) { - static::initializeFormats(); - } - - return isset(static::$formats[$format]) ? static::$formats[$format][0] : null; - } - - /** - * Gets the mime types associated with the format. - * - * @return array - */ - public static function getMimeTypes(string $format) - { - if (null === static::$formats) { - static::initializeFormats(); - } - - return static::$formats[$format] ?? []; - } - - /** - * Gets the format associated with the mime type. - * - * @return string|null - */ - public function getFormat(?string $mimeType) - { - $canonicalMimeType = null; - if ($mimeType && false !== $pos = strpos($mimeType, ';')) { - $canonicalMimeType = trim(substr($mimeType, 0, $pos)); - } - - if (null === static::$formats) { - static::initializeFormats(); - } - - foreach (static::$formats as $format => $mimeTypes) { - if (\in_array($mimeType, (array) $mimeTypes)) { - return $format; - } - if (null !== $canonicalMimeType && \in_array($canonicalMimeType, (array) $mimeTypes)) { - return $format; - } - } - - return null; - } - - /** - * Associates a format with mime types. - * - * @param string|array $mimeTypes The associated mime types (the preferred one must be the first as it will be used as the content type) - */ - public function setFormat(?string $format, $mimeTypes) - { - if (null === static::$formats) { - static::initializeFormats(); - } - - static::$formats[$format] = \is_array($mimeTypes) ? $mimeTypes : [$mimeTypes]; - } - - /** - * Gets the request format. - * - * Here is the process to determine the format: - * - * * format defined by the user (with setRequestFormat()) - * * _format request attribute - * * $default - * - * @see getPreferredFormat - * - * @return string|null - */ - public function getRequestFormat(?string $default = 'html') - { - if (null === $this->format) { - $this->format = $this->attributes->get('_format'); - } - - return $this->format ?? $default; - } - - /** - * Sets the request format. - */ - public function setRequestFormat(?string $format) - { - $this->format = $format; - } - - /** - * Gets the format associated with the request. - * - * @return string|null - */ - public function getContentType() - { - return $this->getFormat($this->headers->get('CONTENT_TYPE', '')); - } - - /** - * Sets the default locale. - */ - public function setDefaultLocale(string $locale) - { - $this->defaultLocale = $locale; - - if (null === $this->locale) { - $this->setPhpDefaultLocale($locale); - } - } - - /** - * Get the default locale. - * - * @return string - */ - public function getDefaultLocale() - { - return $this->defaultLocale; - } - - /** - * Sets the locale. - */ - public function setLocale(string $locale) - { - $this->setPhpDefaultLocale($this->locale = $locale); - } - - /** - * Get the locale. - * - * @return string - */ - public function getLocale() - { - return $this->locale ?? $this->defaultLocale; - } - - /** - * Checks if the request method is of specified type. - * - * @param string $method Uppercase request method (GET, POST etc) - * - * @return bool - */ - public function isMethod(string $method) - { - return $this->getMethod() === strtoupper($method); - } - - /** - * Checks whether or not the method is safe. - * - * @see https://tools.ietf.org/html/rfc7231#section-4.2.1 - * - * @return bool - */ - public function isMethodSafe() - { - return \in_array($this->getMethod(), ['GET', 'HEAD', 'OPTIONS', 'TRACE']); - } - - /** - * Checks whether or not the method is idempotent. - * - * @return bool - */ - public function isMethodIdempotent() - { - return \in_array($this->getMethod(), ['HEAD', 'GET', 'PUT', 'DELETE', 'TRACE', 'OPTIONS', 'PURGE']); - } - - /** - * Checks whether the method is cacheable or not. - * - * @see https://tools.ietf.org/html/rfc7231#section-4.2.3 - * - * @return bool - */ - public function isMethodCacheable() - { - return \in_array($this->getMethod(), ['GET', 'HEAD']); - } - - /** - * Returns the protocol version. - * - * If the application is behind a proxy, the protocol version used in the - * requests between the client and the proxy and between the proxy and the - * server might be different. This returns the former (from the "Via" header) - * if the proxy is trusted (see "setTrustedProxies()"), otherwise it returns - * the latter (from the "SERVER_PROTOCOL" server parameter). - * - * @return string|null - */ - public function getProtocolVersion() - { - if ($this->isFromTrustedProxy()) { - preg_match('~^(HTTP/)?([1-9]\.[0-9]) ~', $this->headers->get('Via') ?? '', $matches); - - if ($matches) { - return 'HTTP/'.$matches[2]; - } - } - - return $this->server->get('SERVER_PROTOCOL'); - } - - /** - * Returns the request body content. - * - * @param bool $asResource If true, a resource will be returned - * - * @return string|resource - */ - public function getContent(bool $asResource = false) - { - $currentContentIsResource = \is_resource($this->content); - - if (true === $asResource) { - if ($currentContentIsResource) { - rewind($this->content); - - return $this->content; - } - - // Content passed in parameter (test) - if (\is_string($this->content)) { - $resource = fopen('php://temp', 'r+'); - fwrite($resource, $this->content); - rewind($resource); - - return $resource; - } - - $this->content = false; - - return fopen('php://input', 'r'); - } - - if ($currentContentIsResource) { - rewind($this->content); - - return stream_get_contents($this->content); - } - - if (null === $this->content || false === $this->content) { - $this->content = file_get_contents('php://input'); - } - - return $this->content; - } - - /** - * Gets the request body decoded as array, typically from a JSON payload. - * - * @return array - * - * @throws JsonException When the body cannot be decoded to an array - */ - public function toArray() - { - if ('' === $content = $this->getContent()) { - throw new JsonException('Request body is empty.'); - } - - try { - $content = json_decode($content, true, 512, \JSON_BIGINT_AS_STRING | (\PHP_VERSION_ID >= 70300 ? \JSON_THROW_ON_ERROR : 0)); - } catch (\JsonException $e) { - throw new JsonException('Could not decode request body.', $e->getCode(), $e); - } - - if (\PHP_VERSION_ID < 70300 && \JSON_ERROR_NONE !== json_last_error()) { - throw new JsonException('Could not decode request body: '.json_last_error_msg(), json_last_error()); - } - - if (!\is_array($content)) { - throw new JsonException(sprintf('JSON content was expected to decode to an array, "%s" returned.', get_debug_type($content))); - } - - return $content; - } - - /** - * Gets the Etags. - * - * @return array - */ - public function getETags() - { - return preg_split('/\s*,\s*/', $this->headers->get('If-None-Match', ''), -1, \PREG_SPLIT_NO_EMPTY); - } - - /** - * @return bool - */ - public function isNoCache() - { - return $this->headers->hasCacheControlDirective('no-cache') || 'no-cache' == $this->headers->get('Pragma'); - } - - /** - * Gets the preferred format for the response by inspecting, in the following order: - * * the request format set using setRequestFormat; - * * the values of the Accept HTTP header. - * - * Note that if you use this method, you should send the "Vary: Accept" header - * in the response to prevent any issues with intermediary HTTP caches. - */ - public function getPreferredFormat(?string $default = 'html'): ?string - { - if (null !== $this->preferredFormat || null !== $this->preferredFormat = $this->getRequestFormat(null)) { - return $this->preferredFormat; - } - - foreach ($this->getAcceptableContentTypes() as $mimeType) { - if ($this->preferredFormat = $this->getFormat($mimeType)) { - return $this->preferredFormat; - } - } - - return $default; - } - - /** - * Returns the preferred language. - * - * @param string[] $locales An array of ordered available locales - * - * @return string|null - */ - public function getPreferredLanguage(?array $locales = null) - { - $preferredLanguages = $this->getLanguages(); - - if (empty($locales)) { - return $preferredLanguages[0] ?? null; - } - - if (!$preferredLanguages) { - return $locales[0]; - } - - $extendedPreferredLanguages = []; - foreach ($preferredLanguages as $language) { - $extendedPreferredLanguages[] = $language; - if (false !== $position = strpos($language, '_')) { - $superLanguage = substr($language, 0, $position); - if (!\in_array($superLanguage, $preferredLanguages)) { - $extendedPreferredLanguages[] = $superLanguage; - } - } - } - - $preferredLanguages = array_values(array_intersect($extendedPreferredLanguages, $locales)); - - return $preferredLanguages[0] ?? $locales[0]; - } - - /** - * Gets a list of languages acceptable by the client browser ordered in the user browser preferences. - * - * @return array - */ - public function getLanguages() - { - if (null !== $this->languages) { - return $this->languages; - } - - $languages = AcceptHeader::fromString($this->headers->get('Accept-Language'))->all(); - $this->languages = []; - foreach ($languages as $acceptHeaderItem) { - $lang = $acceptHeaderItem->getValue(); - if (str_contains($lang, '-')) { - $codes = explode('-', $lang); - if ('i' === $codes[0]) { - // Language not listed in ISO 639 that are not variants - // of any listed language, which can be registered with the - // i-prefix, such as i-cherokee - if (\count($codes) > 1) { - $lang = $codes[1]; - } - } else { - for ($i = 0, $max = \count($codes); $i < $max; ++$i) { - if (0 === $i) { - $lang = strtolower($codes[0]); - } else { - $lang .= '_'.strtoupper($codes[$i]); - } - } - } - } - - $this->languages[] = $lang; - } - - return $this->languages; - } - - /** - * Gets a list of charsets acceptable by the client browser in preferable order. - * - * @return array - */ - public function getCharsets() - { - if (null !== $this->charsets) { - return $this->charsets; - } - - return $this->charsets = array_map('strval', array_keys(AcceptHeader::fromString($this->headers->get('Accept-Charset'))->all())); - } - - /** - * Gets a list of encodings acceptable by the client browser in preferable order. - * - * @return array - */ - public function getEncodings() - { - if (null !== $this->encodings) { - return $this->encodings; - } - - return $this->encodings = array_map('strval', array_keys(AcceptHeader::fromString($this->headers->get('Accept-Encoding'))->all())); - } - - /** - * Gets a list of content types acceptable by the client browser in preferable order. - * - * @return array - */ - public function getAcceptableContentTypes() - { - if (null !== $this->acceptableContentTypes) { - return $this->acceptableContentTypes; - } - - return $this->acceptableContentTypes = array_map('strval', array_keys(AcceptHeader::fromString($this->headers->get('Accept'))->all())); - } - - /** - * Returns true if the request is an XMLHttpRequest. - * - * It works if your JavaScript library sets an X-Requested-With HTTP header. - * It is known to work with common JavaScript frameworks: - * - * @see https://wikipedia.org/wiki/List_of_Ajax_frameworks#JavaScript - * - * @return bool - */ - public function isXmlHttpRequest() - { - return 'XMLHttpRequest' == $this->headers->get('X-Requested-With'); - } - - /** - * Checks whether the client browser prefers safe content or not according to RFC8674. - * - * @see https://tools.ietf.org/html/rfc8674 - */ - public function preferSafeContent(): bool - { - if (null !== $this->isSafeContentPreferred) { - return $this->isSafeContentPreferred; - } - - if (!$this->isSecure()) { - // see https://tools.ietf.org/html/rfc8674#section-3 - return $this->isSafeContentPreferred = false; - } - - return $this->isSafeContentPreferred = AcceptHeader::fromString($this->headers->get('Prefer'))->has('safe'); - } - - /* - * The following methods are derived from code of the Zend Framework (1.10dev - 2010-01-24) - * - * Code subject to the new BSD license (https://framework.zend.com/license). - * - * Copyright (c) 2005-2010 Zend Technologies USA Inc. (https://www.zend.com/) - */ - - protected function prepareRequestUri() - { - $requestUri = ''; - - if ($this->isIisRewrite() && '' != $this->server->get('UNENCODED_URL')) { - // IIS7 with URL Rewrite: make sure we get the unencoded URL (double slash problem) - $requestUri = $this->server->get('UNENCODED_URL'); - $this->server->remove('UNENCODED_URL'); - } elseif ($this->server->has('REQUEST_URI')) { - $requestUri = $this->server->get('REQUEST_URI'); - - if ('' !== $requestUri && '/' === $requestUri[0]) { - // To only use path and query remove the fragment. - if (false !== $pos = strpos($requestUri, '#')) { - $requestUri = substr($requestUri, 0, $pos); - } - } else { - // HTTP proxy reqs setup request URI with scheme and host [and port] + the URL path, - // only use URL path. - $uriComponents = parse_url($requestUri); - - if (isset($uriComponents['path'])) { - $requestUri = $uriComponents['path']; - } - - if (isset($uriComponents['query'])) { - $requestUri .= '?'.$uriComponents['query']; - } - } - } elseif ($this->server->has('ORIG_PATH_INFO')) { - // IIS 5.0, PHP as CGI - $requestUri = $this->server->get('ORIG_PATH_INFO'); - if ('' != $this->server->get('QUERY_STRING')) { - $requestUri .= '?'.$this->server->get('QUERY_STRING'); - } - $this->server->remove('ORIG_PATH_INFO'); - } - - // normalize the request URI to ease creating sub-requests from this request - $this->server->set('REQUEST_URI', $requestUri); - - return $requestUri; - } - - /** - * Prepares the base URL. - * - * @return string - */ - protected function prepareBaseUrl() - { - $filename = basename($this->server->get('SCRIPT_FILENAME', '')); - - if (basename($this->server->get('SCRIPT_NAME', '')) === $filename) { - $baseUrl = $this->server->get('SCRIPT_NAME'); - } elseif (basename($this->server->get('PHP_SELF', '')) === $filename) { - $baseUrl = $this->server->get('PHP_SELF'); - } elseif (basename($this->server->get('ORIG_SCRIPT_NAME', '')) === $filename) { - $baseUrl = $this->server->get('ORIG_SCRIPT_NAME'); // 1and1 shared hosting compatibility - } else { - // Backtrack up the script_filename to find the portion matching - // php_self - $path = $this->server->get('PHP_SELF', ''); - $file = $this->server->get('SCRIPT_FILENAME', ''); - $segs = explode('/', trim($file, '/')); - $segs = array_reverse($segs); - $index = 0; - $last = \count($segs); - $baseUrl = ''; - do { - $seg = $segs[$index]; - $baseUrl = '/'.$seg.$baseUrl; - ++$index; - } while ($last > $index && (false !== $pos = strpos($path, $baseUrl)) && 0 != $pos); - } - - // Does the baseUrl have anything in common with the request_uri? - $requestUri = $this->getRequestUri(); - if ('' !== $requestUri && '/' !== $requestUri[0]) { - $requestUri = '/'.$requestUri; - } - - if ($baseUrl && null !== $prefix = $this->getUrlencodedPrefix($requestUri, $baseUrl)) { - // full $baseUrl matches - return $prefix; - } - - if ($baseUrl && null !== $prefix = $this->getUrlencodedPrefix($requestUri, rtrim(\dirname($baseUrl), '/'.\DIRECTORY_SEPARATOR).'/')) { - // directory portion of $baseUrl matches - return rtrim($prefix, '/'.\DIRECTORY_SEPARATOR); - } - - $truncatedRequestUri = $requestUri; - if (false !== $pos = strpos($requestUri, '?')) { - $truncatedRequestUri = substr($requestUri, 0, $pos); - } - - $basename = basename($baseUrl ?? ''); - if (empty($basename) || !strpos(rawurldecode($truncatedRequestUri), $basename)) { - // no match whatsoever; set it blank - return ''; - } - - // If using mod_rewrite or ISAPI_Rewrite strip the script filename - // out of baseUrl. $pos !== 0 makes sure it is not matching a value - // from PATH_INFO or QUERY_STRING - if (\strlen($requestUri) >= \strlen($baseUrl) && (false !== $pos = strpos($requestUri, $baseUrl)) && 0 !== $pos) { - $baseUrl = substr($requestUri, 0, $pos + \strlen($baseUrl)); - } - - return rtrim($baseUrl, '/'.\DIRECTORY_SEPARATOR); - } - - /** - * Prepares the base path. - * - * @return string - */ - protected function prepareBasePath() - { - $baseUrl = $this->getBaseUrl(); - if (empty($baseUrl)) { - return ''; - } - - $filename = basename($this->server->get('SCRIPT_FILENAME')); - if (basename($baseUrl) === $filename) { - $basePath = \dirname($baseUrl); - } else { - $basePath = $baseUrl; - } - - if ('\\' === \DIRECTORY_SEPARATOR) { - $basePath = str_replace('\\', '/', $basePath); - } - - return rtrim($basePath, '/'); - } - - /** - * Prepares the path info. - * - * @return string - */ - protected function preparePathInfo() - { - if (null === ($requestUri = $this->getRequestUri())) { - return '/'; - } - - // Remove the query string from REQUEST_URI - if (false !== $pos = strpos($requestUri, '?')) { - $requestUri = substr($requestUri, 0, $pos); - } - if ('' !== $requestUri && '/' !== $requestUri[0]) { - $requestUri = '/'.$requestUri; - } - - if (null === ($baseUrl = $this->getBaseUrlReal())) { - return $requestUri; - } - - $pathInfo = substr($requestUri, \strlen($baseUrl)); - if (false === $pathInfo || '' === $pathInfo) { - // If substr() returns false then PATH_INFO is set to an empty string - return '/'; - } - - return $pathInfo; - } - - /** - * Initializes HTTP request formats. - */ - protected static function initializeFormats() - { - static::$formats = [ - 'html' => ['text/html', 'application/xhtml+xml'], - 'txt' => ['text/plain'], - 'js' => ['application/javascript', 'application/x-javascript', 'text/javascript'], - 'css' => ['text/css'], - 'json' => ['application/json', 'application/x-json'], - 'jsonld' => ['application/ld+json'], - 'xml' => ['text/xml', 'application/xml', 'application/x-xml'], - 'rdf' => ['application/rdf+xml'], - 'atom' => ['application/atom+xml'], - 'rss' => ['application/rss+xml'], - 'form' => ['application/x-www-form-urlencoded', 'multipart/form-data'], - ]; - } - - private function setPhpDefaultLocale(string $locale): void - { - // if either the class Locale doesn't exist, or an exception is thrown when - // setting the default locale, the intl module is not installed, and - // the call can be ignored: - try { - if (class_exists(\Locale::class, false)) { - \Locale::setDefault($locale); - } - } catch (\Exception $e) { - } - } - - /** - * Returns the prefix as encoded in the string when the string starts with - * the given prefix, null otherwise. - */ - private function getUrlencodedPrefix(string $string, string $prefix): ?string - { - if ($this->isIisRewrite()) { - // ISS with UrlRewriteModule might report SCRIPT_NAME/PHP_SELF with wrong case - // see https://github.com/php/php-src/issues/11981 - if (0 !== stripos(rawurldecode($string), $prefix)) { - return null; - } - } elseif (!str_starts_with(rawurldecode($string), $prefix)) { - return null; - } - - $len = \strlen($prefix); - - if (preg_match(sprintf('#^(%%[[:xdigit:]]{2}|.){%d}#', $len), $string, $match)) { - return $match[0]; - } - - return null; - } - - private static function createRequestFromFactory(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null): self - { - if (self::$requestFactory) { - $request = (self::$requestFactory)($query, $request, $attributes, $cookies, $files, $server, $content); - - if (!$request instanceof self) { - throw new \LogicException('The Request factory must return an instance of Symfony\Component\HttpFoundation\Request.'); - } - - return $request; - } - - return new static($query, $request, $attributes, $cookies, $files, $server, $content); - } - - /** - * Indicates whether this request originated from a trusted proxy. - * - * This can be useful to determine whether or not to trust the - * contents of a proxy-specific header. - * - * @return bool - */ - public function isFromTrustedProxy() - { - return self::$trustedProxies && IpUtils::checkIp($this->server->get('REMOTE_ADDR', ''), self::$trustedProxies); - } - - private function getTrustedValues(int $type, ?string $ip = null): array - { - $clientValues = []; - $forwardedValues = []; - - if ((self::$trustedHeaderSet & $type) && $this->headers->has(self::TRUSTED_HEADERS[$type])) { - foreach (explode(',', $this->headers->get(self::TRUSTED_HEADERS[$type])) as $v) { - $clientValues[] = (self::HEADER_X_FORWARDED_PORT === $type ? '0.0.0.0:' : '').trim($v); - } - } - - if ((self::$trustedHeaderSet & self::HEADER_FORWARDED) && (isset(self::FORWARDED_PARAMS[$type])) && $this->headers->has(self::TRUSTED_HEADERS[self::HEADER_FORWARDED])) { - $forwarded = $this->headers->get(self::TRUSTED_HEADERS[self::HEADER_FORWARDED]); - $parts = HeaderUtils::split($forwarded, ',;='); - $forwardedValues = []; - $param = self::FORWARDED_PARAMS[$type]; - foreach ($parts as $subParts) { - if (null === $v = HeaderUtils::combine($subParts)[$param] ?? null) { - continue; - } - if (self::HEADER_X_FORWARDED_PORT === $type) { - if (str_ends_with($v, ']') || false === $v = strrchr($v, ':')) { - $v = $this->isSecure() ? ':443' : ':80'; - } - $v = '0.0.0.0'.$v; - } - $forwardedValues[] = $v; - } - } - - if (null !== $ip) { - $clientValues = $this->normalizeAndFilterClientIps($clientValues, $ip); - $forwardedValues = $this->normalizeAndFilterClientIps($forwardedValues, $ip); - } - - if ($forwardedValues === $clientValues || !$clientValues) { - return $forwardedValues; - } - - if (!$forwardedValues) { - return $clientValues; - } - - if (!$this->isForwardedValid) { - return null !== $ip ? ['0.0.0.0', $ip] : []; - } - $this->isForwardedValid = false; - - throw new ConflictingHeadersException(sprintf('The request has both a trusted "%s" header and a trusted "%s" header, conflicting with each other. You should either configure your proxy to remove one of them, or configure your project to distrust the offending one.', self::TRUSTED_HEADERS[self::HEADER_FORWARDED], self::TRUSTED_HEADERS[$type])); - } - - private function normalizeAndFilterClientIps(array $clientIps, string $ip): array - { - if (!$clientIps) { - return []; - } - $clientIps[] = $ip; // Complete the IP chain with the IP the request actually came from - $firstTrustedIp = null; - - foreach ($clientIps as $key => $clientIp) { - if (strpos($clientIp, '.')) { - // Strip :port from IPv4 addresses. This is allowed in Forwarded - // and may occur in X-Forwarded-For. - $i = strpos($clientIp, ':'); - if ($i) { - $clientIps[$key] = $clientIp = substr($clientIp, 0, $i); - } - } elseif (str_starts_with($clientIp, '[')) { - // Strip brackets and :port from IPv6 addresses. - $i = strpos($clientIp, ']', 1); - $clientIps[$key] = $clientIp = substr($clientIp, 1, $i - 1); - } - - if (!filter_var($clientIp, \FILTER_VALIDATE_IP)) { - unset($clientIps[$key]); - - continue; - } - - if (IpUtils::checkIp($clientIp, self::$trustedProxies)) { - unset($clientIps[$key]); - - // Fallback to this when the client IP falls into the range of trusted proxies - if (null === $firstTrustedIp) { - $firstTrustedIp = $clientIp; - } - } - } - - // Now the IP chain contains only untrusted proxies and the client IP - return $clientIps ? array_reverse($clientIps) : [$firstTrustedIp]; - } - - /** - * Is this IIS with UrlRewriteModule? - * - * This method consumes, caches and removed the IIS_WasUrlRewritten env var, - * so we don't inherit it to sub-requests. - */ - private function isIisRewrite(): bool - { - if (1 === $this->server->getInt('IIS_WasUrlRewritten')) { - $this->isIisRewrite = true; - $this->server->remove('IIS_WasUrlRewritten'); - } - - return $this->isIisRewrite; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/RequestMatcher.php b/digital_doctor/vendor/symfony/http-foundation/RequestMatcher.php deleted file mode 100644 index 03ccee9..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/RequestMatcher.php +++ /dev/null @@ -1,196 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * RequestMatcher compares a pre-defined set of checks against a Request instance. - * - * @author Fabien Potencier - */ -class RequestMatcher implements RequestMatcherInterface -{ - /** - * @var string|null - */ - private $path; - - /** - * @var string|null - */ - private $host; - - /** - * @var int|null - */ - private $port; - - /** - * @var string[] - */ - private $methods = []; - - /** - * @var string[] - */ - private $ips = []; - - /** - * @var array - */ - private $attributes = []; - - /** - * @var string[] - */ - private $schemes = []; - - /** - * @param string|string[]|null $methods - * @param string|string[]|null $ips - * @param string|string[]|null $schemes - */ - public function __construct(?string $path = null, ?string $host = null, $methods = null, $ips = null, array $attributes = [], $schemes = null, ?int $port = null) - { - $this->matchPath($path); - $this->matchHost($host); - $this->matchMethod($methods); - $this->matchIps($ips); - $this->matchScheme($schemes); - $this->matchPort($port); - - foreach ($attributes as $k => $v) { - $this->matchAttribute($k, $v); - } - } - - /** - * Adds a check for the HTTP scheme. - * - * @param string|string[]|null $scheme An HTTP scheme or an array of HTTP schemes - */ - public function matchScheme($scheme) - { - $this->schemes = null !== $scheme ? array_map('strtolower', (array) $scheme) : []; - } - - /** - * Adds a check for the URL host name. - */ - public function matchHost(?string $regexp) - { - $this->host = $regexp; - } - - /** - * Adds a check for the URL port. - * - * @param int|null $port The port number to connect to - */ - public function matchPort(?int $port) - { - $this->port = $port; - } - - /** - * Adds a check for the URL path info. - */ - public function matchPath(?string $regexp) - { - $this->path = $regexp; - } - - /** - * Adds a check for the client IP. - * - * @param string $ip A specific IP address or a range specified using IP/netmask like 192.168.1.0/24 - */ - public function matchIp(string $ip) - { - $this->matchIps($ip); - } - - /** - * Adds a check for the client IP. - * - * @param string|string[]|null $ips A specific IP address or a range specified using IP/netmask like 192.168.1.0/24 - */ - public function matchIps($ips) - { - $ips = null !== $ips ? (array) $ips : []; - - $this->ips = array_reduce($ips, static function (array $ips, string $ip) { - return array_merge($ips, preg_split('/\s*,\s*/', $ip)); - }, []); - } - - /** - * Adds a check for the HTTP method. - * - * @param string|string[]|null $method An HTTP method or an array of HTTP methods - */ - public function matchMethod($method) - { - $this->methods = null !== $method ? array_map('strtoupper', (array) $method) : []; - } - - /** - * Adds a check for request attribute. - */ - public function matchAttribute(string $key, string $regexp) - { - $this->attributes[$key] = $regexp; - } - - /** - * {@inheritdoc} - */ - public function matches(Request $request) - { - if ($this->schemes && !\in_array($request->getScheme(), $this->schemes, true)) { - return false; - } - - if ($this->methods && !\in_array($request->getMethod(), $this->methods, true)) { - return false; - } - - foreach ($this->attributes as $key => $pattern) { - $requestAttribute = $request->attributes->get($key); - if (!\is_string($requestAttribute)) { - return false; - } - if (!preg_match('{'.$pattern.'}', $requestAttribute)) { - return false; - } - } - - if (null !== $this->path && !preg_match('{'.$this->path.'}', rawurldecode($request->getPathInfo()))) { - return false; - } - - if (null !== $this->host && !preg_match('{'.$this->host.'}i', $request->getHost())) { - return false; - } - - if (null !== $this->port && 0 < $this->port && $request->getPort() !== $this->port) { - return false; - } - - if (IpUtils::checkIp($request->getClientIp() ?? '', $this->ips)) { - return true; - } - - // Note to future implementors: add additional checks above the - // foreach above or else your check might not be run! - return 0 === \count($this->ips); - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/RequestMatcherInterface.php b/digital_doctor/vendor/symfony/http-foundation/RequestMatcherInterface.php deleted file mode 100644 index c2e1478..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/RequestMatcherInterface.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * RequestMatcherInterface is an interface for strategies to match a Request. - * - * @author Fabien Potencier - */ -interface RequestMatcherInterface -{ - /** - * Decides whether the rule(s) implemented by the strategy matches the supplied request. - * - * @return bool - */ - public function matches(Request $request); -} diff --git a/digital_doctor/vendor/symfony/http-foundation/RequestStack.php b/digital_doctor/vendor/symfony/http-foundation/RequestStack.php deleted file mode 100644 index 855b518..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/RequestStack.php +++ /dev/null @@ -1,128 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -use Symfony\Component\HttpFoundation\Exception\SessionNotFoundException; -use Symfony\Component\HttpFoundation\Session\SessionInterface; - -/** - * Request stack that controls the lifecycle of requests. - * - * @author Benjamin Eberlei - */ -class RequestStack -{ - /** - * @var Request[] - */ - private $requests = []; - - /** - * Pushes a Request on the stack. - * - * This method should generally not be called directly as the stack - * management should be taken care of by the application itself. - */ - public function push(Request $request) - { - $this->requests[] = $request; - } - - /** - * Pops the current request from the stack. - * - * This operation lets the current request go out of scope. - * - * This method should generally not be called directly as the stack - * management should be taken care of by the application itself. - * - * @return Request|null - */ - public function pop() - { - if (!$this->requests) { - return null; - } - - return array_pop($this->requests); - } - - /** - * @return Request|null - */ - public function getCurrentRequest() - { - return end($this->requests) ?: null; - } - - /** - * Gets the main request. - * - * Be warned that making your code aware of the main request - * might make it un-compatible with other features of your framework - * like ESI support. - */ - public function getMainRequest(): ?Request - { - if (!$this->requests) { - return null; - } - - return $this->requests[0]; - } - - /** - * Gets the master request. - * - * @return Request|null - * - * @deprecated since symfony/http-foundation 5.3, use getMainRequest() instead - */ - public function getMasterRequest() - { - trigger_deprecation('symfony/http-foundation', '5.3', '"%s()" is deprecated, use "getMainRequest()" instead.', __METHOD__); - - return $this->getMainRequest(); - } - - /** - * Returns the parent request of the current. - * - * Be warned that making your code aware of the parent request - * might make it un-compatible with other features of your framework - * like ESI support. - * - * If current Request is the main request, it returns null. - * - * @return Request|null - */ - public function getParentRequest() - { - $pos = \count($this->requests) - 2; - - return $this->requests[$pos] ?? null; - } - - /** - * Gets the current session. - * - * @throws SessionNotFoundException - */ - public function getSession(): SessionInterface - { - if ((null !== $request = end($this->requests) ?: null) && $request->hasSession()) { - return $request->getSession(); - } - - throw new SessionNotFoundException(); - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Response.php b/digital_doctor/vendor/symfony/http-foundation/Response.php deleted file mode 100644 index 6798a04..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Response.php +++ /dev/null @@ -1,1288 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -// Help opcache.preload discover always-needed symbols -class_exists(ResponseHeaderBag::class); - -/** - * Response represents an HTTP response. - * - * @author Fabien Potencier - */ -class Response -{ - public const HTTP_CONTINUE = 100; - public const HTTP_SWITCHING_PROTOCOLS = 101; - public const HTTP_PROCESSING = 102; // RFC2518 - public const HTTP_EARLY_HINTS = 103; // RFC8297 - public const HTTP_OK = 200; - public const HTTP_CREATED = 201; - public const HTTP_ACCEPTED = 202; - public const HTTP_NON_AUTHORITATIVE_INFORMATION = 203; - public const HTTP_NO_CONTENT = 204; - public const HTTP_RESET_CONTENT = 205; - public const HTTP_PARTIAL_CONTENT = 206; - public const HTTP_MULTI_STATUS = 207; // RFC4918 - public const HTTP_ALREADY_REPORTED = 208; // RFC5842 - public const HTTP_IM_USED = 226; // RFC3229 - public const HTTP_MULTIPLE_CHOICES = 300; - public const HTTP_MOVED_PERMANENTLY = 301; - public const HTTP_FOUND = 302; - public const HTTP_SEE_OTHER = 303; - public const HTTP_NOT_MODIFIED = 304; - public const HTTP_USE_PROXY = 305; - public const HTTP_RESERVED = 306; - public const HTTP_TEMPORARY_REDIRECT = 307; - public const HTTP_PERMANENTLY_REDIRECT = 308; // RFC7238 - public const HTTP_BAD_REQUEST = 400; - public const HTTP_UNAUTHORIZED = 401; - public const HTTP_PAYMENT_REQUIRED = 402; - public const HTTP_FORBIDDEN = 403; - public const HTTP_NOT_FOUND = 404; - public const HTTP_METHOD_NOT_ALLOWED = 405; - public const HTTP_NOT_ACCEPTABLE = 406; - public const HTTP_PROXY_AUTHENTICATION_REQUIRED = 407; - public const HTTP_REQUEST_TIMEOUT = 408; - public const HTTP_CONFLICT = 409; - public const HTTP_GONE = 410; - public const HTTP_LENGTH_REQUIRED = 411; - public const HTTP_PRECONDITION_FAILED = 412; - public const HTTP_REQUEST_ENTITY_TOO_LARGE = 413; - public const HTTP_REQUEST_URI_TOO_LONG = 414; - public const HTTP_UNSUPPORTED_MEDIA_TYPE = 415; - public const HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416; - public const HTTP_EXPECTATION_FAILED = 417; - public const HTTP_I_AM_A_TEAPOT = 418; // RFC2324 - public const HTTP_MISDIRECTED_REQUEST = 421; // RFC7540 - public const HTTP_UNPROCESSABLE_ENTITY = 422; // RFC4918 - public const HTTP_LOCKED = 423; // RFC4918 - public const HTTP_FAILED_DEPENDENCY = 424; // RFC4918 - public const HTTP_TOO_EARLY = 425; // RFC-ietf-httpbis-replay-04 - public const HTTP_UPGRADE_REQUIRED = 426; // RFC2817 - public const HTTP_PRECONDITION_REQUIRED = 428; // RFC6585 - public const HTTP_TOO_MANY_REQUESTS = 429; // RFC6585 - public const HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431; // RFC6585 - public const HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451; // RFC7725 - public const HTTP_INTERNAL_SERVER_ERROR = 500; - public const HTTP_NOT_IMPLEMENTED = 501; - public const HTTP_BAD_GATEWAY = 502; - public const HTTP_SERVICE_UNAVAILABLE = 503; - public const HTTP_GATEWAY_TIMEOUT = 504; - public const HTTP_VERSION_NOT_SUPPORTED = 505; - public const HTTP_VARIANT_ALSO_NEGOTIATES_EXPERIMENTAL = 506; // RFC2295 - public const HTTP_INSUFFICIENT_STORAGE = 507; // RFC4918 - public const HTTP_LOOP_DETECTED = 508; // RFC5842 - public const HTTP_NOT_EXTENDED = 510; // RFC2774 - public const HTTP_NETWORK_AUTHENTICATION_REQUIRED = 511; // RFC6585 - - /** - * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control - */ - private const HTTP_RESPONSE_CACHE_CONTROL_DIRECTIVES = [ - 'must_revalidate' => false, - 'no_cache' => false, - 'no_store' => false, - 'no_transform' => false, - 'public' => false, - 'private' => false, - 'proxy_revalidate' => false, - 'max_age' => true, - 's_maxage' => true, - 'immutable' => false, - 'last_modified' => true, - 'etag' => true, - ]; - - /** - * @var ResponseHeaderBag - */ - public $headers; - - /** - * @var string - */ - protected $content; - - /** - * @var string - */ - protected $version; - - /** - * @var int - */ - protected $statusCode; - - /** - * @var string - */ - protected $statusText; - - /** - * @var string - */ - protected $charset; - - /** - * Status codes translation table. - * - * The list of codes is complete according to the - * {@link https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml Hypertext Transfer Protocol (HTTP) Status Code Registry} - * (last updated 2021-10-01). - * - * Unless otherwise noted, the status code is defined in RFC2616. - * - * @var array - */ - public static $statusTexts = [ - 100 => 'Continue', - 101 => 'Switching Protocols', - 102 => 'Processing', // RFC2518 - 103 => 'Early Hints', - 200 => 'OK', - 201 => 'Created', - 202 => 'Accepted', - 203 => 'Non-Authoritative Information', - 204 => 'No Content', - 205 => 'Reset Content', - 206 => 'Partial Content', - 207 => 'Multi-Status', // RFC4918 - 208 => 'Already Reported', // RFC5842 - 226 => 'IM Used', // RFC3229 - 300 => 'Multiple Choices', - 301 => 'Moved Permanently', - 302 => 'Found', - 303 => 'See Other', - 304 => 'Not Modified', - 305 => 'Use Proxy', - 307 => 'Temporary Redirect', - 308 => 'Permanent Redirect', // RFC7238 - 400 => 'Bad Request', - 401 => 'Unauthorized', - 402 => 'Payment Required', - 403 => 'Forbidden', - 404 => 'Not Found', - 405 => 'Method Not Allowed', - 406 => 'Not Acceptable', - 407 => 'Proxy Authentication Required', - 408 => 'Request Timeout', - 409 => 'Conflict', - 410 => 'Gone', - 411 => 'Length Required', - 412 => 'Precondition Failed', - 413 => 'Content Too Large', // RFC-ietf-httpbis-semantics - 414 => 'URI Too Long', - 415 => 'Unsupported Media Type', - 416 => 'Range Not Satisfiable', - 417 => 'Expectation Failed', - 418 => 'I\'m a teapot', // RFC2324 - 421 => 'Misdirected Request', // RFC7540 - 422 => 'Unprocessable Content', // RFC-ietf-httpbis-semantics - 423 => 'Locked', // RFC4918 - 424 => 'Failed Dependency', // RFC4918 - 425 => 'Too Early', // RFC-ietf-httpbis-replay-04 - 426 => 'Upgrade Required', // RFC2817 - 428 => 'Precondition Required', // RFC6585 - 429 => 'Too Many Requests', // RFC6585 - 431 => 'Request Header Fields Too Large', // RFC6585 - 451 => 'Unavailable For Legal Reasons', // RFC7725 - 500 => 'Internal Server Error', - 501 => 'Not Implemented', - 502 => 'Bad Gateway', - 503 => 'Service Unavailable', - 504 => 'Gateway Timeout', - 505 => 'HTTP Version Not Supported', - 506 => 'Variant Also Negotiates', // RFC2295 - 507 => 'Insufficient Storage', // RFC4918 - 508 => 'Loop Detected', // RFC5842 - 510 => 'Not Extended', // RFC2774 - 511 => 'Network Authentication Required', // RFC6585 - ]; - - /** - * @throws \InvalidArgumentException When the HTTP status code is not valid - */ - public function __construct(?string $content = '', int $status = 200, array $headers = []) - { - $this->headers = new ResponseHeaderBag($headers); - $this->setContent($content); - $this->setStatusCode($status); - $this->setProtocolVersion('1.0'); - } - - /** - * Factory method for chainability. - * - * Example: - * - * return Response::create($body, 200) - * ->setSharedMaxAge(300); - * - * @return static - * - * @deprecated since Symfony 5.1, use __construct() instead. - */ - public static function create(?string $content = '', int $status = 200, array $headers = []) - { - trigger_deprecation('symfony/http-foundation', '5.1', 'The "%s()" method is deprecated, use "new %s()" instead.', __METHOD__, static::class); - - return new static($content, $status, $headers); - } - - /** - * Returns the Response as an HTTP string. - * - * The string representation of the Response is the same as the - * one that will be sent to the client only if the prepare() method - * has been called before. - * - * @return string - * - * @see prepare() - */ - public function __toString() - { - return - sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText)."\r\n". - $this->headers."\r\n". - $this->getContent(); - } - - /** - * Clones the current Response instance. - */ - public function __clone() - { - $this->headers = clone $this->headers; - } - - /** - * Prepares the Response before it is sent to the client. - * - * This method tweaks the Response to ensure that it is - * compliant with RFC 2616. Most of the changes are based on - * the Request that is "associated" with this Response. - * - * @return $this - */ - public function prepare(Request $request) - { - $headers = $this->headers; - - if ($this->isInformational() || $this->isEmpty()) { - $this->setContent(null); - $headers->remove('Content-Type'); - $headers->remove('Content-Length'); - // prevent PHP from sending the Content-Type header based on default_mimetype - ini_set('default_mimetype', ''); - } else { - // Content-type based on the Request - if (!$headers->has('Content-Type')) { - $format = $request->getRequestFormat(null); - if (null !== $format && $mimeType = $request->getMimeType($format)) { - $headers->set('Content-Type', $mimeType); - } - } - - // Fix Content-Type - $charset = $this->charset ?: 'UTF-8'; - if (!$headers->has('Content-Type')) { - $headers->set('Content-Type', 'text/html; charset='.$charset); - } elseif (0 === stripos($headers->get('Content-Type') ?? '', 'text/') && false === stripos($headers->get('Content-Type') ?? '', 'charset')) { - // add the charset - $headers->set('Content-Type', $headers->get('Content-Type').'; charset='.$charset); - } - - // Fix Content-Length - if ($headers->has('Transfer-Encoding')) { - $headers->remove('Content-Length'); - } - - if ($request->isMethod('HEAD')) { - // cf. RFC2616 14.13 - $length = $headers->get('Content-Length'); - $this->setContent(null); - if ($length) { - $headers->set('Content-Length', $length); - } - } - } - - // Fix protocol - if ('HTTP/1.0' != $request->server->get('SERVER_PROTOCOL')) { - $this->setProtocolVersion('1.1'); - } - - // Check if we need to send extra expire info headers - if ('1.0' == $this->getProtocolVersion() && str_contains($headers->get('Cache-Control', ''), 'no-cache')) { - $headers->set('pragma', 'no-cache'); - $headers->set('expires', -1); - } - - $this->ensureIEOverSSLCompatibility($request); - - if ($request->isSecure()) { - foreach ($headers->getCookies() as $cookie) { - $cookie->setSecureDefault(true); - } - } - - return $this; - } - - /** - * Sends HTTP headers. - * - * @return $this - */ - public function sendHeaders() - { - // headers have already been sent by the developer - if (headers_sent()) { - return $this; - } - - // headers - foreach ($this->headers->allPreserveCaseWithoutCookies() as $name => $values) { - $replace = 0 === strcasecmp($name, 'Content-Type'); - foreach ($values as $value) { - header($name.': '.$value, $replace, $this->statusCode); - } - } - - // cookies - foreach ($this->headers->getCookies() as $cookie) { - header('Set-Cookie: '.$cookie, false, $this->statusCode); - } - - // status - header(sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText), true, $this->statusCode); - - return $this; - } - - /** - * Sends content for the current web response. - * - * @return $this - */ - public function sendContent() - { - echo $this->content; - - return $this; - } - - /** - * Sends HTTP headers and content. - * - * @return $this - */ - public function send() - { - $this->sendHeaders(); - $this->sendContent(); - - if (\function_exists('fastcgi_finish_request')) { - fastcgi_finish_request(); - } elseif (\function_exists('litespeed_finish_request')) { - litespeed_finish_request(); - } elseif (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) { - static::closeOutputBuffers(0, true); - flush(); - } - - return $this; - } - - /** - * Sets the response content. - * - * @return $this - */ - public function setContent(?string $content) - { - $this->content = $content ?? ''; - - return $this; - } - - /** - * Gets the current response content. - * - * @return string|false - */ - public function getContent() - { - return $this->content; - } - - /** - * Sets the HTTP protocol version (1.0 or 1.1). - * - * @return $this - * - * @final - */ - public function setProtocolVersion(string $version): object - { - $this->version = $version; - - return $this; - } - - /** - * Gets the HTTP protocol version. - * - * @final - */ - public function getProtocolVersion(): string - { - return $this->version; - } - - /** - * Sets the response status code. - * - * If the status text is null it will be automatically populated for the known - * status codes and left empty otherwise. - * - * @return $this - * - * @throws \InvalidArgumentException When the HTTP status code is not valid - * - * @final - */ - public function setStatusCode(int $code, ?string $text = null): object - { - $this->statusCode = $code; - if ($this->isInvalid()) { - throw new \InvalidArgumentException(sprintf('The HTTP status code "%s" is not valid.', $code)); - } - - if (null === $text) { - $this->statusText = self::$statusTexts[$code] ?? 'unknown status'; - - return $this; - } - - if (false === $text) { - $this->statusText = ''; - - return $this; - } - - $this->statusText = $text; - - return $this; - } - - /** - * Retrieves the status code for the current web response. - * - * @final - */ - public function getStatusCode(): int - { - return $this->statusCode; - } - - /** - * Sets the response charset. - * - * @return $this - * - * @final - */ - public function setCharset(string $charset): object - { - $this->charset = $charset; - - return $this; - } - - /** - * Retrieves the response charset. - * - * @final - */ - public function getCharset(): ?string - { - return $this->charset; - } - - /** - * Returns true if the response may safely be kept in a shared (surrogate) cache. - * - * Responses marked "private" with an explicit Cache-Control directive are - * considered uncacheable. - * - * Responses with neither a freshness lifetime (Expires, max-age) nor cache - * validator (Last-Modified, ETag) are considered uncacheable because there is - * no way to tell when or how to remove them from the cache. - * - * Note that RFC 7231 and RFC 7234 possibly allow for a more permissive implementation, - * for example "status codes that are defined as cacheable by default [...] - * can be reused by a cache with heuristic expiration unless otherwise indicated" - * (https://tools.ietf.org/html/rfc7231#section-6.1) - * - * @final - */ - public function isCacheable(): bool - { - if (!\in_array($this->statusCode, [200, 203, 300, 301, 302, 404, 410])) { - return false; - } - - if ($this->headers->hasCacheControlDirective('no-store') || $this->headers->getCacheControlDirective('private')) { - return false; - } - - return $this->isValidateable() || $this->isFresh(); - } - - /** - * Returns true if the response is "fresh". - * - * Fresh responses may be served from cache without any interaction with the - * origin. A response is considered fresh when it includes a Cache-Control/max-age - * indicator or Expires header and the calculated age is less than the freshness lifetime. - * - * @final - */ - public function isFresh(): bool - { - return $this->getTtl() > 0; - } - - /** - * Returns true if the response includes headers that can be used to validate - * the response with the origin server using a conditional GET request. - * - * @final - */ - public function isValidateable(): bool - { - return $this->headers->has('Last-Modified') || $this->headers->has('ETag'); - } - - /** - * Marks the response as "private". - * - * It makes the response ineligible for serving other clients. - * - * @return $this - * - * @final - */ - public function setPrivate(): object - { - $this->headers->removeCacheControlDirective('public'); - $this->headers->addCacheControlDirective('private'); - - return $this; - } - - /** - * Marks the response as "public". - * - * It makes the response eligible for serving other clients. - * - * @return $this - * - * @final - */ - public function setPublic(): object - { - $this->headers->addCacheControlDirective('public'); - $this->headers->removeCacheControlDirective('private'); - - return $this; - } - - /** - * Marks the response as "immutable". - * - * @return $this - * - * @final - */ - public function setImmutable(bool $immutable = true): object - { - if ($immutable) { - $this->headers->addCacheControlDirective('immutable'); - } else { - $this->headers->removeCacheControlDirective('immutable'); - } - - return $this; - } - - /** - * Returns true if the response is marked as "immutable". - * - * @final - */ - public function isImmutable(): bool - { - return $this->headers->hasCacheControlDirective('immutable'); - } - - /** - * Returns true if the response must be revalidated by shared caches once it has become stale. - * - * This method indicates that the response must not be served stale by a - * cache in any circumstance without first revalidating with the origin. - * When present, the TTL of the response should not be overridden to be - * greater than the value provided by the origin. - * - * @final - */ - public function mustRevalidate(): bool - { - return $this->headers->hasCacheControlDirective('must-revalidate') || $this->headers->hasCacheControlDirective('proxy-revalidate'); - } - - /** - * Returns the Date header as a DateTime instance. - * - * @throws \RuntimeException When the header is not parseable - * - * @final - */ - public function getDate(): ?\DateTimeInterface - { - return $this->headers->getDate('Date'); - } - - /** - * Sets the Date header. - * - * @return $this - * - * @final - */ - public function setDate(\DateTimeInterface $date): object - { - if ($date instanceof \DateTime) { - $date = \DateTimeImmutable::createFromMutable($date); - } - - $date = $date->setTimezone(new \DateTimeZone('UTC')); - $this->headers->set('Date', $date->format('D, d M Y H:i:s').' GMT'); - - return $this; - } - - /** - * Returns the age of the response in seconds. - * - * @final - */ - public function getAge(): int - { - if (null !== $age = $this->headers->get('Age')) { - return (int) $age; - } - - return max(time() - (int) $this->getDate()->format('U'), 0); - } - - /** - * Marks the response stale by setting the Age header to be equal to the maximum age of the response. - * - * @return $this - */ - public function expire() - { - if ($this->isFresh()) { - $this->headers->set('Age', $this->getMaxAge()); - $this->headers->remove('Expires'); - } - - return $this; - } - - /** - * Returns the value of the Expires header as a DateTime instance. - * - * @final - */ - public function getExpires(): ?\DateTimeInterface - { - try { - return $this->headers->getDate('Expires'); - } catch (\RuntimeException $e) { - // according to RFC 2616 invalid date formats (e.g. "0" and "-1") must be treated as in the past - return \DateTime::createFromFormat('U', time() - 172800); - } - } - - /** - * Sets the Expires HTTP header with a DateTime instance. - * - * Passing null as value will remove the header. - * - * @return $this - * - * @final - */ - public function setExpires(?\DateTimeInterface $date = null): object - { - if (null === $date) { - $this->headers->remove('Expires'); - - return $this; - } - - if ($date instanceof \DateTime) { - $date = \DateTimeImmutable::createFromMutable($date); - } - - $date = $date->setTimezone(new \DateTimeZone('UTC')); - $this->headers->set('Expires', $date->format('D, d M Y H:i:s').' GMT'); - - return $this; - } - - /** - * Returns the number of seconds after the time specified in the response's Date - * header when the response should no longer be considered fresh. - * - * First, it checks for a s-maxage directive, then a max-age directive, and then it falls - * back on an expires header. It returns null when no maximum age can be established. - * - * @final - */ - public function getMaxAge(): ?int - { - if ($this->headers->hasCacheControlDirective('s-maxage')) { - return (int) $this->headers->getCacheControlDirective('s-maxage'); - } - - if ($this->headers->hasCacheControlDirective('max-age')) { - return (int) $this->headers->getCacheControlDirective('max-age'); - } - - if (null !== $expires = $this->getExpires()) { - $maxAge = (int) $expires->format('U') - (int) $this->getDate()->format('U'); - - return max($maxAge, 0); - } - - return null; - } - - /** - * Sets the number of seconds after which the response should no longer be considered fresh. - * - * This methods sets the Cache-Control max-age directive. - * - * @return $this - * - * @final - */ - public function setMaxAge(int $value): object - { - $this->headers->addCacheControlDirective('max-age', $value); - - return $this; - } - - /** - * Sets the number of seconds after which the response should no longer be considered fresh by shared caches. - * - * This methods sets the Cache-Control s-maxage directive. - * - * @return $this - * - * @final - */ - public function setSharedMaxAge(int $value): object - { - $this->setPublic(); - $this->headers->addCacheControlDirective('s-maxage', $value); - - return $this; - } - - /** - * Returns the response's time-to-live in seconds. - * - * It returns null when no freshness information is present in the response. - * - * When the response's TTL is 0, the response may not be served from cache without first - * revalidating with the origin. - * - * @final - */ - public function getTtl(): ?int - { - $maxAge = $this->getMaxAge(); - - return null !== $maxAge ? max($maxAge - $this->getAge(), 0) : null; - } - - /** - * Sets the response's time-to-live for shared caches in seconds. - * - * This method adjusts the Cache-Control/s-maxage directive. - * - * @return $this - * - * @final - */ - public function setTtl(int $seconds): object - { - $this->setSharedMaxAge($this->getAge() + $seconds); - - return $this; - } - - /** - * Sets the response's time-to-live for private/client caches in seconds. - * - * This method adjusts the Cache-Control/max-age directive. - * - * @return $this - * - * @final - */ - public function setClientTtl(int $seconds): object - { - $this->setMaxAge($this->getAge() + $seconds); - - return $this; - } - - /** - * Returns the Last-Modified HTTP header as a DateTime instance. - * - * @throws \RuntimeException When the HTTP header is not parseable - * - * @final - */ - public function getLastModified(): ?\DateTimeInterface - { - return $this->headers->getDate('Last-Modified'); - } - - /** - * Sets the Last-Modified HTTP header with a DateTime instance. - * - * Passing null as value will remove the header. - * - * @return $this - * - * @final - */ - public function setLastModified(?\DateTimeInterface $date = null): object - { - if (null === $date) { - $this->headers->remove('Last-Modified'); - - return $this; - } - - if ($date instanceof \DateTime) { - $date = \DateTimeImmutable::createFromMutable($date); - } - - $date = $date->setTimezone(new \DateTimeZone('UTC')); - $this->headers->set('Last-Modified', $date->format('D, d M Y H:i:s').' GMT'); - - return $this; - } - - /** - * Returns the literal value of the ETag HTTP header. - * - * @final - */ - public function getEtag(): ?string - { - return $this->headers->get('ETag'); - } - - /** - * Sets the ETag value. - * - * @param string|null $etag The ETag unique identifier or null to remove the header - * @param bool $weak Whether you want a weak ETag or not - * - * @return $this - * - * @final - */ - public function setEtag(?string $etag = null, bool $weak = false): object - { - if (null === $etag) { - $this->headers->remove('Etag'); - } else { - if (!str_starts_with($etag, '"')) { - $etag = '"'.$etag.'"'; - } - - $this->headers->set('ETag', (true === $weak ? 'W/' : '').$etag); - } - - return $this; - } - - /** - * Sets the response's cache headers (validation and/or expiration). - * - * Available options are: must_revalidate, no_cache, no_store, no_transform, public, private, proxy_revalidate, max_age, s_maxage, immutable, last_modified and etag. - * - * @return $this - * - * @throws \InvalidArgumentException - * - * @final - */ - public function setCache(array $options): object - { - if ($diff = array_diff(array_keys($options), array_keys(self::HTTP_RESPONSE_CACHE_CONTROL_DIRECTIVES))) { - throw new \InvalidArgumentException(sprintf('Response does not support the following options: "%s".', implode('", "', $diff))); - } - - if (isset($options['etag'])) { - $this->setEtag($options['etag']); - } - - if (isset($options['last_modified'])) { - $this->setLastModified($options['last_modified']); - } - - if (isset($options['max_age'])) { - $this->setMaxAge($options['max_age']); - } - - if (isset($options['s_maxage'])) { - $this->setSharedMaxAge($options['s_maxage']); - } - - foreach (self::HTTP_RESPONSE_CACHE_CONTROL_DIRECTIVES as $directive => $hasValue) { - if (!$hasValue && isset($options[$directive])) { - if ($options[$directive]) { - $this->headers->addCacheControlDirective(str_replace('_', '-', $directive)); - } else { - $this->headers->removeCacheControlDirective(str_replace('_', '-', $directive)); - } - } - } - - if (isset($options['public'])) { - if ($options['public']) { - $this->setPublic(); - } else { - $this->setPrivate(); - } - } - - if (isset($options['private'])) { - if ($options['private']) { - $this->setPrivate(); - } else { - $this->setPublic(); - } - } - - return $this; - } - - /** - * Modifies the response so that it conforms to the rules defined for a 304 status code. - * - * This sets the status, removes the body, and discards any headers - * that MUST NOT be included in 304 responses. - * - * @return $this - * - * @see https://tools.ietf.org/html/rfc2616#section-10.3.5 - * - * @final - */ - public function setNotModified(): object - { - $this->setStatusCode(304); - $this->setContent(null); - - // remove headers that MUST NOT be included with 304 Not Modified responses - foreach (['Allow', 'Content-Encoding', 'Content-Language', 'Content-Length', 'Content-MD5', 'Content-Type', 'Last-Modified'] as $header) { - $this->headers->remove($header); - } - - return $this; - } - - /** - * Returns true if the response includes a Vary header. - * - * @final - */ - public function hasVary(): bool - { - return null !== $this->headers->get('Vary'); - } - - /** - * Returns an array of header names given in the Vary header. - * - * @final - */ - public function getVary(): array - { - if (!$vary = $this->headers->all('Vary')) { - return []; - } - - $ret = []; - foreach ($vary as $item) { - $ret[] = preg_split('/[\s,]+/', $item); - } - - return array_merge([], ...$ret); - } - - /** - * Sets the Vary header. - * - * @param string|array $headers - * @param bool $replace Whether to replace the actual value or not (true by default) - * - * @return $this - * - * @final - */ - public function setVary($headers, bool $replace = true): object - { - $this->headers->set('Vary', $headers, $replace); - - return $this; - } - - /** - * Determines if the Response validators (ETag, Last-Modified) match - * a conditional value specified in the Request. - * - * If the Response is not modified, it sets the status code to 304 and - * removes the actual content by calling the setNotModified() method. - * - * @final - */ - public function isNotModified(Request $request): bool - { - if (!$request->isMethodCacheable()) { - return false; - } - - $notModified = false; - $lastModified = $this->headers->get('Last-Modified'); - $modifiedSince = $request->headers->get('If-Modified-Since'); - - if (($ifNoneMatchEtags = $request->getETags()) && (null !== $etag = $this->getEtag())) { - if (0 == strncmp($etag, 'W/', 2)) { - $etag = substr($etag, 2); - } - - // Use weak comparison as per https://tools.ietf.org/html/rfc7232#section-3.2. - foreach ($ifNoneMatchEtags as $ifNoneMatchEtag) { - if (0 == strncmp($ifNoneMatchEtag, 'W/', 2)) { - $ifNoneMatchEtag = substr($ifNoneMatchEtag, 2); - } - - if ($ifNoneMatchEtag === $etag || '*' === $ifNoneMatchEtag) { - $notModified = true; - break; - } - } - } - // Only do If-Modified-Since date comparison when If-None-Match is not present as per https://tools.ietf.org/html/rfc7232#section-3.3. - elseif ($modifiedSince && $lastModified) { - $notModified = strtotime($modifiedSince) >= strtotime($lastModified); - } - - if ($notModified) { - $this->setNotModified(); - } - - return $notModified; - } - - /** - * Is response invalid? - * - * @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html - * - * @final - */ - public function isInvalid(): bool - { - return $this->statusCode < 100 || $this->statusCode >= 600; - } - - /** - * Is response informative? - * - * @final - */ - public function isInformational(): bool - { - return $this->statusCode >= 100 && $this->statusCode < 200; - } - - /** - * Is response successful? - * - * @final - */ - public function isSuccessful(): bool - { - return $this->statusCode >= 200 && $this->statusCode < 300; - } - - /** - * Is the response a redirect? - * - * @final - */ - public function isRedirection(): bool - { - return $this->statusCode >= 300 && $this->statusCode < 400; - } - - /** - * Is there a client error? - * - * @final - */ - public function isClientError(): bool - { - return $this->statusCode >= 400 && $this->statusCode < 500; - } - - /** - * Was there a server side error? - * - * @final - */ - public function isServerError(): bool - { - return $this->statusCode >= 500 && $this->statusCode < 600; - } - - /** - * Is the response OK? - * - * @final - */ - public function isOk(): bool - { - return 200 === $this->statusCode; - } - - /** - * Is the response forbidden? - * - * @final - */ - public function isForbidden(): bool - { - return 403 === $this->statusCode; - } - - /** - * Is the response a not found error? - * - * @final - */ - public function isNotFound(): bool - { - return 404 === $this->statusCode; - } - - /** - * Is the response a redirect of some form? - * - * @final - */ - public function isRedirect(?string $location = null): bool - { - return \in_array($this->statusCode, [201, 301, 302, 303, 307, 308]) && (null === $location ?: $location == $this->headers->get('Location')); - } - - /** - * Is the response empty? - * - * @final - */ - public function isEmpty(): bool - { - return \in_array($this->statusCode, [204, 304]); - } - - /** - * Cleans or flushes output buffers up to target level. - * - * Resulting level can be greater than target level if a non-removable buffer has been encountered. - * - * @final - */ - public static function closeOutputBuffers(int $targetLevel, bool $flush): void - { - $status = ob_get_status(true); - $level = \count($status); - $flags = \PHP_OUTPUT_HANDLER_REMOVABLE | ($flush ? \PHP_OUTPUT_HANDLER_FLUSHABLE : \PHP_OUTPUT_HANDLER_CLEANABLE); - - while ($level-- > $targetLevel && ($s = $status[$level]) && (!isset($s['del']) ? !isset($s['flags']) || ($s['flags'] & $flags) === $flags : $s['del'])) { - if ($flush) { - ob_end_flush(); - } else { - ob_end_clean(); - } - } - } - - /** - * Marks a response as safe according to RFC8674. - * - * @see https://tools.ietf.org/html/rfc8674 - */ - public function setContentSafe(bool $safe = true): void - { - if ($safe) { - $this->headers->set('Preference-Applied', 'safe'); - } elseif ('safe' === $this->headers->get('Preference-Applied')) { - $this->headers->remove('Preference-Applied'); - } - - $this->setVary('Prefer', false); - } - - /** - * Checks if we need to remove Cache-Control for SSL encrypted downloads when using IE < 9. - * - * @see http://support.microsoft.com/kb/323308 - * - * @final - */ - protected function ensureIEOverSSLCompatibility(Request $request): void - { - if (false !== stripos($this->headers->get('Content-Disposition') ?? '', 'attachment') && 1 == preg_match('/MSIE (.*?);/i', $request->server->get('HTTP_USER_AGENT') ?? '', $match) && true === $request->isSecure()) { - if ((int) preg_replace('/(MSIE )(.*?);/', '$2', $match[0]) < 9) { - $this->headers->remove('Cache-Control'); - } - } - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/ResponseHeaderBag.php b/digital_doctor/vendor/symfony/http-foundation/ResponseHeaderBag.php deleted file mode 100644 index d4c4f39..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/ResponseHeaderBag.php +++ /dev/null @@ -1,291 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * ResponseHeaderBag is a container for Response HTTP headers. - * - * @author Fabien Potencier - */ -class ResponseHeaderBag extends HeaderBag -{ - public const COOKIES_FLAT = 'flat'; - public const COOKIES_ARRAY = 'array'; - - public const DISPOSITION_ATTACHMENT = 'attachment'; - public const DISPOSITION_INLINE = 'inline'; - - protected $computedCacheControl = []; - protected $cookies = []; - protected $headerNames = []; - - public function __construct(array $headers = []) - { - parent::__construct($headers); - - if (!isset($this->headers['cache-control'])) { - $this->set('Cache-Control', ''); - } - - /* RFC2616 - 14.18 says all Responses need to have a Date */ - if (!isset($this->headers['date'])) { - $this->initDate(); - } - } - - /** - * Returns the headers, with original capitalizations. - * - * @return array - */ - public function allPreserveCase() - { - $headers = []; - foreach ($this->all() as $name => $value) { - $headers[$this->headerNames[$name] ?? $name] = $value; - } - - return $headers; - } - - public function allPreserveCaseWithoutCookies() - { - $headers = $this->allPreserveCase(); - if (isset($this->headerNames['set-cookie'])) { - unset($headers[$this->headerNames['set-cookie']]); - } - - return $headers; - } - - /** - * {@inheritdoc} - */ - public function replace(array $headers = []) - { - $this->headerNames = []; - - parent::replace($headers); - - if (!isset($this->headers['cache-control'])) { - $this->set('Cache-Control', ''); - } - - if (!isset($this->headers['date'])) { - $this->initDate(); - } - } - - /** - * {@inheritdoc} - */ - public function all(?string $key = null) - { - $headers = parent::all(); - - if (null !== $key) { - $key = strtr($key, self::UPPER, self::LOWER); - - return 'set-cookie' !== $key ? $headers[$key] ?? [] : array_map('strval', $this->getCookies()); - } - - foreach ($this->getCookies() as $cookie) { - $headers['set-cookie'][] = (string) $cookie; - } - - return $headers; - } - - /** - * {@inheritdoc} - */ - public function set(string $key, $values, bool $replace = true) - { - $uniqueKey = strtr($key, self::UPPER, self::LOWER); - - if ('set-cookie' === $uniqueKey) { - if ($replace) { - $this->cookies = []; - } - foreach ((array) $values as $cookie) { - $this->setCookie(Cookie::fromString($cookie)); - } - $this->headerNames[$uniqueKey] = $key; - - return; - } - - $this->headerNames[$uniqueKey] = $key; - - parent::set($key, $values, $replace); - - // ensure the cache-control header has sensible defaults - if (\in_array($uniqueKey, ['cache-control', 'etag', 'last-modified', 'expires'], true) && '' !== $computed = $this->computeCacheControlValue()) { - $this->headers['cache-control'] = [$computed]; - $this->headerNames['cache-control'] = 'Cache-Control'; - $this->computedCacheControl = $this->parseCacheControl($computed); - } - } - - /** - * {@inheritdoc} - */ - public function remove(string $key) - { - $uniqueKey = strtr($key, self::UPPER, self::LOWER); - unset($this->headerNames[$uniqueKey]); - - if ('set-cookie' === $uniqueKey) { - $this->cookies = []; - - return; - } - - parent::remove($key); - - if ('cache-control' === $uniqueKey) { - $this->computedCacheControl = []; - } - - if ('date' === $uniqueKey) { - $this->initDate(); - } - } - - /** - * {@inheritdoc} - */ - public function hasCacheControlDirective(string $key) - { - return \array_key_exists($key, $this->computedCacheControl); - } - - /** - * {@inheritdoc} - */ - public function getCacheControlDirective(string $key) - { - return $this->computedCacheControl[$key] ?? null; - } - - public function setCookie(Cookie $cookie) - { - $this->cookies[$cookie->getDomain()][$cookie->getPath()][$cookie->getName()] = $cookie; - $this->headerNames['set-cookie'] = 'Set-Cookie'; - } - - /** - * Removes a cookie from the array, but does not unset it in the browser. - */ - public function removeCookie(string $name, ?string $path = '/', ?string $domain = null) - { - if (null === $path) { - $path = '/'; - } - - unset($this->cookies[$domain][$path][$name]); - - if (empty($this->cookies[$domain][$path])) { - unset($this->cookies[$domain][$path]); - - if (empty($this->cookies[$domain])) { - unset($this->cookies[$domain]); - } - } - - if (empty($this->cookies)) { - unset($this->headerNames['set-cookie']); - } - } - - /** - * Returns an array with all cookies. - * - * @return Cookie[] - * - * @throws \InvalidArgumentException When the $format is invalid - */ - public function getCookies(string $format = self::COOKIES_FLAT) - { - if (!\in_array($format, [self::COOKIES_FLAT, self::COOKIES_ARRAY])) { - throw new \InvalidArgumentException(sprintf('Format "%s" invalid (%s).', $format, implode(', ', [self::COOKIES_FLAT, self::COOKIES_ARRAY]))); - } - - if (self::COOKIES_ARRAY === $format) { - return $this->cookies; - } - - $flattenedCookies = []; - foreach ($this->cookies as $path) { - foreach ($path as $cookies) { - foreach ($cookies as $cookie) { - $flattenedCookies[] = $cookie; - } - } - } - - return $flattenedCookies; - } - - /** - * Clears a cookie in the browser. - */ - public function clearCookie(string $name, ?string $path = '/', ?string $domain = null, bool $secure = false, bool $httpOnly = true, ?string $sameSite = null) - { - $this->setCookie(new Cookie($name, null, 1, $path, $domain, $secure, $httpOnly, false, $sameSite)); - } - - /** - * @see HeaderUtils::makeDisposition() - */ - public function makeDisposition(string $disposition, string $filename, string $filenameFallback = '') - { - return HeaderUtils::makeDisposition($disposition, $filename, $filenameFallback); - } - - /** - * Returns the calculated value of the cache-control header. - * - * This considers several other headers and calculates or modifies the - * cache-control header to a sensible, conservative value. - * - * @return string - */ - protected function computeCacheControlValue() - { - if (!$this->cacheControl) { - if ($this->has('Last-Modified') || $this->has('Expires')) { - return 'private, must-revalidate'; // allows for heuristic expiration (RFC 7234 Section 4.2.2) in the case of "Last-Modified" - } - - // conservative by default - return 'no-cache, private'; - } - - $header = $this->getCacheControlHeader(); - if (isset($this->cacheControl['public']) || isset($this->cacheControl['private'])) { - return $header; - } - - // public if s-maxage is defined, private otherwise - if (!isset($this->cacheControl['s-maxage'])) { - return $header.', private'; - } - - return $header; - } - - private function initDate(): void - { - $this->set('Date', gmdate('D, d M Y H:i:s').' GMT'); - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/ServerBag.php b/digital_doctor/vendor/symfony/http-foundation/ServerBag.php deleted file mode 100644 index 831caa6..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/ServerBag.php +++ /dev/null @@ -1,99 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * ServerBag is a container for HTTP headers from the $_SERVER variable. - * - * @author Fabien Potencier - * @author Bulat Shakirzyanov - * @author Robert Kiss - */ -class ServerBag extends ParameterBag -{ - /** - * Gets the HTTP headers. - * - * @return array - */ - public function getHeaders() - { - $headers = []; - foreach ($this->parameters as $key => $value) { - if (str_starts_with($key, 'HTTP_')) { - $headers[substr($key, 5)] = $value; - } elseif (\in_array($key, ['CONTENT_TYPE', 'CONTENT_LENGTH', 'CONTENT_MD5'], true) && '' !== $value) { - $headers[$key] = $value; - } - } - - if (isset($this->parameters['PHP_AUTH_USER'])) { - $headers['PHP_AUTH_USER'] = $this->parameters['PHP_AUTH_USER']; - $headers['PHP_AUTH_PW'] = $this->parameters['PHP_AUTH_PW'] ?? ''; - } else { - /* - * php-cgi under Apache does not pass HTTP Basic user/pass to PHP by default - * For this workaround to work, add these lines to your .htaccess file: - * RewriteCond %{HTTP:Authorization} .+ - * RewriteRule ^ - [E=HTTP_AUTHORIZATION:%0] - * - * A sample .htaccess file: - * RewriteEngine On - * RewriteCond %{HTTP:Authorization} .+ - * RewriteRule ^ - [E=HTTP_AUTHORIZATION:%0] - * RewriteCond %{REQUEST_FILENAME} !-f - * RewriteRule ^(.*)$ index.php [QSA,L] - */ - - $authorizationHeader = null; - if (isset($this->parameters['HTTP_AUTHORIZATION'])) { - $authorizationHeader = $this->parameters['HTTP_AUTHORIZATION']; - } elseif (isset($this->parameters['REDIRECT_HTTP_AUTHORIZATION'])) { - $authorizationHeader = $this->parameters['REDIRECT_HTTP_AUTHORIZATION']; - } - - if (null !== $authorizationHeader) { - if (0 === stripos($authorizationHeader, 'basic ')) { - // Decode AUTHORIZATION header into PHP_AUTH_USER and PHP_AUTH_PW when authorization header is basic - $exploded = explode(':', base64_decode(substr($authorizationHeader, 6)), 2); - if (2 == \count($exploded)) { - [$headers['PHP_AUTH_USER'], $headers['PHP_AUTH_PW']] = $exploded; - } - } elseif (empty($this->parameters['PHP_AUTH_DIGEST']) && (0 === stripos($authorizationHeader, 'digest '))) { - // In some circumstances PHP_AUTH_DIGEST needs to be set - $headers['PHP_AUTH_DIGEST'] = $authorizationHeader; - $this->parameters['PHP_AUTH_DIGEST'] = $authorizationHeader; - } elseif (0 === stripos($authorizationHeader, 'bearer ')) { - /* - * XXX: Since there is no PHP_AUTH_BEARER in PHP predefined variables, - * I'll just set $headers['AUTHORIZATION'] here. - * https://php.net/reserved.variables.server - */ - $headers['AUTHORIZATION'] = $authorizationHeader; - } - } - } - - if (isset($headers['AUTHORIZATION'])) { - return $headers; - } - - // PHP_AUTH_USER/PHP_AUTH_PW - if (isset($headers['PHP_AUTH_USER'])) { - $headers['AUTHORIZATION'] = 'Basic '.base64_encode($headers['PHP_AUTH_USER'].':'.($headers['PHP_AUTH_PW'] ?? '')); - } elseif (isset($headers['PHP_AUTH_DIGEST'])) { - $headers['AUTHORIZATION'] = $headers['PHP_AUTH_DIGEST']; - } - - return $headers; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/Attribute/AttributeBag.php b/digital_doctor/vendor/symfony/http-foundation/Session/Attribute/AttributeBag.php deleted file mode 100644 index f4f051c..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/Attribute/AttributeBag.php +++ /dev/null @@ -1,152 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Attribute; - -/** - * This class relates to session attribute storage. - * - * @implements \IteratorAggregate - */ -class AttributeBag implements AttributeBagInterface, \IteratorAggregate, \Countable -{ - private $name = 'attributes'; - private $storageKey; - - protected $attributes = []; - - /** - * @param string $storageKey The key used to store attributes in the session - */ - public function __construct(string $storageKey = '_sf2_attributes') - { - $this->storageKey = $storageKey; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return $this->name; - } - - public function setName(string $name) - { - $this->name = $name; - } - - /** - * {@inheritdoc} - */ - public function initialize(array &$attributes) - { - $this->attributes = &$attributes; - } - - /** - * {@inheritdoc} - */ - public function getStorageKey() - { - return $this->storageKey; - } - - /** - * {@inheritdoc} - */ - public function has(string $name) - { - return \array_key_exists($name, $this->attributes); - } - - /** - * {@inheritdoc} - */ - public function get(string $name, $default = null) - { - return \array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default; - } - - /** - * {@inheritdoc} - */ - public function set(string $name, $value) - { - $this->attributes[$name] = $value; - } - - /** - * {@inheritdoc} - */ - public function all() - { - return $this->attributes; - } - - /** - * {@inheritdoc} - */ - public function replace(array $attributes) - { - $this->attributes = []; - foreach ($attributes as $key => $value) { - $this->set($key, $value); - } - } - - /** - * {@inheritdoc} - */ - public function remove(string $name) - { - $retval = null; - if (\array_key_exists($name, $this->attributes)) { - $retval = $this->attributes[$name]; - unset($this->attributes[$name]); - } - - return $retval; - } - - /** - * {@inheritdoc} - */ - public function clear() - { - $return = $this->attributes; - $this->attributes = []; - - return $return; - } - - /** - * Returns an iterator for attributes. - * - * @return \ArrayIterator - */ - #[\ReturnTypeWillChange] - public function getIterator() - { - return new \ArrayIterator($this->attributes); - } - - /** - * Returns the number of attributes. - * - * @return int - */ - #[\ReturnTypeWillChange] - public function count() - { - return \count($this->attributes); - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/Attribute/AttributeBagInterface.php b/digital_doctor/vendor/symfony/http-foundation/Session/Attribute/AttributeBagInterface.php deleted file mode 100644 index cb50696..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/Attribute/AttributeBagInterface.php +++ /dev/null @@ -1,61 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Attribute; - -use Symfony\Component\HttpFoundation\Session\SessionBagInterface; - -/** - * Attributes store. - * - * @author Drak - */ -interface AttributeBagInterface extends SessionBagInterface -{ - /** - * Checks if an attribute is defined. - * - * @return bool - */ - public function has(string $name); - - /** - * Returns an attribute. - * - * @param mixed $default The default value if not found - * - * @return mixed - */ - public function get(string $name, $default = null); - - /** - * Sets an attribute. - * - * @param mixed $value - */ - public function set(string $name, $value); - - /** - * Returns attributes. - * - * @return array - */ - public function all(); - - public function replace(array $attributes); - - /** - * Removes an attribute. - * - * @return mixed The removed value or null when it does not exist - */ - public function remove(string $name); -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/Attribute/NamespacedAttributeBag.php b/digital_doctor/vendor/symfony/http-foundation/Session/Attribute/NamespacedAttributeBag.php deleted file mode 100644 index 864b35f..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/Attribute/NamespacedAttributeBag.php +++ /dev/null @@ -1,161 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Attribute; - -trigger_deprecation('symfony/http-foundation', '5.3', 'The "%s" class is deprecated.', NamespacedAttributeBag::class); - -/** - * This class provides structured storage of session attributes using - * a name spacing character in the key. - * - * @author Drak - * - * @deprecated since Symfony 5.3 - */ -class NamespacedAttributeBag extends AttributeBag -{ - private $namespaceCharacter; - - /** - * @param string $storageKey Session storage key - * @param string $namespaceCharacter Namespace character to use in keys - */ - public function __construct(string $storageKey = '_sf2_attributes', string $namespaceCharacter = '/') - { - $this->namespaceCharacter = $namespaceCharacter; - parent::__construct($storageKey); - } - - /** - * {@inheritdoc} - */ - public function has(string $name) - { - // reference mismatch: if fixed, re-introduced in array_key_exists; keep as it is - $attributes = $this->resolveAttributePath($name); - $name = $this->resolveKey($name); - - if (null === $attributes) { - return false; - } - - return \array_key_exists($name, $attributes); - } - - /** - * {@inheritdoc} - */ - public function get(string $name, $default = null) - { - // reference mismatch: if fixed, re-introduced in array_key_exists; keep as it is - $attributes = $this->resolveAttributePath($name); - $name = $this->resolveKey($name); - - if (null === $attributes) { - return $default; - } - - return \array_key_exists($name, $attributes) ? $attributes[$name] : $default; - } - - /** - * {@inheritdoc} - */ - public function set(string $name, $value) - { - $attributes = &$this->resolveAttributePath($name, true); - $name = $this->resolveKey($name); - $attributes[$name] = $value; - } - - /** - * {@inheritdoc} - */ - public function remove(string $name) - { - $retval = null; - $attributes = &$this->resolveAttributePath($name); - $name = $this->resolveKey($name); - if (null !== $attributes && \array_key_exists($name, $attributes)) { - $retval = $attributes[$name]; - unset($attributes[$name]); - } - - return $retval; - } - - /** - * Resolves a path in attributes property and returns it as a reference. - * - * This method allows structured namespacing of session attributes. - * - * @param string $name Key name - * @param bool $writeContext Write context, default false - * - * @return array|null - */ - protected function &resolveAttributePath(string $name, bool $writeContext = false) - { - $array = &$this->attributes; - $name = (str_starts_with($name, $this->namespaceCharacter)) ? substr($name, 1) : $name; - - // Check if there is anything to do, else return - if (!$name) { - return $array; - } - - $parts = explode($this->namespaceCharacter, $name); - if (\count($parts) < 2) { - if (!$writeContext) { - return $array; - } - - $array[$parts[0]] = []; - - return $array; - } - - unset($parts[\count($parts) - 1]); - - foreach ($parts as $part) { - if (null !== $array && !\array_key_exists($part, $array)) { - if (!$writeContext) { - $null = null; - - return $null; - } - - $array[$part] = []; - } - - $array = &$array[$part]; - } - - return $array; - } - - /** - * Resolves the key from the name. - * - * This is the last part in a dot separated string. - * - * @return string - */ - protected function resolveKey(string $name) - { - if (false !== $pos = strrpos($name, $this->namespaceCharacter)) { - $name = substr($name, $pos + 1); - } - - return $name; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/Flash/AutoExpireFlashBag.php b/digital_doctor/vendor/symfony/http-foundation/Session/Flash/AutoExpireFlashBag.php deleted file mode 100644 index 8aab3a1..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/Flash/AutoExpireFlashBag.php +++ /dev/null @@ -1,161 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Flash; - -/** - * AutoExpireFlashBag flash message container. - * - * @author Drak - */ -class AutoExpireFlashBag implements FlashBagInterface -{ - private $name = 'flashes'; - private $flashes = ['display' => [], 'new' => []]; - private $storageKey; - - /** - * @param string $storageKey The key used to store flashes in the session - */ - public function __construct(string $storageKey = '_symfony_flashes') - { - $this->storageKey = $storageKey; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return $this->name; - } - - public function setName(string $name) - { - $this->name = $name; - } - - /** - * {@inheritdoc} - */ - public function initialize(array &$flashes) - { - $this->flashes = &$flashes; - - // The logic: messages from the last request will be stored in new, so we move them to previous - // This request we will show what is in 'display'. What is placed into 'new' this time round will - // be moved to display next time round. - $this->flashes['display'] = \array_key_exists('new', $this->flashes) ? $this->flashes['new'] : []; - $this->flashes['new'] = []; - } - - /** - * {@inheritdoc} - */ - public function add(string $type, $message) - { - $this->flashes['new'][$type][] = $message; - } - - /** - * {@inheritdoc} - */ - public function peek(string $type, array $default = []) - { - return $this->has($type) ? $this->flashes['display'][$type] : $default; - } - - /** - * {@inheritdoc} - */ - public function peekAll() - { - return \array_key_exists('display', $this->flashes) ? $this->flashes['display'] : []; - } - - /** - * {@inheritdoc} - */ - public function get(string $type, array $default = []) - { - $return = $default; - - if (!$this->has($type)) { - return $return; - } - - if (isset($this->flashes['display'][$type])) { - $return = $this->flashes['display'][$type]; - unset($this->flashes['display'][$type]); - } - - return $return; - } - - /** - * {@inheritdoc} - */ - public function all() - { - $return = $this->flashes['display']; - $this->flashes['display'] = []; - - return $return; - } - - /** - * {@inheritdoc} - */ - public function setAll(array $messages) - { - $this->flashes['new'] = $messages; - } - - /** - * {@inheritdoc} - */ - public function set(string $type, $messages) - { - $this->flashes['new'][$type] = (array) $messages; - } - - /** - * {@inheritdoc} - */ - public function has(string $type) - { - return \array_key_exists($type, $this->flashes['display']) && $this->flashes['display'][$type]; - } - - /** - * {@inheritdoc} - */ - public function keys() - { - return array_keys($this->flashes['display']); - } - - /** - * {@inheritdoc} - */ - public function getStorageKey() - { - return $this->storageKey; - } - - /** - * {@inheritdoc} - */ - public function clear() - { - return $this->all(); - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/Flash/FlashBag.php b/digital_doctor/vendor/symfony/http-foundation/Session/Flash/FlashBag.php deleted file mode 100644 index 88df750..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/Flash/FlashBag.php +++ /dev/null @@ -1,152 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Flash; - -/** - * FlashBag flash message container. - * - * @author Drak - */ -class FlashBag implements FlashBagInterface -{ - private $name = 'flashes'; - private $flashes = []; - private $storageKey; - - /** - * @param string $storageKey The key used to store flashes in the session - */ - public function __construct(string $storageKey = '_symfony_flashes') - { - $this->storageKey = $storageKey; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return $this->name; - } - - public function setName(string $name) - { - $this->name = $name; - } - - /** - * {@inheritdoc} - */ - public function initialize(array &$flashes) - { - $this->flashes = &$flashes; - } - - /** - * {@inheritdoc} - */ - public function add(string $type, $message) - { - $this->flashes[$type][] = $message; - } - - /** - * {@inheritdoc} - */ - public function peek(string $type, array $default = []) - { - return $this->has($type) ? $this->flashes[$type] : $default; - } - - /** - * {@inheritdoc} - */ - public function peekAll() - { - return $this->flashes; - } - - /** - * {@inheritdoc} - */ - public function get(string $type, array $default = []) - { - if (!$this->has($type)) { - return $default; - } - - $return = $this->flashes[$type]; - - unset($this->flashes[$type]); - - return $return; - } - - /** - * {@inheritdoc} - */ - public function all() - { - $return = $this->peekAll(); - $this->flashes = []; - - return $return; - } - - /** - * {@inheritdoc} - */ - public function set(string $type, $messages) - { - $this->flashes[$type] = (array) $messages; - } - - /** - * {@inheritdoc} - */ - public function setAll(array $messages) - { - $this->flashes = $messages; - } - - /** - * {@inheritdoc} - */ - public function has(string $type) - { - return \array_key_exists($type, $this->flashes) && $this->flashes[$type]; - } - - /** - * {@inheritdoc} - */ - public function keys() - { - return array_keys($this->flashes); - } - - /** - * {@inheritdoc} - */ - public function getStorageKey() - { - return $this->storageKey; - } - - /** - * {@inheritdoc} - */ - public function clear() - { - return $this->all(); - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/Flash/FlashBagInterface.php b/digital_doctor/vendor/symfony/http-foundation/Session/Flash/FlashBagInterface.php deleted file mode 100644 index 8713e71..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/Flash/FlashBagInterface.php +++ /dev/null @@ -1,88 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Flash; - -use Symfony\Component\HttpFoundation\Session\SessionBagInterface; - -/** - * FlashBagInterface. - * - * @author Drak - */ -interface FlashBagInterface extends SessionBagInterface -{ - /** - * Adds a flash message for the given type. - * - * @param mixed $message - */ - public function add(string $type, $message); - - /** - * Registers one or more messages for a given type. - * - * @param string|array $messages - */ - public function set(string $type, $messages); - - /** - * Gets flash messages for a given type. - * - * @param string $type Message category type - * @param array $default Default value if $type does not exist - * - * @return array - */ - public function peek(string $type, array $default = []); - - /** - * Gets all flash messages. - * - * @return array - */ - public function peekAll(); - - /** - * Gets and clears flash from the stack. - * - * @param array $default Default value if $type does not exist - * - * @return array - */ - public function get(string $type, array $default = []); - - /** - * Gets and clears flashes from the stack. - * - * @return array - */ - public function all(); - - /** - * Sets all flash messages. - */ - public function setAll(array $messages); - - /** - * Has flash messages for a given type? - * - * @return bool - */ - public function has(string $type); - - /** - * Returns a list of all defined types. - * - * @return array - */ - public function keys(); -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/Session.php b/digital_doctor/vendor/symfony/http-foundation/Session/Session.php deleted file mode 100644 index 917920a..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/Session.php +++ /dev/null @@ -1,285 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session; - -use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; -use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBagInterface; -use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; -use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface; -use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; -use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface; - -// Help opcache.preload discover always-needed symbols -class_exists(AttributeBag::class); -class_exists(FlashBag::class); -class_exists(SessionBagProxy::class); - -/** - * @author Fabien Potencier - * @author Drak - * - * @implements \IteratorAggregate - */ -class Session implements SessionInterface, \IteratorAggregate, \Countable -{ - protected $storage; - - private $flashName; - private $attributeName; - private $data = []; - private $usageIndex = 0; - private $usageReporter; - - public function __construct(?SessionStorageInterface $storage = null, ?AttributeBagInterface $attributes = null, ?FlashBagInterface $flashes = null, ?callable $usageReporter = null) - { - $this->storage = $storage ?? new NativeSessionStorage(); - $this->usageReporter = $usageReporter; - - $attributes = $attributes ?? new AttributeBag(); - $this->attributeName = $attributes->getName(); - $this->registerBag($attributes); - - $flashes = $flashes ?? new FlashBag(); - $this->flashName = $flashes->getName(); - $this->registerBag($flashes); - } - - /** - * {@inheritdoc} - */ - public function start() - { - return $this->storage->start(); - } - - /** - * {@inheritdoc} - */ - public function has(string $name) - { - return $this->getAttributeBag()->has($name); - } - - /** - * {@inheritdoc} - */ - public function get(string $name, $default = null) - { - return $this->getAttributeBag()->get($name, $default); - } - - /** - * {@inheritdoc} - */ - public function set(string $name, $value) - { - $this->getAttributeBag()->set($name, $value); - } - - /** - * {@inheritdoc} - */ - public function all() - { - return $this->getAttributeBag()->all(); - } - - /** - * {@inheritdoc} - */ - public function replace(array $attributes) - { - $this->getAttributeBag()->replace($attributes); - } - - /** - * {@inheritdoc} - */ - public function remove(string $name) - { - return $this->getAttributeBag()->remove($name); - } - - /** - * {@inheritdoc} - */ - public function clear() - { - $this->getAttributeBag()->clear(); - } - - /** - * {@inheritdoc} - */ - public function isStarted() - { - return $this->storage->isStarted(); - } - - /** - * Returns an iterator for attributes. - * - * @return \ArrayIterator - */ - #[\ReturnTypeWillChange] - public function getIterator() - { - return new \ArrayIterator($this->getAttributeBag()->all()); - } - - /** - * Returns the number of attributes. - * - * @return int - */ - #[\ReturnTypeWillChange] - public function count() - { - return \count($this->getAttributeBag()->all()); - } - - public function &getUsageIndex(): int - { - return $this->usageIndex; - } - - /** - * @internal - */ - public function isEmpty(): bool - { - if ($this->isStarted()) { - ++$this->usageIndex; - if ($this->usageReporter && 0 <= $this->usageIndex) { - ($this->usageReporter)(); - } - } - foreach ($this->data as &$data) { - if (!empty($data)) { - return false; - } - } - - return true; - } - - /** - * {@inheritdoc} - */ - public function invalidate(?int $lifetime = null) - { - $this->storage->clear(); - - return $this->migrate(true, $lifetime); - } - - /** - * {@inheritdoc} - */ - public function migrate(bool $destroy = false, ?int $lifetime = null) - { - return $this->storage->regenerate($destroy, $lifetime); - } - - /** - * {@inheritdoc} - */ - public function save() - { - $this->storage->save(); - } - - /** - * {@inheritdoc} - */ - public function getId() - { - return $this->storage->getId(); - } - - /** - * {@inheritdoc} - */ - public function setId(string $id) - { - if ($this->storage->getId() !== $id) { - $this->storage->setId($id); - } - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return $this->storage->getName(); - } - - /** - * {@inheritdoc} - */ - public function setName(string $name) - { - $this->storage->setName($name); - } - - /** - * {@inheritdoc} - */ - public function getMetadataBag() - { - ++$this->usageIndex; - if ($this->usageReporter && 0 <= $this->usageIndex) { - ($this->usageReporter)(); - } - - return $this->storage->getMetadataBag(); - } - - /** - * {@inheritdoc} - */ - public function registerBag(SessionBagInterface $bag) - { - $this->storage->registerBag(new SessionBagProxy($bag, $this->data, $this->usageIndex, $this->usageReporter)); - } - - /** - * {@inheritdoc} - */ - public function getBag(string $name) - { - $bag = $this->storage->getBag($name); - - return method_exists($bag, 'getBag') ? $bag->getBag() : $bag; - } - - /** - * Gets the flashbag interface. - * - * @return FlashBagInterface - */ - public function getFlashBag() - { - return $this->getBag($this->flashName); - } - - /** - * Gets the attributebag interface. - * - * Note that this method was added to help with IDE autocompletion. - */ - private function getAttributeBag(): AttributeBagInterface - { - return $this->getBag($this->attributeName); - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/SessionBagInterface.php b/digital_doctor/vendor/symfony/http-foundation/Session/SessionBagInterface.php deleted file mode 100644 index 8e37d06..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/SessionBagInterface.php +++ /dev/null @@ -1,46 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session; - -/** - * Session Bag store. - * - * @author Drak - */ -interface SessionBagInterface -{ - /** - * Gets this bag's name. - * - * @return string - */ - public function getName(); - - /** - * Initializes the Bag. - */ - public function initialize(array &$array); - - /** - * Gets the storage key for this bag. - * - * @return string - */ - public function getStorageKey(); - - /** - * Clears out data from bag. - * - * @return mixed Whatever data was contained - */ - public function clear(); -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/SessionBagProxy.php b/digital_doctor/vendor/symfony/http-foundation/Session/SessionBagProxy.php deleted file mode 100644 index 90aa010..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/SessionBagProxy.php +++ /dev/null @@ -1,95 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session; - -/** - * @author Nicolas Grekas - * - * @internal - */ -final class SessionBagProxy implements SessionBagInterface -{ - private $bag; - private $data; - private $usageIndex; - private $usageReporter; - - public function __construct(SessionBagInterface $bag, array &$data, ?int &$usageIndex, ?callable $usageReporter) - { - $this->bag = $bag; - $this->data = &$data; - $this->usageIndex = &$usageIndex; - $this->usageReporter = $usageReporter; - } - - public function getBag(): SessionBagInterface - { - ++$this->usageIndex; - if ($this->usageReporter && 0 <= $this->usageIndex) { - ($this->usageReporter)(); - } - - return $this->bag; - } - - public function isEmpty(): bool - { - if (!isset($this->data[$this->bag->getStorageKey()])) { - return true; - } - ++$this->usageIndex; - if ($this->usageReporter && 0 <= $this->usageIndex) { - ($this->usageReporter)(); - } - - return empty($this->data[$this->bag->getStorageKey()]); - } - - /** - * {@inheritdoc} - */ - public function getName(): string - { - return $this->bag->getName(); - } - - /** - * {@inheritdoc} - */ - public function initialize(array &$array): void - { - ++$this->usageIndex; - if ($this->usageReporter && 0 <= $this->usageIndex) { - ($this->usageReporter)(); - } - - $this->data[$this->bag->getStorageKey()] = &$array; - - $this->bag->initialize($array); - } - - /** - * {@inheritdoc} - */ - public function getStorageKey(): string - { - return $this->bag->getStorageKey(); - } - - /** - * {@inheritdoc} - */ - public function clear() - { - return $this->bag->clear(); - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/SessionFactory.php b/digital_doctor/vendor/symfony/http-foundation/Session/SessionFactory.php deleted file mode 100644 index bd79282..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/SessionFactory.php +++ /dev/null @@ -1,40 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session; - -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageFactoryInterface; - -// Help opcache.preload discover always-needed symbols -class_exists(Session::class); - -/** - * @author Jérémy Derussé - */ -class SessionFactory implements SessionFactoryInterface -{ - private $requestStack; - private $storageFactory; - private $usageReporter; - - public function __construct(RequestStack $requestStack, SessionStorageFactoryInterface $storageFactory, ?callable $usageReporter = null) - { - $this->requestStack = $requestStack; - $this->storageFactory = $storageFactory; - $this->usageReporter = $usageReporter; - } - - public function createSession(): SessionInterface - { - return new Session($this->storageFactory->createStorage($this->requestStack->getMainRequest()), null, null, $this->usageReporter); - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/SessionFactoryInterface.php b/digital_doctor/vendor/symfony/http-foundation/Session/SessionFactoryInterface.php deleted file mode 100644 index b24fdc4..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/SessionFactoryInterface.php +++ /dev/null @@ -1,20 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session; - -/** - * @author Kevin Bond - */ -interface SessionFactoryInterface -{ - public function createSession(): SessionInterface; -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/SessionInterface.php b/digital_doctor/vendor/symfony/http-foundation/Session/SessionInterface.php deleted file mode 100644 index b73dfd0..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/SessionInterface.php +++ /dev/null @@ -1,166 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session; - -use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag; - -/** - * Interface for the session. - * - * @author Drak - */ -interface SessionInterface -{ - /** - * Starts the session storage. - * - * @return bool - * - * @throws \RuntimeException if session fails to start - */ - public function start(); - - /** - * Returns the session ID. - * - * @return string - */ - public function getId(); - - /** - * Sets the session ID. - */ - public function setId(string $id); - - /** - * Returns the session name. - * - * @return string - */ - public function getName(); - - /** - * Sets the session name. - */ - public function setName(string $name); - - /** - * Invalidates the current session. - * - * Clears all session attributes and flashes and regenerates the - * session and deletes the old session from persistence. - * - * @param int|null $lifetime Sets the cookie lifetime for the session cookie. A null value - * will leave the system settings unchanged, 0 sets the cookie - * to expire with browser session. Time is in seconds, and is - * not a Unix timestamp. - * - * @return bool - */ - public function invalidate(?int $lifetime = null); - - /** - * Migrates the current session to a new session id while maintaining all - * session attributes. - * - * @param bool $destroy Whether to delete the old session or leave it to garbage collection - * @param int|null $lifetime Sets the cookie lifetime for the session cookie. A null value - * will leave the system settings unchanged, 0 sets the cookie - * to expire with browser session. Time is in seconds, and is - * not a Unix timestamp. - * - * @return bool - */ - public function migrate(bool $destroy = false, ?int $lifetime = null); - - /** - * Force the session to be saved and closed. - * - * This method is generally not required for real sessions as - * the session will be automatically saved at the end of - * code execution. - */ - public function save(); - - /** - * Checks if an attribute is defined. - * - * @return bool - */ - public function has(string $name); - - /** - * Returns an attribute. - * - * @param mixed $default The default value if not found - * - * @return mixed - */ - public function get(string $name, $default = null); - - /** - * Sets an attribute. - * - * @param mixed $value - */ - public function set(string $name, $value); - - /** - * Returns attributes. - * - * @return array - */ - public function all(); - - /** - * Sets attributes. - */ - public function replace(array $attributes); - - /** - * Removes an attribute. - * - * @return mixed The removed value or null when it does not exist - */ - public function remove(string $name); - - /** - * Clears all attributes. - */ - public function clear(); - - /** - * Checks if the session was started. - * - * @return bool - */ - public function isStarted(); - - /** - * Registers a SessionBagInterface with the session. - */ - public function registerBag(SessionBagInterface $bag); - - /** - * Gets a bag instance by name. - * - * @return SessionBagInterface - */ - public function getBag(string $name); - - /** - * Gets session meta. - * - * @return MetadataBag - */ - public function getMetadataBag(); -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/SessionUtils.php b/digital_doctor/vendor/symfony/http-foundation/Session/SessionUtils.php deleted file mode 100644 index b5bce4a..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/SessionUtils.php +++ /dev/null @@ -1,59 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session; - -/** - * Session utility functions. - * - * @author Nicolas Grekas - * @author Rémon van de Kamp - * - * @internal - */ -final class SessionUtils -{ - /** - * Finds the session header amongst the headers that are to be sent, removes it, and returns - * it so the caller can process it further. - */ - public static function popSessionCookie(string $sessionName, string $sessionId): ?string - { - $sessionCookie = null; - $sessionCookiePrefix = sprintf(' %s=', urlencode($sessionName)); - $sessionCookieWithId = sprintf('%s%s;', $sessionCookiePrefix, urlencode($sessionId)); - $otherCookies = []; - foreach (headers_list() as $h) { - if (0 !== stripos($h, 'Set-Cookie:')) { - continue; - } - if (11 === strpos($h, $sessionCookiePrefix, 11)) { - $sessionCookie = $h; - - if (11 !== strpos($h, $sessionCookieWithId, 11)) { - $otherCookies[] = $h; - } - } else { - $otherCookies[] = $h; - } - } - if (null === $sessionCookie) { - return null; - } - - header_remove('Set-Cookie'); - foreach ($otherCookies as $h) { - header($h, false); - } - - return $sessionCookie; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php b/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php deleted file mode 100644 index 35d7b4b..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php +++ /dev/null @@ -1,155 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -use Symfony\Component\HttpFoundation\Session\SessionUtils; - -/** - * This abstract session handler provides a generic implementation - * of the PHP 7.0 SessionUpdateTimestampHandlerInterface, - * enabling strict and lazy session handling. - * - * @author Nicolas Grekas - */ -abstract class AbstractSessionHandler implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface -{ - private $sessionName; - private $prefetchId; - private $prefetchData; - private $newSessionId; - private $igbinaryEmptyData; - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function open($savePath, $sessionName) - { - $this->sessionName = $sessionName; - if (!headers_sent() && !\ini_get('session.cache_limiter') && '0' !== \ini_get('session.cache_limiter')) { - header(sprintf('Cache-Control: max-age=%d, private, must-revalidate', 60 * (int) \ini_get('session.cache_expire'))); - } - - return true; - } - - /** - * @return string - */ - abstract protected function doRead(string $sessionId); - - /** - * @return bool - */ - abstract protected function doWrite(string $sessionId, string $data); - - /** - * @return bool - */ - abstract protected function doDestroy(string $sessionId); - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function validateId($sessionId) - { - $this->prefetchData = $this->read($sessionId); - $this->prefetchId = $sessionId; - - if (\PHP_VERSION_ID < 70317 || (70400 <= \PHP_VERSION_ID && \PHP_VERSION_ID < 70405)) { - // work around https://bugs.php.net/79413 - foreach (debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS) as $frame) { - if (!isset($frame['class']) && isset($frame['function']) && \in_array($frame['function'], ['session_regenerate_id', 'session_create_id'], true)) { - return '' === $this->prefetchData; - } - } - } - - return '' !== $this->prefetchData; - } - - /** - * @return string - */ - #[\ReturnTypeWillChange] - public function read($sessionId) - { - if (null !== $this->prefetchId) { - $prefetchId = $this->prefetchId; - $prefetchData = $this->prefetchData; - $this->prefetchId = $this->prefetchData = null; - - if ($prefetchId === $sessionId || '' === $prefetchData) { - $this->newSessionId = '' === $prefetchData ? $sessionId : null; - - return $prefetchData; - } - } - - $data = $this->doRead($sessionId); - $this->newSessionId = '' === $data ? $sessionId : null; - - return $data; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function write($sessionId, $data) - { - if (null === $this->igbinaryEmptyData) { - // see https://github.com/igbinary/igbinary/issues/146 - $this->igbinaryEmptyData = \function_exists('igbinary_serialize') ? igbinary_serialize([]) : ''; - } - if ('' === $data || $this->igbinaryEmptyData === $data) { - return $this->destroy($sessionId); - } - $this->newSessionId = null; - - return $this->doWrite($sessionId, $data); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function destroy($sessionId) - { - if (!headers_sent() && filter_var(\ini_get('session.use_cookies'), \FILTER_VALIDATE_BOOLEAN)) { - if (!$this->sessionName) { - throw new \LogicException(sprintf('Session name cannot be empty, did you forget to call "parent::open()" in "%s"?.', static::class)); - } - $cookie = SessionUtils::popSessionCookie($this->sessionName, $sessionId); - - /* - * We send an invalidation Set-Cookie header (zero lifetime) - * when either the session was started or a cookie with - * the session name was sent by the client (in which case - * we know it's invalid as a valid session cookie would've - * started the session). - */ - if (null === $cookie || isset($_COOKIE[$this->sessionName])) { - if (\PHP_VERSION_ID < 70300) { - setcookie($this->sessionName, '', 0, \ini_get('session.cookie_path'), \ini_get('session.cookie_domain'), filter_var(\ini_get('session.cookie_secure'), \FILTER_VALIDATE_BOOLEAN), filter_var(\ini_get('session.cookie_httponly'), \FILTER_VALIDATE_BOOLEAN)); - } else { - $params = session_get_cookie_params(); - unset($params['lifetime']); - setcookie($this->sessionName, '', $params); - } - } - } - - return $this->newSessionId === $sessionId || $this->doDestroy($sessionId); - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/IdentityMarshaller.php b/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/IdentityMarshaller.php deleted file mode 100644 index bea3a32..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/IdentityMarshaller.php +++ /dev/null @@ -1,42 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -use Symfony\Component\Cache\Marshaller\MarshallerInterface; - -/** - * @author Ahmed TAILOULOUTE - */ -class IdentityMarshaller implements MarshallerInterface -{ - /** - * {@inheritdoc} - */ - public function marshall(array $values, ?array &$failed): array - { - foreach ($values as $key => $value) { - if (!\is_string($value)) { - throw new \LogicException(sprintf('%s accepts only string as data.', __METHOD__)); - } - } - - return $values; - } - - /** - * {@inheritdoc} - */ - public function unmarshall(string $value): string - { - return $value; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/MarshallingSessionHandler.php b/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/MarshallingSessionHandler.php deleted file mode 100644 index c321c8c..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/MarshallingSessionHandler.php +++ /dev/null @@ -1,108 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -use Symfony\Component\Cache\Marshaller\MarshallerInterface; - -/** - * @author Ahmed TAILOULOUTE - */ -class MarshallingSessionHandler implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface -{ - private $handler; - private $marshaller; - - public function __construct(AbstractSessionHandler $handler, MarshallerInterface $marshaller) - { - $this->handler = $handler; - $this->marshaller = $marshaller; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function open($savePath, $name) - { - return $this->handler->open($savePath, $name); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function close() - { - return $this->handler->close(); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function destroy($sessionId) - { - return $this->handler->destroy($sessionId); - } - - /** - * @return int|false - */ - #[\ReturnTypeWillChange] - public function gc($maxlifetime) - { - return $this->handler->gc($maxlifetime); - } - - /** - * @return string - */ - #[\ReturnTypeWillChange] - public function read($sessionId) - { - return $this->marshaller->unmarshall($this->handler->read($sessionId)); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function write($sessionId, $data) - { - $failed = []; - $marshalledData = $this->marshaller->marshall(['data' => $data], $failed); - - if (isset($failed['data'])) { - return false; - } - - return $this->handler->write($sessionId, $marshalledData['data']); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function validateId($sessionId) - { - return $this->handler->validateId($sessionId); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function updateTimestamp($sessionId, $data) - { - return $this->handler->updateTimestamp($sessionId, $data); - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php b/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php deleted file mode 100644 index e0ec4d2..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php +++ /dev/null @@ -1,135 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -/** - * Memcached based session storage handler based on the Memcached class - * provided by the PHP memcached extension. - * - * @see https://php.net/memcached - * - * @author Drak - */ -class MemcachedSessionHandler extends AbstractSessionHandler -{ - private $memcached; - - /** - * @var int Time to live in seconds - */ - private $ttl; - - /** - * @var string Key prefix for shared environments - */ - private $prefix; - - /** - * Constructor. - * - * List of available options: - * * prefix: The prefix to use for the memcached keys in order to avoid collision - * * ttl: The time to live in seconds. - * - * @throws \InvalidArgumentException When unsupported options are passed - */ - public function __construct(\Memcached $memcached, array $options = []) - { - $this->memcached = $memcached; - - if ($diff = array_diff(array_keys($options), ['prefix', 'expiretime', 'ttl'])) { - throw new \InvalidArgumentException(sprintf('The following options are not supported "%s".', implode(', ', $diff))); - } - - $this->ttl = $options['expiretime'] ?? $options['ttl'] ?? null; - $this->prefix = $options['prefix'] ?? 'sf2s'; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function close() - { - return $this->memcached->quit(); - } - - /** - * {@inheritdoc} - */ - protected function doRead(string $sessionId) - { - return $this->memcached->get($this->prefix.$sessionId) ?: ''; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function updateTimestamp($sessionId, $data) - { - $this->memcached->touch($this->prefix.$sessionId, $this->getCompatibleTtl()); - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doWrite(string $sessionId, string $data) - { - return $this->memcached->set($this->prefix.$sessionId, $data, $this->getCompatibleTtl()); - } - - private function getCompatibleTtl(): int - { - $ttl = (int) ($this->ttl ?? \ini_get('session.gc_maxlifetime')); - - // If the relative TTL that is used exceeds 30 days, memcached will treat the value as Unix time. - // We have to convert it to an absolute Unix time at this point, to make sure the TTL is correct. - if ($ttl > 60 * 60 * 24 * 30) { - $ttl += time(); - } - - return $ttl; - } - - /** - * {@inheritdoc} - */ - protected function doDestroy(string $sessionId) - { - $result = $this->memcached->delete($this->prefix.$sessionId); - - return $result || \Memcached::RES_NOTFOUND == $this->memcached->getResultCode(); - } - - /** - * @return int|false - */ - #[\ReturnTypeWillChange] - public function gc($maxlifetime) - { - // not required here because memcached will auto expire the records anyhow. - return 0; - } - - /** - * Return a Memcached instance. - * - * @return \Memcached - */ - protected function getMemcached() - { - return $this->memcached; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/MigratingSessionHandler.php b/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/MigratingSessionHandler.php deleted file mode 100644 index bf27ca6..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/MigratingSessionHandler.php +++ /dev/null @@ -1,139 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -/** - * Migrating session handler for migrating from one handler to another. It reads - * from the current handler and writes both the current and new ones. - * - * It ignores errors from the new handler. - * - * @author Ross Motley - * @author Oliver Radwell - */ -class MigratingSessionHandler implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface -{ - /** - * @var \SessionHandlerInterface&\SessionUpdateTimestampHandlerInterface - */ - private $currentHandler; - - /** - * @var \SessionHandlerInterface&\SessionUpdateTimestampHandlerInterface - */ - private $writeOnlyHandler; - - public function __construct(\SessionHandlerInterface $currentHandler, \SessionHandlerInterface $writeOnlyHandler) - { - if (!$currentHandler instanceof \SessionUpdateTimestampHandlerInterface) { - $currentHandler = new StrictSessionHandler($currentHandler); - } - if (!$writeOnlyHandler instanceof \SessionUpdateTimestampHandlerInterface) { - $writeOnlyHandler = new StrictSessionHandler($writeOnlyHandler); - } - - $this->currentHandler = $currentHandler; - $this->writeOnlyHandler = $writeOnlyHandler; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function close() - { - $result = $this->currentHandler->close(); - $this->writeOnlyHandler->close(); - - return $result; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function destroy($sessionId) - { - $result = $this->currentHandler->destroy($sessionId); - $this->writeOnlyHandler->destroy($sessionId); - - return $result; - } - - /** - * @return int|false - */ - #[\ReturnTypeWillChange] - public function gc($maxlifetime) - { - $result = $this->currentHandler->gc($maxlifetime); - $this->writeOnlyHandler->gc($maxlifetime); - - return $result; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function open($savePath, $sessionName) - { - $result = $this->currentHandler->open($savePath, $sessionName); - $this->writeOnlyHandler->open($savePath, $sessionName); - - return $result; - } - - /** - * @return string - */ - #[\ReturnTypeWillChange] - public function read($sessionId) - { - // No reading from new handler until switch-over - return $this->currentHandler->read($sessionId); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function write($sessionId, $sessionData) - { - $result = $this->currentHandler->write($sessionId, $sessionData); - $this->writeOnlyHandler->write($sessionId, $sessionData); - - return $result; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function validateId($sessionId) - { - // No reading from new handler until switch-over - return $this->currentHandler->validateId($sessionId); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function updateTimestamp($sessionId, $sessionData) - { - $result = $this->currentHandler->updateTimestamp($sessionId, $sessionData); - $this->writeOnlyHandler->updateTimestamp($sessionId, $sessionData); - - return $result; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php b/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php deleted file mode 100644 index ef8f719..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php +++ /dev/null @@ -1,193 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -use MongoDB\BSON\Binary; -use MongoDB\BSON\UTCDateTime; -use MongoDB\Client; -use MongoDB\Collection; - -/** - * Session handler using the mongodb/mongodb package and MongoDB driver extension. - * - * @author Markus Bachmann - * - * @see https://packagist.org/packages/mongodb/mongodb - * @see https://php.net/mongodb - */ -class MongoDbSessionHandler extends AbstractSessionHandler -{ - private $mongo; - - /** - * @var Collection - */ - private $collection; - - /** - * @var array - */ - private $options; - - /** - * Constructor. - * - * List of available options: - * * database: The name of the database [required] - * * collection: The name of the collection [required] - * * id_field: The field name for storing the session id [default: _id] - * * data_field: The field name for storing the session data [default: data] - * * time_field: The field name for storing the timestamp [default: time] - * * expiry_field: The field name for storing the expiry-timestamp [default: expires_at]. - * - * It is strongly recommended to put an index on the `expiry_field` for - * garbage-collection. Alternatively it's possible to automatically expire - * the sessions in the database as described below: - * - * A TTL collections can be used on MongoDB 2.2+ to cleanup expired sessions - * automatically. Such an index can for example look like this: - * - * db..createIndex( - * { "": 1 }, - * { "expireAfterSeconds": 0 } - * ) - * - * More details on: https://docs.mongodb.org/manual/tutorial/expire-data/ - * - * If you use such an index, you can drop `gc_probability` to 0 since - * no garbage-collection is required. - * - * @throws \InvalidArgumentException When "database" or "collection" not provided - */ - public function __construct(Client $mongo, array $options) - { - if (!isset($options['database']) || !isset($options['collection'])) { - throw new \InvalidArgumentException('You must provide the "database" and "collection" option for MongoDBSessionHandler.'); - } - - $this->mongo = $mongo; - - $this->options = array_merge([ - 'id_field' => '_id', - 'data_field' => 'data', - 'time_field' => 'time', - 'expiry_field' => 'expires_at', - ], $options); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function close() - { - return true; - } - - /** - * {@inheritdoc} - */ - protected function doDestroy(string $sessionId) - { - $this->getCollection()->deleteOne([ - $this->options['id_field'] => $sessionId, - ]); - - return true; - } - - /** - * @return int|false - */ - #[\ReturnTypeWillChange] - public function gc($maxlifetime) - { - return $this->getCollection()->deleteMany([ - $this->options['expiry_field'] => ['$lt' => new UTCDateTime()], - ])->getDeletedCount(); - } - - /** - * {@inheritdoc} - */ - protected function doWrite(string $sessionId, string $data) - { - $expiry = new UTCDateTime((time() + (int) \ini_get('session.gc_maxlifetime')) * 1000); - - $fields = [ - $this->options['time_field'] => new UTCDateTime(), - $this->options['expiry_field'] => $expiry, - $this->options['data_field'] => new Binary($data, Binary::TYPE_OLD_BINARY), - ]; - - $this->getCollection()->updateOne( - [$this->options['id_field'] => $sessionId], - ['$set' => $fields], - ['upsert' => true] - ); - - return true; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function updateTimestamp($sessionId, $data) - { - $expiry = new UTCDateTime((time() + (int) \ini_get('session.gc_maxlifetime')) * 1000); - - $this->getCollection()->updateOne( - [$this->options['id_field'] => $sessionId], - ['$set' => [ - $this->options['time_field'] => new UTCDateTime(), - $this->options['expiry_field'] => $expiry, - ]] - ); - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doRead(string $sessionId) - { - $dbData = $this->getCollection()->findOne([ - $this->options['id_field'] => $sessionId, - $this->options['expiry_field'] => ['$gte' => new UTCDateTime()], - ]); - - if (null === $dbData) { - return ''; - } - - return $dbData[$this->options['data_field']]->getData(); - } - - private function getCollection(): Collection - { - if (null === $this->collection) { - $this->collection = $this->mongo->selectCollection($this->options['database'], $this->options['collection']); - } - - return $this->collection; - } - - /** - * @return Client - */ - protected function getMongo() - { - return $this->mongo; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php b/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php deleted file mode 100644 index 570d4f4..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php +++ /dev/null @@ -1,59 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -/** - * Native session handler using PHP's built in file storage. - * - * @author Drak - */ -class NativeFileSessionHandler extends \SessionHandler -{ - /** - * @param string|null $savePath Path of directory to save session files - * Default null will leave setting as defined by PHP. - * '/path', 'N;/path', or 'N;octal-mode;/path - * - * @see https://php.net/session.configuration#ini.session.save-path for further details. - * - * @throws \InvalidArgumentException On invalid $savePath - * @throws \RuntimeException When failing to create the save directory - */ - public function __construct(?string $savePath = null) - { - if (null === $savePath) { - $savePath = \ini_get('session.save_path'); - } - - $baseDir = $savePath; - - if ($count = substr_count($savePath, ';')) { - if ($count > 2) { - throw new \InvalidArgumentException(sprintf('Invalid argument $savePath \'%s\'.', $savePath)); - } - - // characters after last ';' are the path - $baseDir = ltrim(strrchr($savePath, ';'), ';'); - } - - if ($baseDir && !is_dir($baseDir) && !@mkdir($baseDir, 0777, true) && !is_dir($baseDir)) { - throw new \RuntimeException(sprintf('Session Storage was not able to create directory "%s".', $baseDir)); - } - - if ($savePath !== \ini_get('session.save_path')) { - ini_set('session.save_path', $savePath); - } - if ('files' !== \ini_get('session.save_handler')) { - ini_set('session.save_handler', 'files'); - } - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/NullSessionHandler.php b/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/NullSessionHandler.php deleted file mode 100644 index 4331dbe..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/NullSessionHandler.php +++ /dev/null @@ -1,80 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -/** - * Can be used in unit testing or in a situations where persisted sessions are not desired. - * - * @author Drak - */ -class NullSessionHandler extends AbstractSessionHandler -{ - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function close() - { - return true; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function validateId($sessionId) - { - return true; - } - - /** - * {@inheritdoc} - */ - protected function doRead(string $sessionId) - { - return ''; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function updateTimestamp($sessionId, $data) - { - return true; - } - - /** - * {@inheritdoc} - */ - protected function doWrite(string $sessionId, string $data) - { - return true; - } - - /** - * {@inheritdoc} - */ - protected function doDestroy(string $sessionId) - { - return true; - } - - /** - * @return int|false - */ - #[\ReturnTypeWillChange] - public function gc($maxlifetime) - { - return 0; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php b/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php deleted file mode 100644 index f9c5d9b..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php +++ /dev/null @@ -1,943 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -/** - * Session handler using a PDO connection to read and write data. - * - * It works with MySQL, PostgreSQL, Oracle, SQL Server and SQLite and implements - * different locking strategies to handle concurrent access to the same session. - * Locking is necessary to prevent loss of data due to race conditions and to keep - * the session data consistent between read() and write(). With locking, requests - * for the same session will wait until the other one finished writing. For this - * reason it's best practice to close a session as early as possible to improve - * concurrency. PHPs internal files session handler also implements locking. - * - * Attention: Since SQLite does not support row level locks but locks the whole database, - * it means only one session can be accessed at a time. Even different sessions would wait - * for another to finish. So saving session in SQLite should only be considered for - * development or prototypes. - * - * Session data is a binary string that can contain non-printable characters like the null byte. - * For this reason it must be saved in a binary column in the database like BLOB in MySQL. - * Saving it in a character column could corrupt the data. You can use createTable() - * to initialize a correctly defined table. - * - * @see https://php.net/sessionhandlerinterface - * - * @author Fabien Potencier - * @author Michael Williams - * @author Tobias Schultze - */ -class PdoSessionHandler extends AbstractSessionHandler -{ - /** - * No locking is done. This means sessions are prone to loss of data due to - * race conditions of concurrent requests to the same session. The last session - * write will win in this case. It might be useful when you implement your own - * logic to deal with this like an optimistic approach. - */ - public const LOCK_NONE = 0; - - /** - * Creates an application-level lock on a session. The disadvantage is that the - * lock is not enforced by the database and thus other, unaware parts of the - * application could still concurrently modify the session. The advantage is it - * does not require a transaction. - * This mode is not available for SQLite and not yet implemented for oci and sqlsrv. - */ - public const LOCK_ADVISORY = 1; - - /** - * Issues a real row lock. Since it uses a transaction between opening and - * closing a session, you have to be careful when you use same database connection - * that you also use for your application logic. This mode is the default because - * it's the only reliable solution across DBMSs. - */ - public const LOCK_TRANSACTIONAL = 2; - - private const MAX_LIFETIME = 315576000; - - /** - * @var \PDO|null PDO instance or null when not connected yet - */ - private $pdo; - - /** - * DSN string or null for session.save_path or false when lazy connection disabled. - * - * @var string|false|null - */ - private $dsn = false; - - /** - * @var string|null - */ - private $driver; - - /** - * @var string - */ - private $table = 'sessions'; - - /** - * @var string - */ - private $idCol = 'sess_id'; - - /** - * @var string - */ - private $dataCol = 'sess_data'; - - /** - * @var string - */ - private $lifetimeCol = 'sess_lifetime'; - - /** - * @var string - */ - private $timeCol = 'sess_time'; - - /** - * Username when lazy-connect. - * - * @var string|null - */ - private $username = null; - - /** - * Password when lazy-connect. - * - * @var string|null - */ - private $password = null; - - /** - * Connection options when lazy-connect. - * - * @var array - */ - private $connectionOptions = []; - - /** - * The strategy for locking, see constants. - * - * @var int - */ - private $lockMode = self::LOCK_TRANSACTIONAL; - - /** - * It's an array to support multiple reads before closing which is manual, non-standard usage. - * - * @var \PDOStatement[] An array of statements to release advisory locks - */ - private $unlockStatements = []; - - /** - * True when the current session exists but expired according to session.gc_maxlifetime. - * - * @var bool - */ - private $sessionExpired = false; - - /** - * Whether a transaction is active. - * - * @var bool - */ - private $inTransaction = false; - - /** - * Whether gc() has been called. - * - * @var bool - */ - private $gcCalled = false; - - /** - * You can either pass an existing database connection as PDO instance or - * pass a DSN string that will be used to lazy-connect to the database - * when the session is actually used. Furthermore it's possible to pass null - * which will then use the session.save_path ini setting as PDO DSN parameter. - * - * List of available options: - * * db_table: The name of the table [default: sessions] - * * db_id_col: The column where to store the session id [default: sess_id] - * * db_data_col: The column where to store the session data [default: sess_data] - * * db_lifetime_col: The column where to store the lifetime [default: sess_lifetime] - * * db_time_col: The column where to store the timestamp [default: sess_time] - * * db_username: The username when lazy-connect [default: ''] - * * db_password: The password when lazy-connect [default: ''] - * * db_connection_options: An array of driver-specific connection options [default: []] - * * lock_mode: The strategy for locking, see constants [default: LOCK_TRANSACTIONAL] - * - * @param \PDO|string|null $pdoOrDsn A \PDO instance or DSN string or URL string or null - * - * @throws \InvalidArgumentException When PDO error mode is not PDO::ERRMODE_EXCEPTION - */ - public function __construct($pdoOrDsn = null, array $options = []) - { - if ($pdoOrDsn instanceof \PDO) { - if (\PDO::ERRMODE_EXCEPTION !== $pdoOrDsn->getAttribute(\PDO::ATTR_ERRMODE)) { - throw new \InvalidArgumentException(sprintf('"%s" requires PDO error mode attribute be set to throw Exceptions (i.e. $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)).', __CLASS__)); - } - - $this->pdo = $pdoOrDsn; - $this->driver = $this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME); - } elseif (\is_string($pdoOrDsn) && str_contains($pdoOrDsn, '://')) { - $this->dsn = $this->buildDsnFromUrl($pdoOrDsn); - } else { - $this->dsn = $pdoOrDsn; - } - - $this->table = $options['db_table'] ?? $this->table; - $this->idCol = $options['db_id_col'] ?? $this->idCol; - $this->dataCol = $options['db_data_col'] ?? $this->dataCol; - $this->lifetimeCol = $options['db_lifetime_col'] ?? $this->lifetimeCol; - $this->timeCol = $options['db_time_col'] ?? $this->timeCol; - $this->username = $options['db_username'] ?? $this->username; - $this->password = $options['db_password'] ?? $this->password; - $this->connectionOptions = $options['db_connection_options'] ?? $this->connectionOptions; - $this->lockMode = $options['lock_mode'] ?? $this->lockMode; - } - - /** - * Creates the table to store sessions which can be called once for setup. - * - * Session ID is saved in a column of maximum length 128 because that is enough even - * for a 512 bit configured session.hash_function like Whirlpool. Session data is - * saved in a BLOB. One could also use a shorter inlined varbinary column - * if one was sure the data fits into it. - * - * @throws \PDOException When the table already exists - * @throws \DomainException When an unsupported PDO driver is used - */ - public function createTable() - { - // connect if we are not yet - $this->getConnection(); - - switch ($this->driver) { - case 'mysql': - // We use varbinary for the ID column because it prevents unwanted conversions: - // - character set conversions between server and client - // - trailing space removal - // - case-insensitivity - // - language processing like é == e - $sql = "CREATE TABLE $this->table ($this->idCol VARBINARY(128) NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER UNSIGNED NOT NULL, $this->timeCol INTEGER UNSIGNED NOT NULL) COLLATE utf8mb4_bin, ENGINE = InnoDB"; - break; - case 'sqlite': - $sql = "CREATE TABLE $this->table ($this->idCol TEXT NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)"; - break; - case 'pgsql': - $sql = "CREATE TABLE $this->table ($this->idCol VARCHAR(128) NOT NULL PRIMARY KEY, $this->dataCol BYTEA NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)"; - break; - case 'oci': - $sql = "CREATE TABLE $this->table ($this->idCol VARCHAR2(128) NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)"; - break; - case 'sqlsrv': - $sql = "CREATE TABLE $this->table ($this->idCol VARCHAR(128) NOT NULL PRIMARY KEY, $this->dataCol VARBINARY(MAX) NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)"; - break; - default: - throw new \DomainException(sprintf('Creating the session table is currently not implemented for PDO driver "%s".', $this->driver)); - } - - try { - $this->pdo->exec($sql); - $this->pdo->exec("CREATE INDEX EXPIRY ON $this->table ($this->lifetimeCol)"); - } catch (\PDOException $e) { - $this->rollback(); - - throw $e; - } - } - - /** - * Returns true when the current session exists but expired according to session.gc_maxlifetime. - * - * Can be used to distinguish between a new session and one that expired due to inactivity. - * - * @return bool - */ - public function isSessionExpired() - { - return $this->sessionExpired; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function open($savePath, $sessionName) - { - $this->sessionExpired = false; - - if (null === $this->pdo) { - $this->connect($this->dsn ?: $savePath); - } - - return parent::open($savePath, $sessionName); - } - - /** - * @return string - */ - #[\ReturnTypeWillChange] - public function read($sessionId) - { - try { - return parent::read($sessionId); - } catch (\PDOException $e) { - $this->rollback(); - - throw $e; - } - } - - /** - * @return int|false - */ - #[\ReturnTypeWillChange] - public function gc($maxlifetime) - { - // We delay gc() to close() so that it is executed outside the transactional and blocking read-write process. - // This way, pruning expired sessions does not block them from being started while the current session is used. - $this->gcCalled = true; - - return 0; - } - - /** - * {@inheritdoc} - */ - protected function doDestroy(string $sessionId) - { - // delete the record associated with this id - $sql = "DELETE FROM $this->table WHERE $this->idCol = :id"; - - try { - $stmt = $this->pdo->prepare($sql); - $stmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); - $stmt->execute(); - } catch (\PDOException $e) { - $this->rollback(); - - throw $e; - } - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doWrite(string $sessionId, string $data) - { - $maxlifetime = (int) \ini_get('session.gc_maxlifetime'); - - try { - // We use a single MERGE SQL query when supported by the database. - $mergeStmt = $this->getMergeStatement($sessionId, $data, $maxlifetime); - if (null !== $mergeStmt) { - $mergeStmt->execute(); - - return true; - } - - $updateStmt = $this->getUpdateStatement($sessionId, $data, $maxlifetime); - $updateStmt->execute(); - - // When MERGE is not supported, like in Postgres < 9.5, we have to use this approach that can result in - // duplicate key errors when the same session is written simultaneously (given the LOCK_NONE behavior). - // We can just catch such an error and re-execute the update. This is similar to a serializable - // transaction with retry logic on serialization failures but without the overhead and without possible - // false positives due to longer gap locking. - if (!$updateStmt->rowCount()) { - try { - $insertStmt = $this->getInsertStatement($sessionId, $data, $maxlifetime); - $insertStmt->execute(); - } catch (\PDOException $e) { - // Handle integrity violation SQLSTATE 23000 (or a subclass like 23505 in Postgres) for duplicate keys - if (str_starts_with($e->getCode(), '23')) { - $updateStmt->execute(); - } else { - throw $e; - } - } - } - } catch (\PDOException $e) { - $this->rollback(); - - throw $e; - } - - return true; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function updateTimestamp($sessionId, $data) - { - $expiry = time() + (int) \ini_get('session.gc_maxlifetime'); - - try { - $updateStmt = $this->pdo->prepare( - "UPDATE $this->table SET $this->lifetimeCol = :expiry, $this->timeCol = :time WHERE $this->idCol = :id" - ); - $updateStmt->bindValue(':id', $sessionId, \PDO::PARAM_STR); - $updateStmt->bindValue(':expiry', $expiry, \PDO::PARAM_INT); - $updateStmt->bindValue(':time', time(), \PDO::PARAM_INT); - $updateStmt->execute(); - } catch (\PDOException $e) { - $this->rollback(); - - throw $e; - } - - return true; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function close() - { - $this->commit(); - - while ($unlockStmt = array_shift($this->unlockStatements)) { - $unlockStmt->execute(); - } - - if ($this->gcCalled) { - $this->gcCalled = false; - - // delete the session records that have expired - $sql = "DELETE FROM $this->table WHERE $this->lifetimeCol < :time AND $this->lifetimeCol > :min"; - $stmt = $this->pdo->prepare($sql); - $stmt->bindValue(':time', time(), \PDO::PARAM_INT); - $stmt->bindValue(':min', self::MAX_LIFETIME, \PDO::PARAM_INT); - $stmt->execute(); - // to be removed in 6.0 - if ('mysql' === $this->driver) { - $legacySql = "DELETE FROM $this->table WHERE $this->lifetimeCol <= :min AND $this->lifetimeCol + $this->timeCol < :time"; - } else { - $legacySql = "DELETE FROM $this->table WHERE $this->lifetimeCol <= :min AND $this->lifetimeCol < :time - $this->timeCol"; - } - - $stmt = $this->pdo->prepare($legacySql); - $stmt->bindValue(':time', time(), \PDO::PARAM_INT); - $stmt->bindValue(':min', self::MAX_LIFETIME, \PDO::PARAM_INT); - $stmt->execute(); - } - - if (false !== $this->dsn) { - $this->pdo = null; // only close lazy-connection - $this->driver = null; - } - - return true; - } - - /** - * Lazy-connects to the database. - */ - private function connect(string $dsn): void - { - $this->pdo = new \PDO($dsn, $this->username, $this->password, $this->connectionOptions); - $this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); - $this->driver = $this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME); - } - - /** - * Builds a PDO DSN from a URL-like connection string. - * - * @todo implement missing support for oci DSN (which look totally different from other PDO ones) - */ - private function buildDsnFromUrl(string $dsnOrUrl): string - { - // (pdo_)?sqlite3?:///... => (pdo_)?sqlite3?://localhost/... or else the URL will be invalid - $url = preg_replace('#^((?:pdo_)?sqlite3?):///#', '$1://localhost/', $dsnOrUrl); - - $params = parse_url($url); - - if (false === $params) { - return $dsnOrUrl; // If the URL is not valid, let's assume it might be a DSN already. - } - - $params = array_map('rawurldecode', $params); - - // Override the default username and password. Values passed through options will still win over these in the constructor. - if (isset($params['user'])) { - $this->username = $params['user']; - } - - if (isset($params['pass'])) { - $this->password = $params['pass']; - } - - if (!isset($params['scheme'])) { - throw new \InvalidArgumentException('URLs without scheme are not supported to configure the PdoSessionHandler.'); - } - - $driverAliasMap = [ - 'mssql' => 'sqlsrv', - 'mysql2' => 'mysql', // Amazon RDS, for some weird reason - 'postgres' => 'pgsql', - 'postgresql' => 'pgsql', - 'sqlite3' => 'sqlite', - ]; - - $driver = $driverAliasMap[$params['scheme']] ?? $params['scheme']; - - // Doctrine DBAL supports passing its internal pdo_* driver names directly too (allowing both dashes and underscores). This allows supporting the same here. - if (str_starts_with($driver, 'pdo_') || str_starts_with($driver, 'pdo-')) { - $driver = substr($driver, 4); - } - - $dsn = null; - switch ($driver) { - case 'mysql': - $dsn = 'mysql:'; - if ('' !== ($params['query'] ?? '')) { - $queryParams = []; - parse_str($params['query'], $queryParams); - if ('' !== ($queryParams['charset'] ?? '')) { - $dsn .= 'charset='.$queryParams['charset'].';'; - } - - if ('' !== ($queryParams['unix_socket'] ?? '')) { - $dsn .= 'unix_socket='.$queryParams['unix_socket'].';'; - - if (isset($params['path'])) { - $dbName = substr($params['path'], 1); // Remove the leading slash - $dsn .= 'dbname='.$dbName.';'; - } - - return $dsn; - } - } - // If "unix_socket" is not in the query, we continue with the same process as pgsql - // no break - case 'pgsql': - $dsn ?? $dsn = 'pgsql:'; - - if (isset($params['host']) && '' !== $params['host']) { - $dsn .= 'host='.$params['host'].';'; - } - - if (isset($params['port']) && '' !== $params['port']) { - $dsn .= 'port='.$params['port'].';'; - } - - if (isset($params['path'])) { - $dbName = substr($params['path'], 1); // Remove the leading slash - $dsn .= 'dbname='.$dbName.';'; - } - - return $dsn; - - case 'sqlite': - return 'sqlite:'.substr($params['path'], 1); - - case 'sqlsrv': - $dsn = 'sqlsrv:server='; - - if (isset($params['host'])) { - $dsn .= $params['host']; - } - - if (isset($params['port']) && '' !== $params['port']) { - $dsn .= ','.$params['port']; - } - - if (isset($params['path'])) { - $dbName = substr($params['path'], 1); // Remove the leading slash - $dsn .= ';Database='.$dbName; - } - - return $dsn; - - default: - throw new \InvalidArgumentException(sprintf('The scheme "%s" is not supported by the PdoSessionHandler URL configuration. Pass a PDO DSN directly.', $params['scheme'])); - } - } - - /** - * Helper method to begin a transaction. - * - * Since SQLite does not support row level locks, we have to acquire a reserved lock - * on the database immediately. Because of https://bugs.php.net/42766 we have to create - * such a transaction manually which also means we cannot use PDO::commit or - * PDO::rollback or PDO::inTransaction for SQLite. - * - * Also MySQLs default isolation, REPEATABLE READ, causes deadlock for different sessions - * due to https://percona.com/blog/2013/12/12/one-more-innodb-gap-lock-to-avoid/ . - * So we change it to READ COMMITTED. - */ - private function beginTransaction(): void - { - if (!$this->inTransaction) { - if ('sqlite' === $this->driver) { - $this->pdo->exec('BEGIN IMMEDIATE TRANSACTION'); - } else { - if ('mysql' === $this->driver) { - $this->pdo->exec('SET TRANSACTION ISOLATION LEVEL READ COMMITTED'); - } - $this->pdo->beginTransaction(); - } - $this->inTransaction = true; - } - } - - /** - * Helper method to commit a transaction. - */ - private function commit(): void - { - if ($this->inTransaction) { - try { - // commit read-write transaction which also releases the lock - if ('sqlite' === $this->driver) { - $this->pdo->exec('COMMIT'); - } else { - $this->pdo->commit(); - } - $this->inTransaction = false; - } catch (\PDOException $e) { - $this->rollback(); - - throw $e; - } - } - } - - /** - * Helper method to rollback a transaction. - */ - private function rollback(): void - { - // We only need to rollback if we are in a transaction. Otherwise the resulting - // error would hide the real problem why rollback was called. We might not be - // in a transaction when not using the transactional locking behavior or when - // two callbacks (e.g. destroy and write) are invoked that both fail. - if ($this->inTransaction) { - if ('sqlite' === $this->driver) { - $this->pdo->exec('ROLLBACK'); - } else { - $this->pdo->rollBack(); - } - $this->inTransaction = false; - } - } - - /** - * Reads the session data in respect to the different locking strategies. - * - * We need to make sure we do not return session data that is already considered garbage according - * to the session.gc_maxlifetime setting because gc() is called after read() and only sometimes. - * - * @return string - */ - protected function doRead(string $sessionId) - { - if (self::LOCK_ADVISORY === $this->lockMode) { - $this->unlockStatements[] = $this->doAdvisoryLock($sessionId); - } - - $selectSql = $this->getSelectSql(); - $selectStmt = $this->pdo->prepare($selectSql); - $selectStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); - $insertStmt = null; - - while (true) { - $selectStmt->execute(); - $sessionRows = $selectStmt->fetchAll(\PDO::FETCH_NUM); - - if ($sessionRows) { - $expiry = (int) $sessionRows[0][1]; - if ($expiry <= self::MAX_LIFETIME) { - $expiry += $sessionRows[0][2]; - } - - if ($expiry < time()) { - $this->sessionExpired = true; - - return ''; - } - - return \is_resource($sessionRows[0][0]) ? stream_get_contents($sessionRows[0][0]) : $sessionRows[0][0]; - } - - if (null !== $insertStmt) { - $this->rollback(); - throw new \RuntimeException('Failed to read session: INSERT reported a duplicate id but next SELECT did not return any data.'); - } - - if (!filter_var(\ini_get('session.use_strict_mode'), \FILTER_VALIDATE_BOOLEAN) && self::LOCK_TRANSACTIONAL === $this->lockMode && 'sqlite' !== $this->driver) { - // In strict mode, session fixation is not possible: new sessions always start with a unique - // random id, so that concurrency is not possible and this code path can be skipped. - // Exclusive-reading of non-existent rows does not block, so we need to do an insert to block - // until other connections to the session are committed. - try { - $insertStmt = $this->getInsertStatement($sessionId, '', 0); - $insertStmt->execute(); - } catch (\PDOException $e) { - // Catch duplicate key error because other connection created the session already. - // It would only not be the case when the other connection destroyed the session. - if (str_starts_with($e->getCode(), '23')) { - // Retrieve finished session data written by concurrent connection by restarting the loop. - // We have to start a new transaction as a failed query will mark the current transaction as - // aborted in PostgreSQL and disallow further queries within it. - $this->rollback(); - $this->beginTransaction(); - continue; - } - - throw $e; - } - } - - return ''; - } - } - - /** - * Executes an application-level lock on the database. - * - * @return \PDOStatement The statement that needs to be executed later to release the lock - * - * @throws \DomainException When an unsupported PDO driver is used - * - * @todo implement missing advisory locks - * - for oci using DBMS_LOCK.REQUEST - * - for sqlsrv using sp_getapplock with LockOwner = Session - */ - private function doAdvisoryLock(string $sessionId): \PDOStatement - { - switch ($this->driver) { - case 'mysql': - // MySQL 5.7.5 and later enforces a maximum length on lock names of 64 characters. Previously, no limit was enforced. - $lockId = substr($sessionId, 0, 64); - // should we handle the return value? 0 on timeout, null on error - // we use a timeout of 50 seconds which is also the default for innodb_lock_wait_timeout - $stmt = $this->pdo->prepare('SELECT GET_LOCK(:key, 50)'); - $stmt->bindValue(':key', $lockId, \PDO::PARAM_STR); - $stmt->execute(); - - $releaseStmt = $this->pdo->prepare('DO RELEASE_LOCK(:key)'); - $releaseStmt->bindValue(':key', $lockId, \PDO::PARAM_STR); - - return $releaseStmt; - case 'pgsql': - // Obtaining an exclusive session level advisory lock requires an integer key. - // When session.sid_bits_per_character > 4, the session id can contain non-hex-characters. - // So we cannot just use hexdec(). - if (4 === \PHP_INT_SIZE) { - $sessionInt1 = $this->convertStringToInt($sessionId); - $sessionInt2 = $this->convertStringToInt(substr($sessionId, 4, 4)); - - $stmt = $this->pdo->prepare('SELECT pg_advisory_lock(:key1, :key2)'); - $stmt->bindValue(':key1', $sessionInt1, \PDO::PARAM_INT); - $stmt->bindValue(':key2', $sessionInt2, \PDO::PARAM_INT); - $stmt->execute(); - - $releaseStmt = $this->pdo->prepare('SELECT pg_advisory_unlock(:key1, :key2)'); - $releaseStmt->bindValue(':key1', $sessionInt1, \PDO::PARAM_INT); - $releaseStmt->bindValue(':key2', $sessionInt2, \PDO::PARAM_INT); - } else { - $sessionBigInt = $this->convertStringToInt($sessionId); - - $stmt = $this->pdo->prepare('SELECT pg_advisory_lock(:key)'); - $stmt->bindValue(':key', $sessionBigInt, \PDO::PARAM_INT); - $stmt->execute(); - - $releaseStmt = $this->pdo->prepare('SELECT pg_advisory_unlock(:key)'); - $releaseStmt->bindValue(':key', $sessionBigInt, \PDO::PARAM_INT); - } - - return $releaseStmt; - case 'sqlite': - throw new \DomainException('SQLite does not support advisory locks.'); - default: - throw new \DomainException(sprintf('Advisory locks are currently not implemented for PDO driver "%s".', $this->driver)); - } - } - - /** - * Encodes the first 4 (when PHP_INT_SIZE == 4) or 8 characters of the string as an integer. - * - * Keep in mind, PHP integers are signed. - */ - private function convertStringToInt(string $string): int - { - if (4 === \PHP_INT_SIZE) { - return (\ord($string[3]) << 24) + (\ord($string[2]) << 16) + (\ord($string[1]) << 8) + \ord($string[0]); - } - - $int1 = (\ord($string[7]) << 24) + (\ord($string[6]) << 16) + (\ord($string[5]) << 8) + \ord($string[4]); - $int2 = (\ord($string[3]) << 24) + (\ord($string[2]) << 16) + (\ord($string[1]) << 8) + \ord($string[0]); - - return $int2 + ($int1 << 32); - } - - /** - * Return a locking or nonlocking SQL query to read session information. - * - * @throws \DomainException When an unsupported PDO driver is used - */ - private function getSelectSql(): string - { - if (self::LOCK_TRANSACTIONAL === $this->lockMode) { - $this->beginTransaction(); - - // selecting the time column should be removed in 6.0 - switch ($this->driver) { - case 'mysql': - case 'oci': - case 'pgsql': - return "SELECT $this->dataCol, $this->lifetimeCol, $this->timeCol FROM $this->table WHERE $this->idCol = :id FOR UPDATE"; - case 'sqlsrv': - return "SELECT $this->dataCol, $this->lifetimeCol, $this->timeCol FROM $this->table WITH (UPDLOCK, ROWLOCK) WHERE $this->idCol = :id"; - case 'sqlite': - // we already locked when starting transaction - break; - default: - throw new \DomainException(sprintf('Transactional locks are currently not implemented for PDO driver "%s".', $this->driver)); - } - } - - return "SELECT $this->dataCol, $this->lifetimeCol, $this->timeCol FROM $this->table WHERE $this->idCol = :id"; - } - - /** - * Returns an insert statement supported by the database for writing session data. - */ - private function getInsertStatement(string $sessionId, string $sessionData, int $maxlifetime): \PDOStatement - { - switch ($this->driver) { - case 'oci': - $data = fopen('php://memory', 'r+'); - fwrite($data, $sessionData); - rewind($data); - $sql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, EMPTY_BLOB(), :expiry, :time) RETURNING $this->dataCol into :data"; - break; - default: - $data = $sessionData; - $sql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :expiry, :time)"; - break; - } - - $stmt = $this->pdo->prepare($sql); - $stmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); - $stmt->bindParam(':data', $data, \PDO::PARAM_LOB); - $stmt->bindValue(':expiry', time() + $maxlifetime, \PDO::PARAM_INT); - $stmt->bindValue(':time', time(), \PDO::PARAM_INT); - - return $stmt; - } - - /** - * Returns an update statement supported by the database for writing session data. - */ - private function getUpdateStatement(string $sessionId, string $sessionData, int $maxlifetime): \PDOStatement - { - switch ($this->driver) { - case 'oci': - $data = fopen('php://memory', 'r+'); - fwrite($data, $sessionData); - rewind($data); - $sql = "UPDATE $this->table SET $this->dataCol = EMPTY_BLOB(), $this->lifetimeCol = :expiry, $this->timeCol = :time WHERE $this->idCol = :id RETURNING $this->dataCol into :data"; - break; - default: - $data = $sessionData; - $sql = "UPDATE $this->table SET $this->dataCol = :data, $this->lifetimeCol = :expiry, $this->timeCol = :time WHERE $this->idCol = :id"; - break; - } - - $stmt = $this->pdo->prepare($sql); - $stmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); - $stmt->bindParam(':data', $data, \PDO::PARAM_LOB); - $stmt->bindValue(':expiry', time() + $maxlifetime, \PDO::PARAM_INT); - $stmt->bindValue(':time', time(), \PDO::PARAM_INT); - - return $stmt; - } - - /** - * Returns a merge/upsert (i.e. insert or update) statement when supported by the database for writing session data. - */ - private function getMergeStatement(string $sessionId, string $data, int $maxlifetime): ?\PDOStatement - { - switch (true) { - case 'mysql' === $this->driver: - $mergeSql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :expiry, :time) ". - "ON DUPLICATE KEY UPDATE $this->dataCol = VALUES($this->dataCol), $this->lifetimeCol = VALUES($this->lifetimeCol), $this->timeCol = VALUES($this->timeCol)"; - break; - case 'sqlsrv' === $this->driver && version_compare($this->pdo->getAttribute(\PDO::ATTR_SERVER_VERSION), '10', '>='): - // MERGE is only available since SQL Server 2008 and must be terminated by semicolon - // It also requires HOLDLOCK according to https://weblogs.sqlteam.com/dang/2009/01/31/upsert-race-condition-with-merge/ - $mergeSql = "MERGE INTO $this->table WITH (HOLDLOCK) USING (SELECT 1 AS dummy) AS src ON ($this->idCol = ?) ". - "WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (?, ?, ?, ?) ". - "WHEN MATCHED THEN UPDATE SET $this->dataCol = ?, $this->lifetimeCol = ?, $this->timeCol = ?;"; - break; - case 'sqlite' === $this->driver: - $mergeSql = "INSERT OR REPLACE INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :expiry, :time)"; - break; - case 'pgsql' === $this->driver && version_compare($this->pdo->getAttribute(\PDO::ATTR_SERVER_VERSION), '9.5', '>='): - $mergeSql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :expiry, :time) ". - "ON CONFLICT ($this->idCol) DO UPDATE SET ($this->dataCol, $this->lifetimeCol, $this->timeCol) = (EXCLUDED.$this->dataCol, EXCLUDED.$this->lifetimeCol, EXCLUDED.$this->timeCol)"; - break; - default: - // MERGE is not supported with LOBs: https://oracle.com/technetwork/articles/fuecks-lobs-095315.html - return null; - } - - $mergeStmt = $this->pdo->prepare($mergeSql); - - if ('sqlsrv' === $this->driver) { - $mergeStmt->bindParam(1, $sessionId, \PDO::PARAM_STR); - $mergeStmt->bindParam(2, $sessionId, \PDO::PARAM_STR); - $mergeStmt->bindParam(3, $data, \PDO::PARAM_LOB); - $mergeStmt->bindValue(4, time() + $maxlifetime, \PDO::PARAM_INT); - $mergeStmt->bindValue(5, time(), \PDO::PARAM_INT); - $mergeStmt->bindParam(6, $data, \PDO::PARAM_LOB); - $mergeStmt->bindValue(7, time() + $maxlifetime, \PDO::PARAM_INT); - $mergeStmt->bindValue(8, time(), \PDO::PARAM_INT); - } else { - $mergeStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); - $mergeStmt->bindParam(':data', $data, \PDO::PARAM_LOB); - $mergeStmt->bindValue(':expiry', time() + $maxlifetime, \PDO::PARAM_INT); - $mergeStmt->bindValue(':time', time(), \PDO::PARAM_INT); - } - - return $mergeStmt; - } - - /** - * Return a PDO instance. - * - * @return \PDO - */ - protected function getConnection() - { - if (null === $this->pdo) { - $this->connect($this->dsn ?: \ini_get('session.save_path')); - } - - return $this->pdo; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php b/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php deleted file mode 100644 index 31954e6..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php +++ /dev/null @@ -1,137 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -use Predis\Response\ErrorInterface; -use Symfony\Component\Cache\Traits\RedisClusterProxy; -use Symfony\Component\Cache\Traits\RedisProxy; - -/** - * Redis based session storage handler based on the Redis class - * provided by the PHP redis extension. - * - * @author Dalibor Karlović - */ -class RedisSessionHandler extends AbstractSessionHandler -{ - private $redis; - - /** - * @var string Key prefix for shared environments - */ - private $prefix; - - /** - * @var int Time to live in seconds - */ - private $ttl; - - /** - * List of available options: - * * prefix: The prefix to use for the keys in order to avoid collision on the Redis server - * * ttl: The time to live in seconds. - * - * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy|RedisClusterProxy $redis - * - * @throws \InvalidArgumentException When unsupported client or options are passed - */ - public function __construct($redis, array $options = []) - { - if ( - !$redis instanceof \Redis && - !$redis instanceof \RedisArray && - !$redis instanceof \RedisCluster && - !$redis instanceof \Predis\ClientInterface && - !$redis instanceof RedisProxy && - !$redis instanceof RedisClusterProxy - ) { - throw new \InvalidArgumentException(sprintf('"%s()" expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\ClientInterface, "%s" given.', __METHOD__, get_debug_type($redis))); - } - - if ($diff = array_diff(array_keys($options), ['prefix', 'ttl'])) { - throw new \InvalidArgumentException(sprintf('The following options are not supported "%s".', implode(', ', $diff))); - } - - $this->redis = $redis; - $this->prefix = $options['prefix'] ?? 'sf_s'; - $this->ttl = $options['ttl'] ?? null; - } - - /** - * {@inheritdoc} - */ - protected function doRead(string $sessionId): string - { - return $this->redis->get($this->prefix.$sessionId) ?: ''; - } - - /** - * {@inheritdoc} - */ - protected function doWrite(string $sessionId, string $data): bool - { - $result = $this->redis->setEx($this->prefix.$sessionId, (int) ($this->ttl ?? \ini_get('session.gc_maxlifetime')), $data); - - return $result && !$result instanceof ErrorInterface; - } - - /** - * {@inheritdoc} - */ - protected function doDestroy(string $sessionId): bool - { - static $unlink = true; - - if ($unlink) { - try { - $unlink = false !== $this->redis->unlink($this->prefix.$sessionId); - } catch (\Throwable $e) { - $unlink = false; - } - } - - if (!$unlink) { - $this->redis->del($this->prefix.$sessionId); - } - - return true; - } - - /** - * {@inheritdoc} - */ - #[\ReturnTypeWillChange] - public function close(): bool - { - return true; - } - - /** - * {@inheritdoc} - * - * @return int|false - */ - #[\ReturnTypeWillChange] - public function gc($maxlifetime) - { - return 0; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function updateTimestamp($sessionId, $data) - { - return (bool) $this->redis->expire($this->prefix.$sessionId, (int) ($this->ttl ?? \ini_get('session.gc_maxlifetime'))); - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php b/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php deleted file mode 100644 index 76e4373..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php +++ /dev/null @@ -1,103 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -use Doctrine\DBAL\Configuration; -use Doctrine\DBAL\DriverManager; -use Doctrine\DBAL\Schema\DefaultSchemaManagerFactory; -use Doctrine\DBAL\Tools\DsnParser; -use Symfony\Component\Cache\Adapter\AbstractAdapter; -use Symfony\Component\Cache\Traits\RedisClusterProxy; -use Symfony\Component\Cache\Traits\RedisProxy; - -/** - * @author Nicolas Grekas - */ -class SessionHandlerFactory -{ - /** - * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy|RedisClusterProxy|\Memcached|\PDO|string $connection Connection or DSN - */ - public static function createHandler($connection): AbstractSessionHandler - { - if (!\is_string($connection) && !\is_object($connection)) { - throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be a string or a connection object, "%s" given.', __METHOD__, get_debug_type($connection))); - } - - if ($options = \is_string($connection) ? parse_url($connection) : false) { - parse_str($options['query'] ?? '', $options); - } - - switch (true) { - case $connection instanceof \Redis: - case $connection instanceof \RedisArray: - case $connection instanceof \RedisCluster: - case $connection instanceof \Predis\ClientInterface: - case $connection instanceof RedisProxy: - case $connection instanceof RedisClusterProxy: - return new RedisSessionHandler($connection); - - case $connection instanceof \Memcached: - return new MemcachedSessionHandler($connection); - - case $connection instanceof \PDO: - return new PdoSessionHandler($connection); - - case !\is_string($connection): - throw new \InvalidArgumentException(sprintf('Unsupported Connection: "%s".', get_debug_type($connection))); - case str_starts_with($connection, 'file://'): - $savePath = substr($connection, 7); - - return new StrictSessionHandler(new NativeFileSessionHandler('' === $savePath ? null : $savePath)); - - case str_starts_with($connection, 'redis:'): - case str_starts_with($connection, 'rediss:'): - case str_starts_with($connection, 'memcached:'): - if (!class_exists(AbstractAdapter::class)) { - throw new \InvalidArgumentException('Unsupported Redis or Memcached DSN. Try running "composer require symfony/cache".'); - } - $handlerClass = str_starts_with($connection, 'memcached:') ? MemcachedSessionHandler::class : RedisSessionHandler::class; - $connection = AbstractAdapter::createConnection($connection, ['lazy' => true]); - - return new $handlerClass($connection, array_intersect_key($options ?: [], ['prefix' => 1, 'ttl' => 1])); - - case str_starts_with($connection, 'pdo_oci://'): - if (!class_exists(DriverManager::class)) { - throw new \InvalidArgumentException('Unsupported PDO OCI DSN. Try running "composer require doctrine/dbal".'); - } - $connection[3] = '-'; - $params = class_exists(DsnParser::class) ? (new DsnParser())->parse($connection) : ['url' => $connection]; - $config = new Configuration(); - if (class_exists(DefaultSchemaManagerFactory::class)) { - $config->setSchemaManagerFactory(new DefaultSchemaManagerFactory()); - } - - $connection = DriverManager::getConnection($params, $config); - // The condition should be removed once support for DBAL <3.3 is dropped - $connection = method_exists($connection, 'getNativeConnection') ? $connection->getNativeConnection() : $connection->getWrappedConnection(); - // no break; - - case str_starts_with($connection, 'mssql://'): - case str_starts_with($connection, 'mysql://'): - case str_starts_with($connection, 'mysql2://'): - case str_starts_with($connection, 'pgsql://'): - case str_starts_with($connection, 'postgres://'): - case str_starts_with($connection, 'postgresql://'): - case str_starts_with($connection, 'sqlsrv://'): - case str_starts_with($connection, 'sqlite://'): - case str_starts_with($connection, 'sqlite3://'): - return new PdoSessionHandler($connection, $options ?: []); - } - - throw new \InvalidArgumentException(sprintf('Unsupported Connection: "%s".', $connection)); - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php b/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php deleted file mode 100644 index f7c385f..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php +++ /dev/null @@ -1,118 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -/** - * Adds basic `SessionUpdateTimestampHandlerInterface` behaviors to another `SessionHandlerInterface`. - * - * @author Nicolas Grekas - */ -class StrictSessionHandler extends AbstractSessionHandler -{ - private $handler; - private $doDestroy; - - public function __construct(\SessionHandlerInterface $handler) - { - if ($handler instanceof \SessionUpdateTimestampHandlerInterface) { - throw new \LogicException(sprintf('"%s" is already an instance of "SessionUpdateTimestampHandlerInterface", you cannot wrap it with "%s".', get_debug_type($handler), self::class)); - } - - $this->handler = $handler; - } - - /** - * Returns true if this handler wraps an internal PHP session save handler using \SessionHandler. - * - * @internal - */ - public function isWrapper(): bool - { - return $this->handler instanceof \SessionHandler; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function open($savePath, $sessionName) - { - parent::open($savePath, $sessionName); - - return $this->handler->open($savePath, $sessionName); - } - - /** - * {@inheritdoc} - */ - protected function doRead(string $sessionId) - { - return $this->handler->read($sessionId); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function updateTimestamp($sessionId, $data) - { - return $this->write($sessionId, $data); - } - - /** - * {@inheritdoc} - */ - protected function doWrite(string $sessionId, string $data) - { - return $this->handler->write($sessionId, $data); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function destroy($sessionId) - { - $this->doDestroy = true; - $destroyed = parent::destroy($sessionId); - - return $this->doDestroy ? $this->doDestroy($sessionId) : $destroyed; - } - - /** - * {@inheritdoc} - */ - protected function doDestroy(string $sessionId) - { - $this->doDestroy = false; - - return $this->handler->destroy($sessionId); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function close() - { - return $this->handler->close(); - } - - /** - * @return int|false - */ - #[\ReturnTypeWillChange] - public function gc($maxlifetime) - { - return $this->handler->gc($maxlifetime); - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/MetadataBag.php b/digital_doctor/vendor/symfony/http-foundation/Session/Storage/MetadataBag.php deleted file mode 100644 index 3e10f6d..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/MetadataBag.php +++ /dev/null @@ -1,167 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Session\SessionBagInterface; - -/** - * Metadata container. - * - * Adds metadata to the session. - * - * @author Drak - */ -class MetadataBag implements SessionBagInterface -{ - public const CREATED = 'c'; - public const UPDATED = 'u'; - public const LIFETIME = 'l'; - - /** - * @var string - */ - private $name = '__metadata'; - - /** - * @var string - */ - private $storageKey; - - /** - * @var array - */ - protected $meta = [self::CREATED => 0, self::UPDATED => 0, self::LIFETIME => 0]; - - /** - * Unix timestamp. - * - * @var int - */ - private $lastUsed; - - /** - * @var int - */ - private $updateThreshold; - - /** - * @param string $storageKey The key used to store bag in the session - * @param int $updateThreshold The time to wait between two UPDATED updates - */ - public function __construct(string $storageKey = '_sf2_meta', int $updateThreshold = 0) - { - $this->storageKey = $storageKey; - $this->updateThreshold = $updateThreshold; - } - - /** - * {@inheritdoc} - */ - public function initialize(array &$array) - { - $this->meta = &$array; - - if (isset($array[self::CREATED])) { - $this->lastUsed = $this->meta[self::UPDATED]; - - $timeStamp = time(); - if ($timeStamp - $array[self::UPDATED] >= $this->updateThreshold) { - $this->meta[self::UPDATED] = $timeStamp; - } - } else { - $this->stampCreated(); - } - } - - /** - * Gets the lifetime that the session cookie was set with. - * - * @return int - */ - public function getLifetime() - { - return $this->meta[self::LIFETIME]; - } - - /** - * Stamps a new session's metadata. - * - * @param int|null $lifetime Sets the cookie lifetime for the session cookie. A null value - * will leave the system settings unchanged, 0 sets the cookie - * to expire with browser session. Time is in seconds, and is - * not a Unix timestamp. - */ - public function stampNew(?int $lifetime = null) - { - $this->stampCreated($lifetime); - } - - /** - * {@inheritdoc} - */ - public function getStorageKey() - { - return $this->storageKey; - } - - /** - * Gets the created timestamp metadata. - * - * @return int Unix timestamp - */ - public function getCreated() - { - return $this->meta[self::CREATED]; - } - - /** - * Gets the last used metadata. - * - * @return int Unix timestamp - */ - public function getLastUsed() - { - return $this->lastUsed; - } - - /** - * {@inheritdoc} - */ - public function clear() - { - // nothing to do - return null; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return $this->name; - } - - /** - * Sets name. - */ - public function setName(string $name) - { - $this->name = $name; - } - - private function stampCreated(?int $lifetime = null): void - { - $timeStamp = time(); - $this->meta[self::CREATED] = $this->meta[self::UPDATED] = $this->lastUsed = $timeStamp; - $this->meta[self::LIFETIME] = $lifetime ?? (int) \ini_get('session.cookie_lifetime'); - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php b/digital_doctor/vendor/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php deleted file mode 100644 index 77bb38f..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php +++ /dev/null @@ -1,252 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Session\SessionBagInterface; - -/** - * MockArraySessionStorage mocks the session for unit tests. - * - * No PHP session is actually started since a session can be initialized - * and shutdown only once per PHP execution cycle. - * - * When doing functional testing, you should use MockFileSessionStorage instead. - * - * @author Fabien Potencier - * @author Bulat Shakirzyanov - * @author Drak - */ -class MockArraySessionStorage implements SessionStorageInterface -{ - /** - * @var string - */ - protected $id = ''; - - /** - * @var string - */ - protected $name; - - /** - * @var bool - */ - protected $started = false; - - /** - * @var bool - */ - protected $closed = false; - - /** - * @var array - */ - protected $data = []; - - /** - * @var MetadataBag - */ - protected $metadataBag; - - /** - * @var array|SessionBagInterface[] - */ - protected $bags = []; - - public function __construct(string $name = 'MOCKSESSID', ?MetadataBag $metaBag = null) - { - $this->name = $name; - $this->setMetadataBag($metaBag); - } - - public function setSessionData(array $array) - { - $this->data = $array; - } - - /** - * {@inheritdoc} - */ - public function start() - { - if ($this->started) { - return true; - } - - if (empty($this->id)) { - $this->id = $this->generateId(); - } - - $this->loadSession(); - - return true; - } - - /** - * {@inheritdoc} - */ - public function regenerate(bool $destroy = false, ?int $lifetime = null) - { - if (!$this->started) { - $this->start(); - } - - $this->metadataBag->stampNew($lifetime); - $this->id = $this->generateId(); - - return true; - } - - /** - * {@inheritdoc} - */ - public function getId() - { - return $this->id; - } - - /** - * {@inheritdoc} - */ - public function setId(string $id) - { - if ($this->started) { - throw new \LogicException('Cannot set session ID after the session has started.'); - } - - $this->id = $id; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return $this->name; - } - - /** - * {@inheritdoc} - */ - public function setName(string $name) - { - $this->name = $name; - } - - /** - * {@inheritdoc} - */ - public function save() - { - if (!$this->started || $this->closed) { - throw new \RuntimeException('Trying to save a session that was not started yet or was already closed.'); - } - // nothing to do since we don't persist the session data - $this->closed = false; - $this->started = false; - } - - /** - * {@inheritdoc} - */ - public function clear() - { - // clear out the bags - foreach ($this->bags as $bag) { - $bag->clear(); - } - - // clear out the session - $this->data = []; - - // reconnect the bags to the session - $this->loadSession(); - } - - /** - * {@inheritdoc} - */ - public function registerBag(SessionBagInterface $bag) - { - $this->bags[$bag->getName()] = $bag; - } - - /** - * {@inheritdoc} - */ - public function getBag(string $name) - { - if (!isset($this->bags[$name])) { - throw new \InvalidArgumentException(sprintf('The SessionBagInterface "%s" is not registered.', $name)); - } - - if (!$this->started) { - $this->start(); - } - - return $this->bags[$name]; - } - - /** - * {@inheritdoc} - */ - public function isStarted() - { - return $this->started; - } - - public function setMetadataBag(?MetadataBag $bag = null) - { - if (null === $bag) { - $bag = new MetadataBag(); - } - - $this->metadataBag = $bag; - } - - /** - * Gets the MetadataBag. - * - * @return MetadataBag - */ - public function getMetadataBag() - { - return $this->metadataBag; - } - - /** - * Generates a session ID. - * - * This doesn't need to be particularly cryptographically secure since this is just - * a mock. - * - * @return string - */ - protected function generateId() - { - return hash('sha256', uniqid('ss_mock_', true)); - } - - protected function loadSession() - { - $bags = array_merge($this->bags, [$this->metadataBag]); - - foreach ($bags as $bag) { - $key = $bag->getStorageKey(); - $this->data[$key] = $this->data[$key] ?? []; - $bag->initialize($this->data[$key]); - } - - $this->started = true; - $this->closed = false; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php b/digital_doctor/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php deleted file mode 100644 index 8aeb972..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php +++ /dev/null @@ -1,160 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -/** - * MockFileSessionStorage is used to mock sessions for - * functional testing where you may need to persist session data - * across separate PHP processes. - * - * No PHP session is actually started since a session can be initialized - * and shutdown only once per PHP execution cycle and this class does - * not pollute any session related globals, including session_*() functions - * or session.* PHP ini directives. - * - * @author Drak - */ -class MockFileSessionStorage extends MockArraySessionStorage -{ - private $savePath; - - /** - * @param string|null $savePath Path of directory to save session files - */ - public function __construct(?string $savePath = null, string $name = 'MOCKSESSID', ?MetadataBag $metaBag = null) - { - if (null === $savePath) { - $savePath = sys_get_temp_dir(); - } - - if (!is_dir($savePath) && !@mkdir($savePath, 0777, true) && !is_dir($savePath)) { - throw new \RuntimeException(sprintf('Session Storage was not able to create directory "%s".', $savePath)); - } - - $this->savePath = $savePath; - - parent::__construct($name, $metaBag); - } - - /** - * {@inheritdoc} - */ - public function start() - { - if ($this->started) { - return true; - } - - if (!$this->id) { - $this->id = $this->generateId(); - } - - $this->read(); - - $this->started = true; - - return true; - } - - /** - * {@inheritdoc} - */ - public function regenerate(bool $destroy = false, ?int $lifetime = null) - { - if (!$this->started) { - $this->start(); - } - - if ($destroy) { - $this->destroy(); - } - - return parent::regenerate($destroy, $lifetime); - } - - /** - * {@inheritdoc} - */ - public function save() - { - if (!$this->started) { - throw new \RuntimeException('Trying to save a session that was not started yet or was already closed.'); - } - - $data = $this->data; - - foreach ($this->bags as $bag) { - if (empty($data[$key = $bag->getStorageKey()])) { - unset($data[$key]); - } - } - if ([$key = $this->metadataBag->getStorageKey()] === array_keys($data)) { - unset($data[$key]); - } - - try { - if ($data) { - $path = $this->getFilePath(); - $tmp = $path.bin2hex(random_bytes(6)); - file_put_contents($tmp, serialize($data)); - rename($tmp, $path); - } else { - $this->destroy(); - } - } finally { - $this->data = $data; - } - - // this is needed when the session object is re-used across multiple requests - // in functional tests. - $this->started = false; - } - - /** - * Deletes a session from persistent storage. - * Deliberately leaves session data in memory intact. - */ - private function destroy(): void - { - set_error_handler(static function () {}); - try { - unlink($this->getFilePath()); - } finally { - restore_error_handler(); - } - } - - /** - * Calculate path to file. - */ - private function getFilePath(): string - { - return $this->savePath.'/'.$this->id.'.mocksess'; - } - - /** - * Reads session from storage and loads session. - */ - private function read(): void - { - set_error_handler(static function () {}); - try { - $data = file_get_contents($this->getFilePath()); - } finally { - restore_error_handler(); - } - - $this->data = $data ? unserialize($data) : []; - - $this->loadSession(); - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.php b/digital_doctor/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.php deleted file mode 100644 index 900fa7c..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.php +++ /dev/null @@ -1,42 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Request; - -// Help opcache.preload discover always-needed symbols -class_exists(MockFileSessionStorage::class); - -/** - * @author Jérémy Derussé - */ -class MockFileSessionStorageFactory implements SessionStorageFactoryInterface -{ - private $savePath; - private $name; - private $metaBag; - - /** - * @see MockFileSessionStorage constructor. - */ - public function __construct(?string $savePath = null, string $name = 'MOCKSESSID', ?MetadataBag $metaBag = null) - { - $this->savePath = $savePath; - $this->name = $name; - $this->metaBag = $metaBag; - } - - public function createStorage(?Request $request): SessionStorageInterface - { - return new MockFileSessionStorage($this->savePath, $this->name, $this->metaBag); - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php b/digital_doctor/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php deleted file mode 100644 index e7b42ed..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php +++ /dev/null @@ -1,507 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Session\SessionBagInterface; -use Symfony\Component\HttpFoundation\Session\SessionUtils; -use Symfony\Component\HttpFoundation\Session\Storage\Handler\StrictSessionHandler; -use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; -use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy; - -// Help opcache.preload discover always-needed symbols -class_exists(MetadataBag::class); -class_exists(StrictSessionHandler::class); -class_exists(SessionHandlerProxy::class); - -/** - * This provides a base class for session attribute storage. - * - * @author Drak - */ -class NativeSessionStorage implements SessionStorageInterface -{ - /** - * @var SessionBagInterface[] - */ - protected $bags = []; - - /** - * @var bool - */ - protected $started = false; - - /** - * @var bool - */ - protected $closed = false; - - /** - * @var AbstractProxy|\SessionHandlerInterface - */ - protected $saveHandler; - - /** - * @var MetadataBag - */ - protected $metadataBag; - - /** - * @var string|null - */ - private $emulateSameSite; - - /** - * Depending on how you want the storage driver to behave you probably - * want to override this constructor entirely. - * - * List of options for $options array with their defaults. - * - * @see https://php.net/session.configuration for options - * but we omit 'session.' from the beginning of the keys for convenience. - * - * ("auto_start", is not supported as it tells PHP to start a session before - * PHP starts to execute user-land code. Setting during runtime has no effect). - * - * cache_limiter, "" (use "0" to prevent headers from being sent entirely). - * cache_expire, "0" - * cookie_domain, "" - * cookie_httponly, "" - * cookie_lifetime, "0" - * cookie_path, "/" - * cookie_secure, "" - * cookie_samesite, null - * gc_divisor, "100" - * gc_maxlifetime, "1440" - * gc_probability, "1" - * lazy_write, "1" - * name, "PHPSESSID" - * referer_check, "" - * serialize_handler, "php" - * use_strict_mode, "1" - * use_cookies, "1" - * use_only_cookies, "1" - * use_trans_sid, "0" - * sid_length, "32" - * sid_bits_per_character, "5" - * trans_sid_hosts, $_SERVER['HTTP_HOST'] - * trans_sid_tags, "a=href,area=href,frame=src,form=" - * - * @param AbstractProxy|\SessionHandlerInterface|null $handler - */ - public function __construct(array $options = [], $handler = null, ?MetadataBag $metaBag = null) - { - if (!\extension_loaded('session')) { - throw new \LogicException('PHP extension "session" is required.'); - } - - $options += [ - 'cache_limiter' => '', - 'cache_expire' => 0, - 'use_cookies' => 1, - 'lazy_write' => 1, - 'use_strict_mode' => 1, - ]; - - session_register_shutdown(); - - $this->setMetadataBag($metaBag); - $this->setOptions($options); - $this->setSaveHandler($handler); - } - - /** - * Gets the save handler instance. - * - * @return AbstractProxy|\SessionHandlerInterface - */ - public function getSaveHandler() - { - return $this->saveHandler; - } - - /** - * {@inheritdoc} - */ - public function start() - { - if ($this->started) { - return true; - } - - if (\PHP_SESSION_ACTIVE === session_status()) { - throw new \RuntimeException('Failed to start the session: already started by PHP.'); - } - - if (filter_var(\ini_get('session.use_cookies'), \FILTER_VALIDATE_BOOLEAN) && headers_sent($file, $line)) { - throw new \RuntimeException(sprintf('Failed to start the session because headers have already been sent by "%s" at line %d.', $file, $line)); - } - - $sessionId = $_COOKIE[session_name()] ?? null; - /* - * Explanation of the session ID regular expression: `/^[a-zA-Z0-9,-]{22,250}$/`. - * - * ---------- Part 1 - * - * The part `[a-zA-Z0-9,-]` is related to the PHP ini directive `session.sid_bits_per_character` defined as 6. - * See https://www.php.net/manual/en/session.configuration.php#ini.session.sid-bits-per-character. - * Allowed values are integers such as: - * - 4 for range `a-f0-9` - * - 5 for range `a-v0-9` - * - 6 for range `a-zA-Z0-9,-` - * - * ---------- Part 2 - * - * The part `{22,250}` is related to the PHP ini directive `session.sid_length`. - * See https://www.php.net/manual/en/session.configuration.php#ini.session.sid-length. - * Allowed values are integers between 22 and 256, but we use 250 for the max. - * - * Where does the 250 come from? - * - The length of Windows and Linux filenames is limited to 255 bytes. Then the max must not exceed 255. - * - The session filename prefix is `sess_`, a 5 bytes string. Then the max must not exceed 255 - 5 = 250. - * - * ---------- Conclusion - * - * The parts 1 and 2 prevent the warning below: - * `PHP Warning: SessionHandler::read(): Session ID is too long or contains illegal characters. Only the A-Z, a-z, 0-9, "-", and "," characters are allowed.` - * - * The part 2 prevents the warning below: - * `PHP Warning: SessionHandler::read(): open(filepath, O_RDWR) failed: No such file or directory (2).` - */ - if ($sessionId && $this->saveHandler instanceof AbstractProxy && 'files' === $this->saveHandler->getSaveHandlerName() && !preg_match('/^[a-zA-Z0-9,-]{22,250}$/', $sessionId)) { - // the session ID in the header is invalid, create a new one - session_id(session_create_id()); - } - - // ok to try and start the session - if (!session_start()) { - throw new \RuntimeException('Failed to start the session.'); - } - - if (null !== $this->emulateSameSite) { - $originalCookie = SessionUtils::popSessionCookie(session_name(), session_id()); - if (null !== $originalCookie) { - header(sprintf('%s; SameSite=%s', $originalCookie, $this->emulateSameSite), false); - } - } - - $this->loadSession(); - - return true; - } - - /** - * {@inheritdoc} - */ - public function getId() - { - return $this->saveHandler->getId(); - } - - /** - * {@inheritdoc} - */ - public function setId(string $id) - { - $this->saveHandler->setId($id); - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return $this->saveHandler->getName(); - } - - /** - * {@inheritdoc} - */ - public function setName(string $name) - { - $this->saveHandler->setName($name); - } - - /** - * {@inheritdoc} - */ - public function regenerate(bool $destroy = false, ?int $lifetime = null) - { - // Cannot regenerate the session ID for non-active sessions. - if (\PHP_SESSION_ACTIVE !== session_status()) { - return false; - } - - if (headers_sent()) { - return false; - } - - if (null !== $lifetime && $lifetime != \ini_get('session.cookie_lifetime')) { - $this->save(); - ini_set('session.cookie_lifetime', $lifetime); - $this->start(); - } - - if ($destroy) { - $this->metadataBag->stampNew(); - } - - $isRegenerated = session_regenerate_id($destroy); - - if (null !== $this->emulateSameSite) { - $originalCookie = SessionUtils::popSessionCookie(session_name(), session_id()); - if (null !== $originalCookie) { - header(sprintf('%s; SameSite=%s', $originalCookie, $this->emulateSameSite), false); - } - } - - return $isRegenerated; - } - - /** - * {@inheritdoc} - */ - public function save() - { - // Store a copy so we can restore the bags in case the session was not left empty - $session = $_SESSION; - - foreach ($this->bags as $bag) { - if (empty($_SESSION[$key = $bag->getStorageKey()])) { - unset($_SESSION[$key]); - } - } - if ($_SESSION && [$key = $this->metadataBag->getStorageKey()] === array_keys($_SESSION)) { - unset($_SESSION[$key]); - } - - // Register error handler to add information about the current save handler - $previousHandler = set_error_handler(function ($type, $msg, $file, $line) use (&$previousHandler) { - if (\E_WARNING === $type && str_starts_with($msg, 'session_write_close():')) { - $handler = $this->saveHandler instanceof SessionHandlerProxy ? $this->saveHandler->getHandler() : $this->saveHandler; - $msg = sprintf('session_write_close(): Failed to write session data with "%s" handler', \get_class($handler)); - } - - return $previousHandler ? $previousHandler($type, $msg, $file, $line) : false; - }); - - try { - session_write_close(); - } finally { - restore_error_handler(); - - // Restore only if not empty - if ($_SESSION) { - $_SESSION = $session; - } - } - - $this->closed = true; - $this->started = false; - } - - /** - * {@inheritdoc} - */ - public function clear() - { - // clear out the bags - foreach ($this->bags as $bag) { - $bag->clear(); - } - - // clear out the session - $_SESSION = []; - - // reconnect the bags to the session - $this->loadSession(); - } - - /** - * {@inheritdoc} - */ - public function registerBag(SessionBagInterface $bag) - { - if ($this->started) { - throw new \LogicException('Cannot register a bag when the session is already started.'); - } - - $this->bags[$bag->getName()] = $bag; - } - - /** - * {@inheritdoc} - */ - public function getBag(string $name) - { - if (!isset($this->bags[$name])) { - throw new \InvalidArgumentException(sprintf('The SessionBagInterface "%s" is not registered.', $name)); - } - - if (!$this->started && $this->saveHandler->isActive()) { - $this->loadSession(); - } elseif (!$this->started) { - $this->start(); - } - - return $this->bags[$name]; - } - - public function setMetadataBag(?MetadataBag $metaBag = null) - { - if (null === $metaBag) { - $metaBag = new MetadataBag(); - } - - $this->metadataBag = $metaBag; - } - - /** - * Gets the MetadataBag. - * - * @return MetadataBag - */ - public function getMetadataBag() - { - return $this->metadataBag; - } - - /** - * {@inheritdoc} - */ - public function isStarted() - { - return $this->started; - } - - /** - * Sets session.* ini variables. - * - * For convenience we omit 'session.' from the beginning of the keys. - * Explicitly ignores other ini keys. - * - * @param array $options Session ini directives [key => value] - * - * @see https://php.net/session.configuration - */ - public function setOptions(array $options) - { - if (headers_sent() || \PHP_SESSION_ACTIVE === session_status()) { - return; - } - - $validOptions = array_flip([ - 'cache_expire', 'cache_limiter', 'cookie_domain', 'cookie_httponly', - 'cookie_lifetime', 'cookie_path', 'cookie_secure', 'cookie_samesite', - 'gc_divisor', 'gc_maxlifetime', 'gc_probability', - 'lazy_write', 'name', 'referer_check', - 'serialize_handler', 'use_strict_mode', 'use_cookies', - 'use_only_cookies', 'use_trans_sid', 'upload_progress.enabled', - 'upload_progress.cleanup', 'upload_progress.prefix', 'upload_progress.name', - 'upload_progress.freq', 'upload_progress.min_freq', 'url_rewriter.tags', - 'sid_length', 'sid_bits_per_character', 'trans_sid_hosts', 'trans_sid_tags', - ]); - - foreach ($options as $key => $value) { - if (isset($validOptions[$key])) { - if (str_starts_with($key, 'upload_progress.')) { - trigger_deprecation('symfony/http-foundation', '5.4', 'Support for the "%s" session option is deprecated. The settings prefixed with "session.upload_progress." can not be changed at runtime.', $key); - continue; - } - if ('url_rewriter.tags' === $key) { - trigger_deprecation('symfony/http-foundation', '5.4', 'Support for the "%s" session option is deprecated. Use "trans_sid_tags" instead.', $key); - } - if ('cookie_samesite' === $key && \PHP_VERSION_ID < 70300) { - // PHP < 7.3 does not support same_site cookies. We will emulate it in - // the start() method instead. - $this->emulateSameSite = $value; - continue; - } - if ('cookie_secure' === $key && 'auto' === $value) { - continue; - } - ini_set('url_rewriter.tags' !== $key ? 'session.'.$key : $key, $value); - } - } - } - - /** - * Registers session save handler as a PHP session handler. - * - * To use internal PHP session save handlers, override this method using ini_set with - * session.save_handler and session.save_path e.g. - * - * ini_set('session.save_handler', 'files'); - * ini_set('session.save_path', '/tmp'); - * - * or pass in a \SessionHandler instance which configures session.save_handler in the - * constructor, for a template see NativeFileSessionHandler. - * - * @see https://php.net/session-set-save-handler - * @see https://php.net/sessionhandlerinterface - * @see https://php.net/sessionhandler - * - * @param AbstractProxy|\SessionHandlerInterface|null $saveHandler - * - * @throws \InvalidArgumentException - */ - public function setSaveHandler($saveHandler = null) - { - if (!$saveHandler instanceof AbstractProxy - && !$saveHandler instanceof \SessionHandlerInterface - && null !== $saveHandler - ) { - throw new \InvalidArgumentException('Must be instance of AbstractProxy; implement \SessionHandlerInterface; or be null.'); - } - - // Wrap $saveHandler in proxy and prevent double wrapping of proxy - if (!$saveHandler instanceof AbstractProxy && $saveHandler instanceof \SessionHandlerInterface) { - $saveHandler = new SessionHandlerProxy($saveHandler); - } elseif (!$saveHandler instanceof AbstractProxy) { - $saveHandler = new SessionHandlerProxy(new StrictSessionHandler(new \SessionHandler())); - } - $this->saveHandler = $saveHandler; - - if (headers_sent() || \PHP_SESSION_ACTIVE === session_status()) { - return; - } - - if ($this->saveHandler instanceof SessionHandlerProxy) { - session_set_save_handler($this->saveHandler, false); - } - } - - /** - * Load the session with attributes. - * - * After starting the session, PHP retrieves the session from whatever handlers - * are set to (either PHP's internal, or a custom save handler set with session_set_save_handler()). - * PHP takes the return value from the read() handler, unserializes it - * and populates $_SESSION with the result automatically. - */ - protected function loadSession(?array &$session = null) - { - if (null === $session) { - $session = &$_SESSION; - } - - $bags = array_merge($this->bags, [$this->metadataBag]); - - foreach ($bags as $bag) { - $key = $bag->getStorageKey(); - $session[$key] = isset($session[$key]) && \is_array($session[$key]) ? $session[$key] : []; - $bag->initialize($session[$key]); - } - - $this->started = true; - $this->closed = false; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php b/digital_doctor/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php deleted file mode 100644 index 48e6526..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php +++ /dev/null @@ -1,49 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Request; - -// Help opcache.preload discover always-needed symbols -class_exists(NativeSessionStorage::class); - -/** - * @author Jérémy Derussé - */ -class NativeSessionStorageFactory implements SessionStorageFactoryInterface -{ - private $options; - private $handler; - private $metaBag; - private $secure; - - /** - * @see NativeSessionStorage constructor. - */ - public function __construct(array $options = [], $handler = null, ?MetadataBag $metaBag = null, bool $secure = false) - { - $this->options = $options; - $this->handler = $handler; - $this->metaBag = $metaBag; - $this->secure = $secure; - } - - public function createStorage(?Request $request): SessionStorageInterface - { - $storage = new NativeSessionStorage($this->options, $this->handler, $this->metaBag); - if ($this->secure && $request && $request->isSecure()) { - $storage->setOptions(['cookie_secure' => true]); - } - - return $storage; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php b/digital_doctor/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php deleted file mode 100644 index 855d5e1..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php +++ /dev/null @@ -1,64 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; - -/** - * Allows session to be started by PHP and managed by Symfony. - * - * @author Drak - */ -class PhpBridgeSessionStorage extends NativeSessionStorage -{ - /** - * @param AbstractProxy|\SessionHandlerInterface|null $handler - */ - public function __construct($handler = null, ?MetadataBag $metaBag = null) - { - if (!\extension_loaded('session')) { - throw new \LogicException('PHP extension "session" is required.'); - } - - $this->setMetadataBag($metaBag); - $this->setSaveHandler($handler); - } - - /** - * {@inheritdoc} - */ - public function start() - { - if ($this->started) { - return true; - } - - $this->loadSession(); - - return true; - } - - /** - * {@inheritdoc} - */ - public function clear() - { - // clear out the bags and nothing else that may be set - // since the purpose of this driver is to share a handler - foreach ($this->bags as $bag) { - $bag->clear(); - } - - // reconnect the bags to the session - $this->loadSession(); - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php b/digital_doctor/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php deleted file mode 100644 index aa93263..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php +++ /dev/null @@ -1,47 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Request; - -// Help opcache.preload discover always-needed symbols -class_exists(PhpBridgeSessionStorage::class); - -/** - * @author Jérémy Derussé - */ -class PhpBridgeSessionStorageFactory implements SessionStorageFactoryInterface -{ - private $handler; - private $metaBag; - private $secure; - - /** - * @see PhpBridgeSessionStorage constructor. - */ - public function __construct($handler = null, ?MetadataBag $metaBag = null, bool $secure = false) - { - $this->handler = $handler; - $this->metaBag = $metaBag; - $this->secure = $secure; - } - - public function createStorage(?Request $request): SessionStorageInterface - { - $storage = new PhpBridgeSessionStorage($this->handler, $this->metaBag); - if ($this->secure && $request && $request->isSecure()) { - $storage->setOptions(['cookie_secure' => true]); - } - - return $storage; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Proxy/AbstractProxy.php b/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Proxy/AbstractProxy.php deleted file mode 100644 index edd04df..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Proxy/AbstractProxy.php +++ /dev/null @@ -1,118 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy; - -/** - * @author Drak - */ -abstract class AbstractProxy -{ - /** - * Flag if handler wraps an internal PHP session handler (using \SessionHandler). - * - * @var bool - */ - protected $wrapper = false; - - /** - * @var string - */ - protected $saveHandlerName; - - /** - * Gets the session.save_handler name. - * - * @return string|null - */ - public function getSaveHandlerName() - { - return $this->saveHandlerName; - } - - /** - * Is this proxy handler and instance of \SessionHandlerInterface. - * - * @return bool - */ - public function isSessionHandlerInterface() - { - return $this instanceof \SessionHandlerInterface; - } - - /** - * Returns true if this handler wraps an internal PHP session save handler using \SessionHandler. - * - * @return bool - */ - public function isWrapper() - { - return $this->wrapper; - } - - /** - * Has a session started? - * - * @return bool - */ - public function isActive() - { - return \PHP_SESSION_ACTIVE === session_status(); - } - - /** - * Gets the session ID. - * - * @return string - */ - public function getId() - { - return session_id(); - } - - /** - * Sets the session ID. - * - * @throws \LogicException - */ - public function setId(string $id) - { - if ($this->isActive()) { - throw new \LogicException('Cannot change the ID of an active session.'); - } - - session_id($id); - } - - /** - * Gets the session name. - * - * @return string - */ - public function getName() - { - return session_name(); - } - - /** - * Sets the session name. - * - * @throws \LogicException - */ - public function setName(string $name) - { - if ($this->isActive()) { - throw new \LogicException('Cannot change the name of an active session.'); - } - - session_name($name); - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php b/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php deleted file mode 100644 index 0defa4a..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php +++ /dev/null @@ -1,111 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy; - -use Symfony\Component\HttpFoundation\Session\Storage\Handler\StrictSessionHandler; - -/** - * @author Drak - */ -class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface -{ - protected $handler; - - public function __construct(\SessionHandlerInterface $handler) - { - $this->handler = $handler; - $this->wrapper = $handler instanceof \SessionHandler; - $this->saveHandlerName = $this->wrapper || ($handler instanceof StrictSessionHandler && $handler->isWrapper()) ? \ini_get('session.save_handler') : 'user'; - } - - /** - * @return \SessionHandlerInterface - */ - public function getHandler() - { - return $this->handler; - } - - // \SessionHandlerInterface - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function open($savePath, $sessionName) - { - return $this->handler->open($savePath, $sessionName); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function close() - { - return $this->handler->close(); - } - - /** - * @return string|false - */ - #[\ReturnTypeWillChange] - public function read($sessionId) - { - return $this->handler->read($sessionId); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function write($sessionId, $data) - { - return $this->handler->write($sessionId, $data); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function destroy($sessionId) - { - return $this->handler->destroy($sessionId); - } - - /** - * @return int|false - */ - #[\ReturnTypeWillChange] - public function gc($maxlifetime) - { - return $this->handler->gc($maxlifetime); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function validateId($sessionId) - { - return !$this->handler instanceof \SessionUpdateTimestampHandlerInterface || $this->handler->validateId($sessionId); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function updateTimestamp($sessionId, $data) - { - return $this->handler instanceof \SessionUpdateTimestampHandlerInterface ? $this->handler->updateTimestamp($sessionId, $data) : $this->write($sessionId, $data); - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/ServiceSessionFactory.php b/digital_doctor/vendor/symfony/http-foundation/Session/Storage/ServiceSessionFactory.php deleted file mode 100644 index d17c60a..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/ServiceSessionFactory.php +++ /dev/null @@ -1,38 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Request; - -/** - * @author Jérémy Derussé - * - * @internal to be removed in Symfony 6 - */ -final class ServiceSessionFactory implements SessionStorageFactoryInterface -{ - private $storage; - - public function __construct(SessionStorageInterface $storage) - { - $this->storage = $storage; - } - - public function createStorage(?Request $request): SessionStorageInterface - { - if ($this->storage instanceof NativeSessionStorage && $request && $request->isSecure()) { - $this->storage->setOptions(['cookie_secure' => true]); - } - - return $this->storage; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/SessionStorageFactoryInterface.php b/digital_doctor/vendor/symfony/http-foundation/Session/Storage/SessionStorageFactoryInterface.php deleted file mode 100644 index d03f0da..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/SessionStorageFactoryInterface.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Request; - -/** - * @author Jérémy Derussé - */ -interface SessionStorageFactoryInterface -{ - /** - * Creates a new instance of SessionStorageInterface. - */ - public function createStorage(?Request $request): SessionStorageInterface; -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/SessionStorageInterface.php b/digital_doctor/vendor/symfony/http-foundation/Session/Storage/SessionStorageInterface.php deleted file mode 100644 index 70b7c6a..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Session/Storage/SessionStorageInterface.php +++ /dev/null @@ -1,131 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Session\SessionBagInterface; - -/** - * StorageInterface. - * - * @author Fabien Potencier - * @author Drak - */ -interface SessionStorageInterface -{ - /** - * Starts the session. - * - * @return bool - * - * @throws \RuntimeException if something goes wrong starting the session - */ - public function start(); - - /** - * Checks if the session is started. - * - * @return bool - */ - public function isStarted(); - - /** - * Returns the session ID. - * - * @return string - */ - public function getId(); - - /** - * Sets the session ID. - */ - public function setId(string $id); - - /** - * Returns the session name. - * - * @return string - */ - public function getName(); - - /** - * Sets the session name. - */ - public function setName(string $name); - - /** - * Regenerates id that represents this storage. - * - * This method must invoke session_regenerate_id($destroy) unless - * this interface is used for a storage object designed for unit - * or functional testing where a real PHP session would interfere - * with testing. - * - * Note regenerate+destroy should not clear the session data in memory - * only delete the session data from persistent storage. - * - * Care: When regenerating the session ID no locking is involved in PHP's - * session design. See https://bugs.php.net/61470 for a discussion. - * So you must make sure the regenerated session is saved BEFORE sending the - * headers with the new ID. Symfony's HttpKernel offers a listener for this. - * See Symfony\Component\HttpKernel\EventListener\SaveSessionListener. - * Otherwise session data could get lost again for concurrent requests with the - * new ID. One result could be that you get logged out after just logging in. - * - * @param bool $destroy Destroy session when regenerating? - * @param int|null $lifetime Sets the cookie lifetime for the session cookie. A null value - * will leave the system settings unchanged, 0 sets the cookie - * to expire with browser session. Time is in seconds, and is - * not a Unix timestamp. - * - * @return bool - * - * @throws \RuntimeException If an error occurs while regenerating this storage - */ - public function regenerate(bool $destroy = false, ?int $lifetime = null); - - /** - * Force the session to be saved and closed. - * - * This method must invoke session_write_close() unless this interface is - * used for a storage object design for unit or functional testing where - * a real PHP session would interfere with testing, in which case - * it should actually persist the session data if required. - * - * @throws \RuntimeException if the session is saved without being started, or if the session - * is already closed - */ - public function save(); - - /** - * Clear all session data in memory. - */ - public function clear(); - - /** - * Gets a SessionBagInterface by name. - * - * @return SessionBagInterface - * - * @throws \InvalidArgumentException If the bag does not exist - */ - public function getBag(string $name); - - /** - * Registers a SessionBagInterface for use. - */ - public function registerBag(SessionBagInterface $bag); - - /** - * @return MetadataBag - */ - public function getMetadataBag(); -} diff --git a/digital_doctor/vendor/symfony/http-foundation/StreamedResponse.php b/digital_doctor/vendor/symfony/http-foundation/StreamedResponse.php deleted file mode 100644 index b42330d..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/StreamedResponse.php +++ /dev/null @@ -1,139 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * StreamedResponse represents a streamed HTTP response. - * - * A StreamedResponse uses a callback for its content. - * - * The callback should use the standard PHP functions like echo - * to stream the response back to the client. The flush() function - * can also be used if needed. - * - * @see flush() - * - * @author Fabien Potencier - */ -class StreamedResponse extends Response -{ - protected $callback; - protected $streamed; - private $headersSent; - - public function __construct(?callable $callback = null, int $status = 200, array $headers = []) - { - parent::__construct(null, $status, $headers); - - if (null !== $callback) { - $this->setCallback($callback); - } - $this->streamed = false; - $this->headersSent = false; - } - - /** - * Factory method for chainability. - * - * @param callable|null $callback A valid PHP callback or null to set it later - * - * @return static - * - * @deprecated since Symfony 5.1, use __construct() instead. - */ - public static function create($callback = null, int $status = 200, array $headers = []) - { - trigger_deprecation('symfony/http-foundation', '5.1', 'The "%s()" method is deprecated, use "new %s()" instead.', __METHOD__, static::class); - - return new static($callback, $status, $headers); - } - - /** - * Sets the PHP callback associated with this Response. - * - * @return $this - */ - public function setCallback(callable $callback) - { - $this->callback = $callback; - - return $this; - } - - /** - * {@inheritdoc} - * - * This method only sends the headers once. - * - * @return $this - */ - public function sendHeaders() - { - if ($this->headersSent) { - return $this; - } - - $this->headersSent = true; - - return parent::sendHeaders(); - } - - /** - * {@inheritdoc} - * - * This method only sends the content once. - * - * @return $this - */ - public function sendContent() - { - if ($this->streamed) { - return $this; - } - - $this->streamed = true; - - if (null === $this->callback) { - throw new \LogicException('The Response callback must not be null.'); - } - - ($this->callback)(); - - return $this; - } - - /** - * {@inheritdoc} - * - * @return $this - * - * @throws \LogicException when the content is not null - */ - public function setContent(?string $content) - { - if (null !== $content) { - throw new \LogicException('The content cannot be set on a StreamedResponse instance.'); - } - - $this->streamed = true; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function getContent() - { - return false; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Test/Constraint/RequestAttributeValueSame.php b/digital_doctor/vendor/symfony/http-foundation/Test/Constraint/RequestAttributeValueSame.php deleted file mode 100644 index cb216ea..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Test/Constraint/RequestAttributeValueSame.php +++ /dev/null @@ -1,55 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use Symfony\Component\HttpFoundation\Request; - -final class RequestAttributeValueSame extends Constraint -{ - private $name; - private $value; - - public function __construct(string $name, string $value) - { - $this->name = $name; - $this->value = $value; - } - - /** - * {@inheritdoc} - */ - public function toString(): string - { - return sprintf('has attribute "%s" with value "%s"', $this->name, $this->value); - } - - /** - * @param Request $request - * - * {@inheritdoc} - */ - protected function matches($request): bool - { - return $this->value === $request->attributes->get($this->name); - } - - /** - * @param Request $request - * - * {@inheritdoc} - */ - protected function failureDescription($request): string - { - return 'the Request '.$this->toString(); - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Test/Constraint/ResponseCookieValueSame.php b/digital_doctor/vendor/symfony/http-foundation/Test/Constraint/ResponseCookieValueSame.php deleted file mode 100644 index 939925b..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Test/Constraint/ResponseCookieValueSame.php +++ /dev/null @@ -1,85 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use Symfony\Component\HttpFoundation\Cookie; -use Symfony\Component\HttpFoundation\Response; - -final class ResponseCookieValueSame extends Constraint -{ - private $name; - private $value; - private $path; - private $domain; - - public function __construct(string $name, string $value, string $path = '/', ?string $domain = null) - { - $this->name = $name; - $this->value = $value; - $this->path = $path; - $this->domain = $domain; - } - - /** - * {@inheritdoc} - */ - public function toString(): string - { - $str = sprintf('has cookie "%s"', $this->name); - if ('/' !== $this->path) { - $str .= sprintf(' with path "%s"', $this->path); - } - if ($this->domain) { - $str .= sprintf(' for domain "%s"', $this->domain); - } - $str .= sprintf(' with value "%s"', $this->value); - - return $str; - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function matches($response): bool - { - $cookie = $this->getCookie($response); - if (!$cookie) { - return false; - } - - return $this->value === (string) $cookie->getValue(); - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function failureDescription($response): string - { - return 'the Response '.$this->toString(); - } - - protected function getCookie(Response $response): ?Cookie - { - $cookies = $response->headers->getCookies(); - - $filteredCookies = array_filter($cookies, function (Cookie $cookie) { - return $cookie->getName() === $this->name && $cookie->getPath() === $this->path && $cookie->getDomain() === $this->domain; - }); - - return reset($filteredCookies) ?: null; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Test/Constraint/ResponseFormatSame.php b/digital_doctor/vendor/symfony/http-foundation/Test/Constraint/ResponseFormatSame.php deleted file mode 100644 index f73aedf..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Test/Constraint/ResponseFormatSame.php +++ /dev/null @@ -1,71 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; - -/** - * Asserts that the response is in the given format. - * - * @author Kévin Dunglas - */ -final class ResponseFormatSame extends Constraint -{ - private $request; - private $format; - - public function __construct(Request $request, ?string $format) - { - $this->request = $request; - $this->format = $format; - } - - /** - * {@inheritdoc} - */ - public function toString(): string - { - return 'format is '.($this->format ?? 'null'); - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function matches($response): bool - { - return $this->format === $this->request->getFormat($response->headers->get('Content-Type')); - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function failureDescription($response): string - { - return 'the Response '.$this->toString(); - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function additionalFailureDescription($response): string - { - return (string) $response; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Test/Constraint/ResponseHasCookie.php b/digital_doctor/vendor/symfony/http-foundation/Test/Constraint/ResponseHasCookie.php deleted file mode 100644 index 9d6e58c..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Test/Constraint/ResponseHasCookie.php +++ /dev/null @@ -1,77 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use Symfony\Component\HttpFoundation\Cookie; -use Symfony\Component\HttpFoundation\Response; - -final class ResponseHasCookie extends Constraint -{ - private $name; - private $path; - private $domain; - - public function __construct(string $name, string $path = '/', ?string $domain = null) - { - $this->name = $name; - $this->path = $path; - $this->domain = $domain; - } - - /** - * {@inheritdoc} - */ - public function toString(): string - { - $str = sprintf('has cookie "%s"', $this->name); - if ('/' !== $this->path) { - $str .= sprintf(' with path "%s"', $this->path); - } - if ($this->domain) { - $str .= sprintf(' for domain "%s"', $this->domain); - } - - return $str; - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function matches($response): bool - { - return null !== $this->getCookie($response); - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function failureDescription($response): string - { - return 'the Response '.$this->toString(); - } - - private function getCookie(Response $response): ?Cookie - { - $cookies = $response->headers->getCookies(); - - $filteredCookies = array_filter($cookies, function (Cookie $cookie) { - return $cookie->getName() === $this->name && $cookie->getPath() === $this->path && $cookie->getDomain() === $this->domain; - }); - - return reset($filteredCookies) ?: null; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Test/Constraint/ResponseHasHeader.php b/digital_doctor/vendor/symfony/http-foundation/Test/Constraint/ResponseHasHeader.php deleted file mode 100644 index 68ad827..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Test/Constraint/ResponseHasHeader.php +++ /dev/null @@ -1,53 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use Symfony\Component\HttpFoundation\Response; - -final class ResponseHasHeader extends Constraint -{ - private $headerName; - - public function __construct(string $headerName) - { - $this->headerName = $headerName; - } - - /** - * {@inheritdoc} - */ - public function toString(): string - { - return sprintf('has header "%s"', $this->headerName); - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function matches($response): bool - { - return $response->headers->has($this->headerName); - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function failureDescription($response): string - { - return 'the Response '.$this->toString(); - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Test/Constraint/ResponseHeaderSame.php b/digital_doctor/vendor/symfony/http-foundation/Test/Constraint/ResponseHeaderSame.php deleted file mode 100644 index a27d0c7..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Test/Constraint/ResponseHeaderSame.php +++ /dev/null @@ -1,55 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use Symfony\Component\HttpFoundation\Response; - -final class ResponseHeaderSame extends Constraint -{ - private $headerName; - private $expectedValue; - - public function __construct(string $headerName, string $expectedValue) - { - $this->headerName = $headerName; - $this->expectedValue = $expectedValue; - } - - /** - * {@inheritdoc} - */ - public function toString(): string - { - return sprintf('has header "%s" with value "%s"', $this->headerName, $this->expectedValue); - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function matches($response): bool - { - return $this->expectedValue === $response->headers->get($this->headerName, null); - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function failureDescription($response): string - { - return 'the Response '.$this->toString(); - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Test/Constraint/ResponseIsRedirected.php b/digital_doctor/vendor/symfony/http-foundation/Test/Constraint/ResponseIsRedirected.php deleted file mode 100644 index 8c4b883..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Test/Constraint/ResponseIsRedirected.php +++ /dev/null @@ -1,56 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use Symfony\Component\HttpFoundation\Response; - -final class ResponseIsRedirected extends Constraint -{ - /** - * {@inheritdoc} - */ - public function toString(): string - { - return 'is redirected'; - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function matches($response): bool - { - return $response->isRedirect(); - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function failureDescription($response): string - { - return 'the Response '.$this->toString(); - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function additionalFailureDescription($response): string - { - return (string) $response; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Test/Constraint/ResponseIsSuccessful.php b/digital_doctor/vendor/symfony/http-foundation/Test/Constraint/ResponseIsSuccessful.php deleted file mode 100644 index 9c66558..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Test/Constraint/ResponseIsSuccessful.php +++ /dev/null @@ -1,56 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use Symfony\Component\HttpFoundation\Response; - -final class ResponseIsSuccessful extends Constraint -{ - /** - * {@inheritdoc} - */ - public function toString(): string - { - return 'is successful'; - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function matches($response): bool - { - return $response->isSuccessful(); - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function failureDescription($response): string - { - return 'the Response '.$this->toString(); - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function additionalFailureDescription($response): string - { - return (string) $response; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Test/Constraint/ResponseIsUnprocessable.php b/digital_doctor/vendor/symfony/http-foundation/Test/Constraint/ResponseIsUnprocessable.php deleted file mode 100644 index 880c781..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Test/Constraint/ResponseIsUnprocessable.php +++ /dev/null @@ -1,56 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use Symfony\Component\HttpFoundation\Response; - -final class ResponseIsUnprocessable extends Constraint -{ - /** - * {@inheritdoc} - */ - public function toString(): string - { - return 'is unprocessable'; - } - - /** - * @param Response $other - * - * {@inheritdoc} - */ - protected function matches($other): bool - { - return Response::HTTP_UNPROCESSABLE_ENTITY === $other->getStatusCode(); - } - - /** - * @param Response $other - * - * {@inheritdoc} - */ - protected function failureDescription($other): string - { - return 'the Response '.$this->toString(); - } - - /** - * @param Response $other - * - * {@inheritdoc} - */ - protected function additionalFailureDescription($other): string - { - return (string) $other; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/Test/Constraint/ResponseStatusCodeSame.php b/digital_doctor/vendor/symfony/http-foundation/Test/Constraint/ResponseStatusCodeSame.php deleted file mode 100644 index 72bb000..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/Test/Constraint/ResponseStatusCodeSame.php +++ /dev/null @@ -1,63 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use Symfony\Component\HttpFoundation\Response; - -final class ResponseStatusCodeSame extends Constraint -{ - private $statusCode; - - public function __construct(int $statusCode) - { - $this->statusCode = $statusCode; - } - - /** - * {@inheritdoc} - */ - public function toString(): string - { - return 'status code is '.$this->statusCode; - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function matches($response): bool - { - return $this->statusCode === $response->getStatusCode(); - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function failureDescription($response): string - { - return 'the Response '.$this->toString(); - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function additionalFailureDescription($response): string - { - return (string) $response; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/UrlHelper.php b/digital_doctor/vendor/symfony/http-foundation/UrlHelper.php deleted file mode 100644 index 9065994..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/UrlHelper.php +++ /dev/null @@ -1,118 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -use Symfony\Component\Routing\RequestContext; -use Symfony\Component\Routing\RequestContextAwareInterface; - -/** - * A helper service for manipulating URLs within and outside the request scope. - * - * @author Valentin Udaltsov - */ -final class UrlHelper -{ - private $requestStack; - private $requestContext; - - /** - * @param RequestContextAwareInterface|RequestContext|null $requestContext - */ - public function __construct(RequestStack $requestStack, $requestContext = null) - { - if (null !== $requestContext && !$requestContext instanceof RequestContext && !$requestContext instanceof RequestContextAwareInterface) { - throw new \TypeError(__METHOD__.': Argument #2 ($requestContext) must of type Symfony\Component\Routing\RequestContextAwareInterface|Symfony\Component\Routing\RequestContext|null, '.get_debug_type($requestContext).' given.'); - } - - $this->requestStack = $requestStack; - $this->requestContext = $requestContext; - } - - public function getAbsoluteUrl(string $path): string - { - if (str_contains($path, '://') || '//' === substr($path, 0, 2)) { - return $path; - } - - if (null === $request = $this->requestStack->getMainRequest()) { - return $this->getAbsoluteUrlFromContext($path); - } - - if ('#' === $path[0]) { - $path = $request->getRequestUri().$path; - } elseif ('?' === $path[0]) { - $path = $request->getPathInfo().$path; - } - - if (!$path || '/' !== $path[0]) { - $prefix = $request->getPathInfo(); - $last = \strlen($prefix) - 1; - if ($last !== $pos = strrpos($prefix, '/')) { - $prefix = substr($prefix, 0, $pos).'/'; - } - - return $request->getUriForPath($prefix.$path); - } - - return $request->getSchemeAndHttpHost().$path; - } - - public function getRelativePath(string $path): string - { - if (str_contains($path, '://') || '//' === substr($path, 0, 2)) { - return $path; - } - - if (null === $request = $this->requestStack->getMainRequest()) { - return $path; - } - - return $request->getRelativeUriForPath($path); - } - - private function getAbsoluteUrlFromContext(string $path): string - { - if (null === $context = $this->requestContext) { - return $path; - } - - if ($context instanceof RequestContextAwareInterface) { - $context = $context->getContext(); - } - - if ('' === $host = $context->getHost()) { - return $path; - } - - $scheme = $context->getScheme(); - $port = ''; - - if ('http' === $scheme && 80 !== $context->getHttpPort()) { - $port = ':'.$context->getHttpPort(); - } elseif ('https' === $scheme && 443 !== $context->getHttpsPort()) { - $port = ':'.$context->getHttpsPort(); - } - - if ('#' === $path[0]) { - $queryString = $context->getQueryString(); - $path = $context->getPathInfo().($queryString ? '?'.$queryString : '').$path; - } elseif ('?' === $path[0]) { - $path = $context->getPathInfo().$path; - } - - if ('/' !== $path[0]) { - $path = rtrim($context->getBaseUrl(), '/').'/'.$path; - } - - return $scheme.'://'.$host.$port.$path; - } -} diff --git a/digital_doctor/vendor/symfony/http-foundation/composer.json b/digital_doctor/vendor/symfony/http-foundation/composer.json deleted file mode 100644 index a2e43a9..0000000 --- a/digital_doctor/vendor/symfony/http-foundation/composer.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "name": "symfony/http-foundation", - "type": "library", - "description": "Defines an object-oriented layer for the HTTP specification", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-mbstring": "~1.1", - "symfony/polyfill-php80": "^1.16" - }, - "require-dev": { - "predis/predis": "^1.0|^2.0", - "symfony/cache": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4", - "symfony/mime": "^4.4|^5.0|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/rate-limiter": "^5.2|^6.0" - }, - "suggest" : { - "symfony/mime": "To use the file extension guesser" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\HttpFoundation\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev" -} diff --git a/digital_doctor/vendor/symfony/polyfill-mbstring/LICENSE b/digital_doctor/vendor/symfony/polyfill-mbstring/LICENSE deleted file mode 100644 index 6e3afce..0000000 --- a/digital_doctor/vendor/symfony/polyfill-mbstring/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2015-present Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/digital_doctor/vendor/symfony/polyfill-mbstring/Mbstring.php b/digital_doctor/vendor/symfony/polyfill-mbstring/Mbstring.php deleted file mode 100644 index 1ad33a8..0000000 --- a/digital_doctor/vendor/symfony/polyfill-mbstring/Mbstring.php +++ /dev/null @@ -1,996 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Mbstring; - -/** - * Partial mbstring implementation in PHP, iconv based, UTF-8 centric. - * - * Implemented: - * - mb_chr - Returns a specific character from its Unicode code point - * - mb_convert_encoding - Convert character encoding - * - mb_convert_variables - Convert character code in variable(s) - * - mb_decode_mimeheader - Decode string in MIME header field - * - mb_encode_mimeheader - Encode string for MIME header XXX NATIVE IMPLEMENTATION IS REALLY BUGGED - * - mb_decode_numericentity - Decode HTML numeric string reference to character - * - mb_encode_numericentity - Encode character to HTML numeric string reference - * - mb_convert_case - Perform case folding on a string - * - mb_detect_encoding - Detect character encoding - * - mb_get_info - Get internal settings of mbstring - * - mb_http_input - Detect HTTP input character encoding - * - mb_http_output - Set/Get HTTP output character encoding - * - mb_internal_encoding - Set/Get internal character encoding - * - mb_list_encodings - Returns an array of all supported encodings - * - mb_ord - Returns the Unicode code point of a character - * - mb_output_handler - Callback function converts character encoding in output buffer - * - mb_scrub - Replaces ill-formed byte sequences with substitute characters - * - mb_strlen - Get string length - * - mb_strpos - Find position of first occurrence of string in a string - * - mb_strrpos - Find position of last occurrence of a string in a string - * - mb_str_split - Convert a string to an array - * - mb_strtolower - Make a string lowercase - * - mb_strtoupper - Make a string uppercase - * - mb_substitute_character - Set/Get substitution character - * - mb_substr - Get part of string - * - mb_stripos - Finds position of first occurrence of a string within another, case insensitive - * - mb_stristr - Finds first occurrence of a string within another, case insensitive - * - mb_strrchr - Finds the last occurrence of a character in a string within another - * - mb_strrichr - Finds the last occurrence of a character in a string within another, case insensitive - * - mb_strripos - Finds position of last occurrence of a string within another, case insensitive - * - mb_strstr - Finds first occurrence of a string within another - * - mb_strwidth - Return width of string - * - mb_substr_count - Count the number of substring occurrences - * - mb_ucfirst - Make a string's first character uppercase - * - mb_lcfirst - Make a string's first character lowercase - * - * Not implemented: - * - mb_convert_kana - Convert "kana" one from another ("zen-kaku", "han-kaku" and more) - * - mb_ereg_* - Regular expression with multibyte support - * - mb_parse_str - Parse GET/POST/COOKIE data and set global variable - * - mb_preferred_mime_name - Get MIME charset string - * - mb_regex_encoding - Returns current encoding for multibyte regex as string - * - mb_regex_set_options - Set/Get the default options for mbregex functions - * - mb_send_mail - Send encoded mail - * - mb_split - Split multibyte string using regular expression - * - mb_strcut - Get part of string - * - mb_strimwidth - Get truncated string with specified width - * - * @author Nicolas Grekas - * - * @internal - */ -final class Mbstring -{ - public const MB_CASE_FOLD = \PHP_INT_MAX; - - private const SIMPLE_CASE_FOLD = [ - ['µ', 'ſ', "\xCD\x85", 'ς', "\xCF\x90", "\xCF\x91", "\xCF\x95", "\xCF\x96", "\xCF\xB0", "\xCF\xB1", "\xCF\xB5", "\xE1\xBA\x9B", "\xE1\xBE\xBE"], - ['μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "\xE1\xB9\xA1", 'ι'], - ]; - - private static $encodingList = ['ASCII', 'UTF-8']; - private static $language = 'neutral'; - private static $internalEncoding = 'UTF-8'; - - public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null) - { - if (\is_array($s)) { - if (PHP_VERSION_ID < 70200) { - trigger_error('mb_convert_encoding() expects parameter 1 to be string, array given', \E_USER_WARNING); - - return null; - } - - $r = []; - foreach ($s as $str) { - $r[] = self::mb_convert_encoding($str, $toEncoding, $fromEncoding); - } - - return $r; - } - - if (\is_array($fromEncoding) || (null !== $fromEncoding && false !== strpos($fromEncoding, ','))) { - $fromEncoding = self::mb_detect_encoding($s, $fromEncoding); - } else { - $fromEncoding = self::getEncoding($fromEncoding); - } - - $toEncoding = self::getEncoding($toEncoding); - - if ('BASE64' === $fromEncoding) { - $s = base64_decode($s); - $fromEncoding = $toEncoding; - } - - if ('BASE64' === $toEncoding) { - return base64_encode($s); - } - - if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) { - if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) { - $fromEncoding = 'Windows-1252'; - } - if ('UTF-8' !== $fromEncoding) { - $s = iconv($fromEncoding, 'UTF-8//IGNORE', $s); - } - - return preg_replace_callback('/[\x80-\xFF]+/', [__CLASS__, 'html_encoding_callback'], $s); - } - - if ('HTML-ENTITIES' === $fromEncoding) { - $s = html_entity_decode($s, \ENT_COMPAT, 'UTF-8'); - $fromEncoding = 'UTF-8'; - } - - return iconv($fromEncoding, $toEncoding.'//IGNORE', $s); - } - - public static function mb_convert_variables($toEncoding, $fromEncoding, &...$vars) - { - $ok = true; - array_walk_recursive($vars, function (&$v) use (&$ok, $toEncoding, $fromEncoding) { - if (false === $v = self::mb_convert_encoding($v, $toEncoding, $fromEncoding)) { - $ok = false; - } - }); - - return $ok ? $fromEncoding : false; - } - - public static function mb_decode_mimeheader($s) - { - return iconv_mime_decode($s, 2, self::$internalEncoding); - } - - public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null) - { - trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', \E_USER_WARNING); - } - - public static function mb_decode_numericentity($s, $convmap, $encoding = null) - { - if (null !== $s && !\is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) { - trigger_error('mb_decode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', \E_USER_WARNING); - - return null; - } - - if (!\is_array($convmap) || (80000 > \PHP_VERSION_ID && !$convmap)) { - return false; - } - - if (null !== $encoding && !\is_scalar($encoding)) { - trigger_error('mb_decode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', \E_USER_WARNING); - - return ''; // Instead of null (cf. mb_encode_numericentity). - } - - $s = (string) $s; - if ('' === $s) { - return ''; - } - - $encoding = self::getEncoding($encoding); - - if ('UTF-8' === $encoding) { - $encoding = null; - if (!preg_match('//u', $s)) { - $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s); - } - } else { - $s = iconv($encoding, 'UTF-8//IGNORE', $s); - } - - $cnt = floor(\count($convmap) / 4) * 4; - - for ($i = 0; $i < $cnt; $i += 4) { - // collector_decode_htmlnumericentity ignores $convmap[$i + 3] - $convmap[$i] += $convmap[$i + 2]; - $convmap[$i + 1] += $convmap[$i + 2]; - } - - $s = preg_replace_callback('/&#(?:0*([0-9]+)|x0*([0-9a-fA-F]+))(?!&);?/', function (array $m) use ($cnt, $convmap) { - $c = isset($m[2]) ? (int) hexdec($m[2]) : $m[1]; - for ($i = 0; $i < $cnt; $i += 4) { - if ($c >= $convmap[$i] && $c <= $convmap[$i + 1]) { - return self::mb_chr($c - $convmap[$i + 2]); - } - } - - return $m[0]; - }, $s); - - if (null === $encoding) { - return $s; - } - - return iconv('UTF-8', $encoding.'//IGNORE', $s); - } - - public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = false) - { - if (null !== $s && !\is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) { - trigger_error('mb_encode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', \E_USER_WARNING); - - return null; - } - - if (!\is_array($convmap) || (80000 > \PHP_VERSION_ID && !$convmap)) { - return false; - } - - if (null !== $encoding && !\is_scalar($encoding)) { - trigger_error('mb_encode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', \E_USER_WARNING); - - return null; // Instead of '' (cf. mb_decode_numericentity). - } - - if (null !== $is_hex && !\is_scalar($is_hex)) { - trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, '.\gettype($s).' given', \E_USER_WARNING); - - return null; - } - - $s = (string) $s; - if ('' === $s) { - return ''; - } - - $encoding = self::getEncoding($encoding); - - if ('UTF-8' === $encoding) { - $encoding = null; - if (!preg_match('//u', $s)) { - $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s); - } - } else { - $s = iconv($encoding, 'UTF-8//IGNORE', $s); - } - - static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4]; - - $cnt = floor(\count($convmap) / 4) * 4; - $i = 0; - $len = \strlen($s); - $result = ''; - - while ($i < $len) { - $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"]; - $uchr = substr($s, $i, $ulen); - $i += $ulen; - $c = self::mb_ord($uchr); - - for ($j = 0; $j < $cnt; $j += 4) { - if ($c >= $convmap[$j] && $c <= $convmap[$j + 1]) { - $cOffset = ($c + $convmap[$j + 2]) & $convmap[$j + 3]; - $result .= $is_hex ? sprintf('&#x%X;', $cOffset) : '&#'.$cOffset.';'; - continue 2; - } - } - $result .= $uchr; - } - - if (null === $encoding) { - return $result; - } - - return iconv('UTF-8', $encoding.'//IGNORE', $result); - } - - public static function mb_convert_case($s, $mode, $encoding = null) - { - $s = (string) $s; - if ('' === $s) { - return ''; - } - - $encoding = self::getEncoding($encoding); - - if ('UTF-8' === $encoding) { - $encoding = null; - if (!preg_match('//u', $s)) { - $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s); - } - } else { - $s = iconv($encoding, 'UTF-8//IGNORE', $s); - } - - if (\MB_CASE_TITLE == $mode) { - static $titleRegexp = null; - if (null === $titleRegexp) { - $titleRegexp = self::getData('titleCaseRegexp'); - } - $s = preg_replace_callback($titleRegexp, [__CLASS__, 'title_case'], $s); - } else { - if (\MB_CASE_UPPER == $mode) { - static $upper = null; - if (null === $upper) { - $upper = self::getData('upperCase'); - } - $map = $upper; - } else { - if (self::MB_CASE_FOLD === $mode) { - static $caseFolding = null; - if (null === $caseFolding) { - $caseFolding = self::getData('caseFolding'); - } - $s = strtr($s, $caseFolding); - } - - static $lower = null; - if (null === $lower) { - $lower = self::getData('lowerCase'); - } - $map = $lower; - } - - static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4]; - - $i = 0; - $len = \strlen($s); - - while ($i < $len) { - $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"]; - $uchr = substr($s, $i, $ulen); - $i += $ulen; - - if (isset($map[$uchr])) { - $uchr = $map[$uchr]; - $nlen = \strlen($uchr); - - if ($nlen == $ulen) { - $nlen = $i; - do { - $s[--$nlen] = $uchr[--$ulen]; - } while ($ulen); - } else { - $s = substr_replace($s, $uchr, $i - $ulen, $ulen); - $len += $nlen - $ulen; - $i += $nlen - $ulen; - } - } - } - } - - if (null === $encoding) { - return $s; - } - - return iconv('UTF-8', $encoding.'//IGNORE', $s); - } - - public static function mb_internal_encoding($encoding = null) - { - if (null === $encoding) { - return self::$internalEncoding; - } - - $normalizedEncoding = self::getEncoding($encoding); - - if ('UTF-8' === $normalizedEncoding || false !== @iconv($normalizedEncoding, $normalizedEncoding, ' ')) { - self::$internalEncoding = $normalizedEncoding; - - return true; - } - - if (80000 > \PHP_VERSION_ID) { - return false; - } - - throw new \ValueError(sprintf('Argument #1 ($encoding) must be a valid encoding, "%s" given', $encoding)); - } - - public static function mb_language($lang = null) - { - if (null === $lang) { - return self::$language; - } - - switch ($normalizedLang = strtolower($lang)) { - case 'uni': - case 'neutral': - self::$language = $normalizedLang; - - return true; - } - - if (80000 > \PHP_VERSION_ID) { - return false; - } - - throw new \ValueError(sprintf('Argument #1 ($language) must be a valid language, "%s" given', $lang)); - } - - public static function mb_list_encodings() - { - return ['UTF-8']; - } - - public static function mb_encoding_aliases($encoding) - { - switch (strtoupper($encoding)) { - case 'UTF8': - case 'UTF-8': - return ['utf8']; - } - - return false; - } - - public static function mb_check_encoding($var = null, $encoding = null) - { - if (\PHP_VERSION_ID < 70200 && \is_array($var)) { - trigger_error('mb_check_encoding() expects parameter 1 to be string, array given', \E_USER_WARNING); - - return null; - } - - if (null === $encoding) { - if (null === $var) { - return false; - } - $encoding = self::$internalEncoding; - } - - if (!\is_array($var)) { - return self::mb_detect_encoding($var, [$encoding]) || false !== @iconv($encoding, $encoding, $var); - } - - foreach ($var as $key => $value) { - if (!self::mb_check_encoding($key, $encoding)) { - return false; - } - if (!self::mb_check_encoding($value, $encoding)) { - return false; - } - } - - return true; - } - - public static function mb_detect_encoding($str, $encodingList = null, $strict = false) - { - if (null === $encodingList) { - $encodingList = self::$encodingList; - } else { - if (!\is_array($encodingList)) { - $encodingList = array_map('trim', explode(',', $encodingList)); - } - $encodingList = array_map('strtoupper', $encodingList); - } - - foreach ($encodingList as $enc) { - switch ($enc) { - case 'ASCII': - if (!preg_match('/[\x80-\xFF]/', $str)) { - return $enc; - } - break; - - case 'UTF8': - case 'UTF-8': - if (preg_match('//u', $str)) { - return 'UTF-8'; - } - break; - - default: - if (0 === strncmp($enc, 'ISO-8859-', 9)) { - return $enc; - } - } - } - - return false; - } - - public static function mb_detect_order($encodingList = null) - { - if (null === $encodingList) { - return self::$encodingList; - } - - if (!\is_array($encodingList)) { - $encodingList = array_map('trim', explode(',', $encodingList)); - } - $encodingList = array_map('strtoupper', $encodingList); - - foreach ($encodingList as $enc) { - switch ($enc) { - default: - if (strncmp($enc, 'ISO-8859-', 9)) { - return false; - } - // no break - case 'ASCII': - case 'UTF8': - case 'UTF-8': - } - } - - self::$encodingList = $encodingList; - - return true; - } - - public static function mb_strlen($s, $encoding = null) - { - $encoding = self::getEncoding($encoding); - if ('CP850' === $encoding || 'ASCII' === $encoding) { - return \strlen($s); - } - - return @iconv_strlen($s, $encoding); - } - - public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null) - { - $encoding = self::getEncoding($encoding); - if ('CP850' === $encoding || 'ASCII' === $encoding) { - return strpos($haystack, $needle, $offset); - } - - $needle = (string) $needle; - if ('' === $needle) { - if (80000 > \PHP_VERSION_ID) { - trigger_error(__METHOD__.': Empty delimiter', \E_USER_WARNING); - - return false; - } - - return 0; - } - - return iconv_strpos($haystack, $needle, $offset, $encoding); - } - - public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null) - { - $encoding = self::getEncoding($encoding); - if ('CP850' === $encoding || 'ASCII' === $encoding) { - return strrpos($haystack, $needle, $offset); - } - - if ($offset != (int) $offset) { - $offset = 0; - } elseif ($offset = (int) $offset) { - if ($offset < 0) { - if (0 > $offset += self::mb_strlen($needle)) { - $haystack = self::mb_substr($haystack, 0, $offset, $encoding); - } - $offset = 0; - } else { - $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding); - } - } - - $pos = '' !== $needle || 80000 > \PHP_VERSION_ID - ? iconv_strrpos($haystack, $needle, $encoding) - : self::mb_strlen($haystack, $encoding); - - return false !== $pos ? $offset + $pos : false; - } - - public static function mb_str_split($string, $split_length = 1, $encoding = null) - { - if (null !== $string && !\is_scalar($string) && !(\is_object($string) && method_exists($string, '__toString'))) { - trigger_error('mb_str_split() expects parameter 1 to be string, '.\gettype($string).' given', \E_USER_WARNING); - - return null; - } - - if (1 > $split_length = (int) $split_length) { - if (80000 > \PHP_VERSION_ID) { - trigger_error('The length of each segment must be greater than zero', \E_USER_WARNING); - - return false; - } - - throw new \ValueError('Argument #2 ($length) must be greater than 0'); - } - - if (null === $encoding) { - $encoding = mb_internal_encoding(); - } - - if ('UTF-8' === $encoding = self::getEncoding($encoding)) { - $rx = '/('; - while (65535 < $split_length) { - $rx .= '.{65535}'; - $split_length -= 65535; - } - $rx .= '.{'.$split_length.'})/us'; - - return preg_split($rx, $string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY); - } - - $result = []; - $length = mb_strlen($string, $encoding); - - for ($i = 0; $i < $length; $i += $split_length) { - $result[] = mb_substr($string, $i, $split_length, $encoding); - } - - return $result; - } - - public static function mb_strtolower($s, $encoding = null) - { - return self::mb_convert_case($s, \MB_CASE_LOWER, $encoding); - } - - public static function mb_strtoupper($s, $encoding = null) - { - return self::mb_convert_case($s, \MB_CASE_UPPER, $encoding); - } - - public static function mb_substitute_character($c = null) - { - if (null === $c) { - return 'none'; - } - if (0 === strcasecmp($c, 'none')) { - return true; - } - if (80000 > \PHP_VERSION_ID) { - return false; - } - if (\is_int($c) || 'long' === $c || 'entity' === $c) { - return false; - } - - throw new \ValueError('Argument #1 ($substitute_character) must be "none", "long", "entity" or a valid codepoint'); - } - - public static function mb_substr($s, $start, $length = null, $encoding = null) - { - $encoding = self::getEncoding($encoding); - if ('CP850' === $encoding || 'ASCII' === $encoding) { - return (string) substr($s, $start, null === $length ? 2147483647 : $length); - } - - if ($start < 0) { - $start = iconv_strlen($s, $encoding) + $start; - if ($start < 0) { - $start = 0; - } - } - - if (null === $length) { - $length = 2147483647; - } elseif ($length < 0) { - $length = iconv_strlen($s, $encoding) + $length - $start; - if ($length < 0) { - return ''; - } - } - - return (string) iconv_substr($s, $start, $length, $encoding); - } - - public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null) - { - [$haystack, $needle] = str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], [ - self::mb_convert_case($haystack, \MB_CASE_LOWER, $encoding), - self::mb_convert_case($needle, \MB_CASE_LOWER, $encoding), - ]); - - return self::mb_strpos($haystack, $needle, $offset, $encoding); - } - - public static function mb_stristr($haystack, $needle, $part = false, $encoding = null) - { - $pos = self::mb_stripos($haystack, $needle, 0, $encoding); - - return self::getSubpart($pos, $part, $haystack, $encoding); - } - - public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null) - { - $encoding = self::getEncoding($encoding); - if ('CP850' === $encoding || 'ASCII' === $encoding) { - $pos = strrpos($haystack, $needle); - } else { - $needle = self::mb_substr($needle, 0, 1, $encoding); - $pos = iconv_strrpos($haystack, $needle, $encoding); - } - - return self::getSubpart($pos, $part, $haystack, $encoding); - } - - public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null) - { - $needle = self::mb_substr($needle, 0, 1, $encoding); - $pos = self::mb_strripos($haystack, $needle, $encoding); - - return self::getSubpart($pos, $part, $haystack, $encoding); - } - - public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null) - { - $haystack = self::mb_convert_case($haystack, \MB_CASE_LOWER, $encoding); - $needle = self::mb_convert_case($needle, \MB_CASE_LOWER, $encoding); - - $haystack = str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], $haystack); - $needle = str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], $needle); - - return self::mb_strrpos($haystack, $needle, $offset, $encoding); - } - - public static function mb_strstr($haystack, $needle, $part = false, $encoding = null) - { - $pos = strpos($haystack, $needle); - if (false === $pos) { - return false; - } - if ($part) { - return substr($haystack, 0, $pos); - } - - return substr($haystack, $pos); - } - - public static function mb_get_info($type = 'all') - { - $info = [ - 'internal_encoding' => self::$internalEncoding, - 'http_output' => 'pass', - 'http_output_conv_mimetypes' => '^(text/|application/xhtml\+xml)', - 'func_overload' => 0, - 'func_overload_list' => 'no overload', - 'mail_charset' => 'UTF-8', - 'mail_header_encoding' => 'BASE64', - 'mail_body_encoding' => 'BASE64', - 'illegal_chars' => 0, - 'encoding_translation' => 'Off', - 'language' => self::$language, - 'detect_order' => self::$encodingList, - 'substitute_character' => 'none', - 'strict_detection' => 'Off', - ]; - - if ('all' === $type) { - return $info; - } - if (isset($info[$type])) { - return $info[$type]; - } - - return false; - } - - public static function mb_http_input($type = '') - { - return false; - } - - public static function mb_http_output($encoding = null) - { - return null !== $encoding ? 'pass' === $encoding : 'pass'; - } - - public static function mb_strwidth($s, $encoding = null) - { - $encoding = self::getEncoding($encoding); - - if ('UTF-8' !== $encoding) { - $s = iconv($encoding, 'UTF-8//IGNORE', $s); - } - - $s = preg_replace('/[\x{1100}-\x{115F}\x{2329}\x{232A}\x{2E80}-\x{303E}\x{3040}-\x{A4CF}\x{AC00}-\x{D7A3}\x{F900}-\x{FAFF}\x{FE10}-\x{FE19}\x{FE30}-\x{FE6F}\x{FF00}-\x{FF60}\x{FFE0}-\x{FFE6}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}]/u', '', $s, -1, $wide); - - return ($wide << 1) + iconv_strlen($s, 'UTF-8'); - } - - public static function mb_substr_count($haystack, $needle, $encoding = null) - { - return substr_count($haystack, $needle); - } - - public static function mb_output_handler($contents, $status) - { - return $contents; - } - - public static function mb_chr($code, $encoding = null) - { - if (0x80 > $code %= 0x200000) { - $s = \chr($code); - } elseif (0x800 > $code) { - $s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F); - } elseif (0x10000 > $code) { - $s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); - } else { - $s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); - } - - if ('UTF-8' !== $encoding = self::getEncoding($encoding)) { - $s = mb_convert_encoding($s, $encoding, 'UTF-8'); - } - - return $s; - } - - public static function mb_ord($s, $encoding = null) - { - if ('UTF-8' !== $encoding = self::getEncoding($encoding)) { - $s = mb_convert_encoding($s, 'UTF-8', $encoding); - } - - if (1 === \strlen($s)) { - return \ord($s); - } - - $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0; - if (0xF0 <= $code) { - return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80; - } - if (0xE0 <= $code) { - return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80; - } - if (0xC0 <= $code) { - return (($code - 0xC0) << 6) + $s[2] - 0x80; - } - - return $code; - } - - public static function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = \STR_PAD_RIGHT, ?string $encoding = null): string - { - if (!\in_array($pad_type, [\STR_PAD_RIGHT, \STR_PAD_LEFT, \STR_PAD_BOTH], true)) { - throw new \ValueError('mb_str_pad(): Argument #4 ($pad_type) must be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH'); - } - - if (null === $encoding) { - $encoding = self::mb_internal_encoding(); - } else { - self::assertEncoding($encoding, 'mb_str_pad(): Argument #5 ($encoding) must be a valid encoding, "%s" given'); - } - - if (self::mb_strlen($pad_string, $encoding) <= 0) { - throw new \ValueError('mb_str_pad(): Argument #3 ($pad_string) must be a non-empty string'); - } - - $paddingRequired = $length - self::mb_strlen($string, $encoding); - - if ($paddingRequired < 1) { - return $string; - } - - switch ($pad_type) { - case \STR_PAD_LEFT: - return self::mb_substr(str_repeat($pad_string, $paddingRequired), 0, $paddingRequired, $encoding).$string; - case \STR_PAD_RIGHT: - return $string.self::mb_substr(str_repeat($pad_string, $paddingRequired), 0, $paddingRequired, $encoding); - default: - $leftPaddingLength = floor($paddingRequired / 2); - $rightPaddingLength = $paddingRequired - $leftPaddingLength; - - return self::mb_substr(str_repeat($pad_string, $leftPaddingLength), 0, $leftPaddingLength, $encoding).$string.self::mb_substr(str_repeat($pad_string, $rightPaddingLength), 0, $rightPaddingLength, $encoding); - } - } - - public static function mb_ucfirst(string $string, ?string $encoding = null): string - { - if (null === $encoding) { - $encoding = self::mb_internal_encoding(); - } else { - self::assertEncoding($encoding, 'mb_ucfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given'); - } - - $firstChar = mb_substr($string, 0, 1, $encoding); - $firstChar = mb_convert_case($firstChar, \MB_CASE_TITLE, $encoding); - - return $firstChar.mb_substr($string, 1, null, $encoding); - } - - public static function mb_lcfirst(string $string, ?string $encoding = null): string - { - if (null === $encoding) { - $encoding = self::mb_internal_encoding(); - } else { - self::assertEncoding($encoding, 'mb_lcfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given'); - } - - $firstChar = mb_substr($string, 0, 1, $encoding); - $firstChar = mb_convert_case($firstChar, \MB_CASE_LOWER, $encoding); - - return $firstChar.mb_substr($string, 1, null, $encoding); - } - - private static function getSubpart($pos, $part, $haystack, $encoding) - { - if (false === $pos) { - return false; - } - if ($part) { - return self::mb_substr($haystack, 0, $pos, $encoding); - } - - return self::mb_substr($haystack, $pos, null, $encoding); - } - - private static function html_encoding_callback(array $m) - { - $i = 1; - $entities = ''; - $m = unpack('C*', htmlentities($m[0], \ENT_COMPAT, 'UTF-8')); - - while (isset($m[$i])) { - if (0x80 > $m[$i]) { - $entities .= \chr($m[$i++]); - continue; - } - if (0xF0 <= $m[$i]) { - $c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80; - } elseif (0xE0 <= $m[$i]) { - $c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80; - } else { - $c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80; - } - - $entities .= '&#'.$c.';'; - } - - return $entities; - } - - private static function title_case(array $s) - { - return self::mb_convert_case($s[1], \MB_CASE_UPPER, 'UTF-8').self::mb_convert_case($s[2], \MB_CASE_LOWER, 'UTF-8'); - } - - private static function getData($file) - { - if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) { - return require $file; - } - - return false; - } - - private static function getEncoding($encoding) - { - if (null === $encoding) { - return self::$internalEncoding; - } - - if ('UTF-8' === $encoding) { - return 'UTF-8'; - } - - $encoding = strtoupper($encoding); - - if ('8BIT' === $encoding || 'BINARY' === $encoding) { - return 'CP850'; - } - - if ('UTF8' === $encoding) { - return 'UTF-8'; - } - - return $encoding; - } - - private static function assertEncoding(string $encoding, string $errorFormat): void - { - try { - $validEncoding = @self::mb_check_encoding('', $encoding); - } catch (\ValueError $e) { - throw new \ValueError(\sprintf($errorFormat, $encoding)); - } - - // BC for PHP 7.3 and lower - if (!$validEncoding) { - throw new \ValueError(\sprintf($errorFormat, $encoding)); - } - } -} diff --git a/digital_doctor/vendor/symfony/polyfill-mbstring/README.md b/digital_doctor/vendor/symfony/polyfill-mbstring/README.md deleted file mode 100644 index 478b40d..0000000 --- a/digital_doctor/vendor/symfony/polyfill-mbstring/README.md +++ /dev/null @@ -1,13 +0,0 @@ -Symfony Polyfill / Mbstring -=========================== - -This component provides a partial, native PHP implementation for the -[Mbstring](https://php.net/mbstring) extension. - -More information can be found in the -[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). - -License -======= - -This library is released under the [MIT license](LICENSE). diff --git a/digital_doctor/vendor/symfony/polyfill-mbstring/Resources/unidata/caseFolding.php b/digital_doctor/vendor/symfony/polyfill-mbstring/Resources/unidata/caseFolding.php deleted file mode 100644 index 512bba0..0000000 --- a/digital_doctor/vendor/symfony/polyfill-mbstring/Resources/unidata/caseFolding.php +++ /dev/null @@ -1,119 +0,0 @@ - 'i̇', - 'µ' => 'μ', - 'ſ' => 's', - 'ͅ' => 'ι', - 'ς' => 'σ', - 'ϐ' => 'β', - 'ϑ' => 'θ', - 'ϕ' => 'φ', - 'ϖ' => 'π', - 'ϰ' => 'κ', - 'ϱ' => 'ρ', - 'ϵ' => 'ε', - 'ẛ' => 'ṡ', - 'ι' => 'ι', - 'ß' => 'ss', - 'ʼn' => 'ʼn', - 'ǰ' => 'ǰ', - 'ΐ' => 'ΐ', - 'ΰ' => 'ΰ', - 'և' => 'եւ', - 'ẖ' => 'ẖ', - 'ẗ' => 'ẗ', - 'ẘ' => 'ẘ', - 'ẙ' => 'ẙ', - 'ẚ' => 'aʾ', - 'ẞ' => 'ss', - 'ὐ' => 'ὐ', - 'ὒ' => 'ὒ', - 'ὔ' => 'ὔ', - 'ὖ' => 'ὖ', - 'ᾀ' => 'ἀι', - 'ᾁ' => 'ἁι', - 'ᾂ' => 'ἂι', - 'ᾃ' => 'ἃι', - 'ᾄ' => 'ἄι', - 'ᾅ' => 'ἅι', - 'ᾆ' => 'ἆι', - 'ᾇ' => 'ἇι', - 'ᾈ' => 'ἀι', - 'ᾉ' => 'ἁι', - 'ᾊ' => 'ἂι', - 'ᾋ' => 'ἃι', - 'ᾌ' => 'ἄι', - 'ᾍ' => 'ἅι', - 'ᾎ' => 'ἆι', - 'ᾏ' => 'ἇι', - 'ᾐ' => 'ἠι', - 'ᾑ' => 'ἡι', - 'ᾒ' => 'ἢι', - 'ᾓ' => 'ἣι', - 'ᾔ' => 'ἤι', - 'ᾕ' => 'ἥι', - 'ᾖ' => 'ἦι', - 'ᾗ' => 'ἧι', - 'ᾘ' => 'ἠι', - 'ᾙ' => 'ἡι', - 'ᾚ' => 'ἢι', - 'ᾛ' => 'ἣι', - 'ᾜ' => 'ἤι', - 'ᾝ' => 'ἥι', - 'ᾞ' => 'ἦι', - 'ᾟ' => 'ἧι', - 'ᾠ' => 'ὠι', - 'ᾡ' => 'ὡι', - 'ᾢ' => 'ὢι', - 'ᾣ' => 'ὣι', - 'ᾤ' => 'ὤι', - 'ᾥ' => 'ὥι', - 'ᾦ' => 'ὦι', - 'ᾧ' => 'ὧι', - 'ᾨ' => 'ὠι', - 'ᾩ' => 'ὡι', - 'ᾪ' => 'ὢι', - 'ᾫ' => 'ὣι', - 'ᾬ' => 'ὤι', - 'ᾭ' => 'ὥι', - 'ᾮ' => 'ὦι', - 'ᾯ' => 'ὧι', - 'ᾲ' => 'ὰι', - 'ᾳ' => 'αι', - 'ᾴ' => 'άι', - 'ᾶ' => 'ᾶ', - 'ᾷ' => 'ᾶι', - 'ᾼ' => 'αι', - 'ῂ' => 'ὴι', - 'ῃ' => 'ηι', - 'ῄ' => 'ήι', - 'ῆ' => 'ῆ', - 'ῇ' => 'ῆι', - 'ῌ' => 'ηι', - 'ῒ' => 'ῒ', - 'ῖ' => 'ῖ', - 'ῗ' => 'ῗ', - 'ῢ' => 'ῢ', - 'ῤ' => 'ῤ', - 'ῦ' => 'ῦ', - 'ῧ' => 'ῧ', - 'ῲ' => 'ὼι', - 'ῳ' => 'ωι', - 'ῴ' => 'ώι', - 'ῶ' => 'ῶ', - 'ῷ' => 'ῶι', - 'ῼ' => 'ωι', - 'ff' => 'ff', - 'fi' => 'fi', - 'fl' => 'fl', - 'ffi' => 'ffi', - 'ffl' => 'ffl', - 'ſt' => 'st', - 'st' => 'st', - 'ﬓ' => 'մն', - 'ﬔ' => 'մե', - 'ﬕ' => 'մի', - 'ﬖ' => 'վն', - 'ﬗ' => 'մխ', -]; diff --git a/digital_doctor/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php b/digital_doctor/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php deleted file mode 100644 index fac60b0..0000000 --- a/digital_doctor/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php +++ /dev/null @@ -1,1397 +0,0 @@ - 'a', - 'B' => 'b', - 'C' => 'c', - 'D' => 'd', - 'E' => 'e', - 'F' => 'f', - 'G' => 'g', - 'H' => 'h', - 'I' => 'i', - 'J' => 'j', - 'K' => 'k', - 'L' => 'l', - 'M' => 'm', - 'N' => 'n', - 'O' => 'o', - 'P' => 'p', - 'Q' => 'q', - 'R' => 'r', - 'S' => 's', - 'T' => 't', - 'U' => 'u', - 'V' => 'v', - 'W' => 'w', - 'X' => 'x', - 'Y' => 'y', - 'Z' => 'z', - 'À' => 'à', - 'Á' => 'á', - 'Â' => 'â', - 'Ã' => 'ã', - 'Ä' => 'ä', - 'Å' => 'å', - 'Æ' => 'æ', - 'Ç' => 'ç', - 'È' => 'è', - 'É' => 'é', - 'Ê' => 'ê', - 'Ë' => 'ë', - 'Ì' => 'ì', - 'Í' => 'í', - 'Î' => 'î', - 'Ï' => 'ï', - 'Ð' => 'ð', - 'Ñ' => 'ñ', - 'Ò' => 'ò', - 'Ó' => 'ó', - 'Ô' => 'ô', - 'Õ' => 'õ', - 'Ö' => 'ö', - 'Ø' => 'ø', - 'Ù' => 'ù', - 'Ú' => 'ú', - 'Û' => 'û', - 'Ü' => 'ü', - 'Ý' => 'ý', - 'Þ' => 'þ', - 'Ā' => 'ā', - 'Ă' => 'ă', - 'Ą' => 'ą', - 'Ć' => 'ć', - 'Ĉ' => 'ĉ', - 'Ċ' => 'ċ', - 'Č' => 'č', - 'Ď' => 'ď', - 'Đ' => 'đ', - 'Ē' => 'ē', - 'Ĕ' => 'ĕ', - 'Ė' => 'ė', - 'Ę' => 'ę', - 'Ě' => 'ě', - 'Ĝ' => 'ĝ', - 'Ğ' => 'ğ', - 'Ġ' => 'ġ', - 'Ģ' => 'ģ', - 'Ĥ' => 'ĥ', - 'Ħ' => 'ħ', - 'Ĩ' => 'ĩ', - 'Ī' => 'ī', - 'Ĭ' => 'ĭ', - 'Į' => 'į', - 'İ' => 'i̇', - 'IJ' => 'ij', - 'Ĵ' => 'ĵ', - 'Ķ' => 'ķ', - 'Ĺ' => 'ĺ', - 'Ļ' => 'ļ', - 'Ľ' => 'ľ', - 'Ŀ' => 'ŀ', - 'Ł' => 'ł', - 'Ń' => 'ń', - 'Ņ' => 'ņ', - 'Ň' => 'ň', - 'Ŋ' => 'ŋ', - 'Ō' => 'ō', - 'Ŏ' => 'ŏ', - 'Ő' => 'ő', - 'Œ' => 'œ', - 'Ŕ' => 'ŕ', - 'Ŗ' => 'ŗ', - 'Ř' => 'ř', - 'Ś' => 'ś', - 'Ŝ' => 'ŝ', - 'Ş' => 'ş', - 'Š' => 'š', - 'Ţ' => 'ţ', - 'Ť' => 'ť', - 'Ŧ' => 'ŧ', - 'Ũ' => 'ũ', - 'Ū' => 'ū', - 'Ŭ' => 'ŭ', - 'Ů' => 'ů', - 'Ű' => 'ű', - 'Ų' => 'ų', - 'Ŵ' => 'ŵ', - 'Ŷ' => 'ŷ', - 'Ÿ' => 'ÿ', - 'Ź' => 'ź', - 'Ż' => 'ż', - 'Ž' => 'ž', - 'Ɓ' => 'ɓ', - 'Ƃ' => 'ƃ', - 'Ƅ' => 'ƅ', - 'Ɔ' => 'ɔ', - 'Ƈ' => 'ƈ', - 'Ɖ' => 'ɖ', - 'Ɗ' => 'ɗ', - 'Ƌ' => 'ƌ', - 'Ǝ' => 'ǝ', - 'Ə' => 'ə', - 'Ɛ' => 'ɛ', - 'Ƒ' => 'ƒ', - 'Ɠ' => 'ɠ', - 'Ɣ' => 'ɣ', - 'Ɩ' => 'ɩ', - 'Ɨ' => 'ɨ', - 'Ƙ' => 'ƙ', - 'Ɯ' => 'ɯ', - 'Ɲ' => 'ɲ', - 'Ɵ' => 'ɵ', - 'Ơ' => 'ơ', - 'Ƣ' => 'ƣ', - 'Ƥ' => 'ƥ', - 'Ʀ' => 'ʀ', - 'Ƨ' => 'ƨ', - 'Ʃ' => 'ʃ', - 'Ƭ' => 'ƭ', - 'Ʈ' => 'ʈ', - 'Ư' => 'ư', - 'Ʊ' => 'ʊ', - 'Ʋ' => 'ʋ', - 'Ƴ' => 'ƴ', - 'Ƶ' => 'ƶ', - 'Ʒ' => 'ʒ', - 'Ƹ' => 'ƹ', - 'Ƽ' => 'ƽ', - 'DŽ' => 'dž', - 'Dž' => 'dž', - 'LJ' => 'lj', - 'Lj' => 'lj', - 'NJ' => 'nj', - 'Nj' => 'nj', - 'Ǎ' => 'ǎ', - 'Ǐ' => 'ǐ', - 'Ǒ' => 'ǒ', - 'Ǔ' => 'ǔ', - 'Ǖ' => 'ǖ', - 'Ǘ' => 'ǘ', - 'Ǚ' => 'ǚ', - 'Ǜ' => 'ǜ', - 'Ǟ' => 'ǟ', - 'Ǡ' => 'ǡ', - 'Ǣ' => 'ǣ', - 'Ǥ' => 'ǥ', - 'Ǧ' => 'ǧ', - 'Ǩ' => 'ǩ', - 'Ǫ' => 'ǫ', - 'Ǭ' => 'ǭ', - 'Ǯ' => 'ǯ', - 'DZ' => 'dz', - 'Dz' => 'dz', - 'Ǵ' => 'ǵ', - 'Ƕ' => 'ƕ', - 'Ƿ' => 'ƿ', - 'Ǹ' => 'ǹ', - 'Ǻ' => 'ǻ', - 'Ǽ' => 'ǽ', - 'Ǿ' => 'ǿ', - 'Ȁ' => 'ȁ', - 'Ȃ' => 'ȃ', - 'Ȅ' => 'ȅ', - 'Ȇ' => 'ȇ', - 'Ȉ' => 'ȉ', - 'Ȋ' => 'ȋ', - 'Ȍ' => 'ȍ', - 'Ȏ' => 'ȏ', - 'Ȑ' => 'ȑ', - 'Ȓ' => 'ȓ', - 'Ȕ' => 'ȕ', - 'Ȗ' => 'ȗ', - 'Ș' => 'ș', - 'Ț' => 'ț', - 'Ȝ' => 'ȝ', - 'Ȟ' => 'ȟ', - 'Ƞ' => 'ƞ', - 'Ȣ' => 'ȣ', - 'Ȥ' => 'ȥ', - 'Ȧ' => 'ȧ', - 'Ȩ' => 'ȩ', - 'Ȫ' => 'ȫ', - 'Ȭ' => 'ȭ', - 'Ȯ' => 'ȯ', - 'Ȱ' => 'ȱ', - 'Ȳ' => 'ȳ', - 'Ⱥ' => 'ⱥ', - 'Ȼ' => 'ȼ', - 'Ƚ' => 'ƚ', - 'Ⱦ' => 'ⱦ', - 'Ɂ' => 'ɂ', - 'Ƀ' => 'ƀ', - 'Ʉ' => 'ʉ', - 'Ʌ' => 'ʌ', - 'Ɇ' => 'ɇ', - 'Ɉ' => 'ɉ', - 'Ɋ' => 'ɋ', - 'Ɍ' => 'ɍ', - 'Ɏ' => 'ɏ', - 'Ͱ' => 'ͱ', - 'Ͳ' => 'ͳ', - 'Ͷ' => 'ͷ', - 'Ϳ' => 'ϳ', - 'Ά' => 'ά', - 'Έ' => 'έ', - 'Ή' => 'ή', - 'Ί' => 'ί', - 'Ό' => 'ό', - 'Ύ' => 'ύ', - 'Ώ' => 'ώ', - 'Α' => 'α', - 'Β' => 'β', - 'Γ' => 'γ', - 'Δ' => 'δ', - 'Ε' => 'ε', - 'Ζ' => 'ζ', - 'Η' => 'η', - 'Θ' => 'θ', - 'Ι' => 'ι', - 'Κ' => 'κ', - 'Λ' => 'λ', - 'Μ' => 'μ', - 'Ν' => 'ν', - 'Ξ' => 'ξ', - 'Ο' => 'ο', - 'Π' => 'π', - 'Ρ' => 'ρ', - 'Σ' => 'σ', - 'Τ' => 'τ', - 'Υ' => 'υ', - 'Φ' => 'φ', - 'Χ' => 'χ', - 'Ψ' => 'ψ', - 'Ω' => 'ω', - 'Ϊ' => 'ϊ', - 'Ϋ' => 'ϋ', - 'Ϗ' => 'ϗ', - 'Ϙ' => 'ϙ', - 'Ϛ' => 'ϛ', - 'Ϝ' => 'ϝ', - 'Ϟ' => 'ϟ', - 'Ϡ' => 'ϡ', - 'Ϣ' => 'ϣ', - 'Ϥ' => 'ϥ', - 'Ϧ' => 'ϧ', - 'Ϩ' => 'ϩ', - 'Ϫ' => 'ϫ', - 'Ϭ' => 'ϭ', - 'Ϯ' => 'ϯ', - 'ϴ' => 'θ', - 'Ϸ' => 'ϸ', - 'Ϲ' => 'ϲ', - 'Ϻ' => 'ϻ', - 'Ͻ' => 'ͻ', - 'Ͼ' => 'ͼ', - 'Ͽ' => 'ͽ', - 'Ѐ' => 'ѐ', - 'Ё' => 'ё', - 'Ђ' => 'ђ', - 'Ѓ' => 'ѓ', - 'Є' => 'є', - 'Ѕ' => 'ѕ', - 'І' => 'і', - 'Ї' => 'ї', - 'Ј' => 'ј', - 'Љ' => 'љ', - 'Њ' => 'њ', - 'Ћ' => 'ћ', - 'Ќ' => 'ќ', - 'Ѝ' => 'ѝ', - 'Ў' => 'ў', - 'Џ' => 'џ', - 'А' => 'а', - 'Б' => 'б', - 'В' => 'в', - 'Г' => 'г', - 'Д' => 'д', - 'Е' => 'е', - 'Ж' => 'ж', - 'З' => 'з', - 'И' => 'и', - 'Й' => 'й', - 'К' => 'к', - 'Л' => 'л', - 'М' => 'м', - 'Н' => 'н', - 'О' => 'о', - 'П' => 'п', - 'Р' => 'р', - 'С' => 'с', - 'Т' => 'т', - 'У' => 'у', - 'Ф' => 'ф', - 'Х' => 'х', - 'Ц' => 'ц', - 'Ч' => 'ч', - 'Ш' => 'ш', - 'Щ' => 'щ', - 'Ъ' => 'ъ', - 'Ы' => 'ы', - 'Ь' => 'ь', - 'Э' => 'э', - 'Ю' => 'ю', - 'Я' => 'я', - 'Ѡ' => 'ѡ', - 'Ѣ' => 'ѣ', - 'Ѥ' => 'ѥ', - 'Ѧ' => 'ѧ', - 'Ѩ' => 'ѩ', - 'Ѫ' => 'ѫ', - 'Ѭ' => 'ѭ', - 'Ѯ' => 'ѯ', - 'Ѱ' => 'ѱ', - 'Ѳ' => 'ѳ', - 'Ѵ' => 'ѵ', - 'Ѷ' => 'ѷ', - 'Ѹ' => 'ѹ', - 'Ѻ' => 'ѻ', - 'Ѽ' => 'ѽ', - 'Ѿ' => 'ѿ', - 'Ҁ' => 'ҁ', - 'Ҋ' => 'ҋ', - 'Ҍ' => 'ҍ', - 'Ҏ' => 'ҏ', - 'Ґ' => 'ґ', - 'Ғ' => 'ғ', - 'Ҕ' => 'ҕ', - 'Җ' => 'җ', - 'Ҙ' => 'ҙ', - 'Қ' => 'қ', - 'Ҝ' => 'ҝ', - 'Ҟ' => 'ҟ', - 'Ҡ' => 'ҡ', - 'Ң' => 'ң', - 'Ҥ' => 'ҥ', - 'Ҧ' => 'ҧ', - 'Ҩ' => 'ҩ', - 'Ҫ' => 'ҫ', - 'Ҭ' => 'ҭ', - 'Ү' => 'ү', - 'Ұ' => 'ұ', - 'Ҳ' => 'ҳ', - 'Ҵ' => 'ҵ', - 'Ҷ' => 'ҷ', - 'Ҹ' => 'ҹ', - 'Һ' => 'һ', - 'Ҽ' => 'ҽ', - 'Ҿ' => 'ҿ', - 'Ӏ' => 'ӏ', - 'Ӂ' => 'ӂ', - 'Ӄ' => 'ӄ', - 'Ӆ' => 'ӆ', - 'Ӈ' => 'ӈ', - 'Ӊ' => 'ӊ', - 'Ӌ' => 'ӌ', - 'Ӎ' => 'ӎ', - 'Ӑ' => 'ӑ', - 'Ӓ' => 'ӓ', - 'Ӕ' => 'ӕ', - 'Ӗ' => 'ӗ', - 'Ә' => 'ә', - 'Ӛ' => 'ӛ', - 'Ӝ' => 'ӝ', - 'Ӟ' => 'ӟ', - 'Ӡ' => 'ӡ', - 'Ӣ' => 'ӣ', - 'Ӥ' => 'ӥ', - 'Ӧ' => 'ӧ', - 'Ө' => 'ө', - 'Ӫ' => 'ӫ', - 'Ӭ' => 'ӭ', - 'Ӯ' => 'ӯ', - 'Ӱ' => 'ӱ', - 'Ӳ' => 'ӳ', - 'Ӵ' => 'ӵ', - 'Ӷ' => 'ӷ', - 'Ӹ' => 'ӹ', - 'Ӻ' => 'ӻ', - 'Ӽ' => 'ӽ', - 'Ӿ' => 'ӿ', - 'Ԁ' => 'ԁ', - 'Ԃ' => 'ԃ', - 'Ԅ' => 'ԅ', - 'Ԇ' => 'ԇ', - 'Ԉ' => 'ԉ', - 'Ԋ' => 'ԋ', - 'Ԍ' => 'ԍ', - 'Ԏ' => 'ԏ', - 'Ԑ' => 'ԑ', - 'Ԓ' => 'ԓ', - 'Ԕ' => 'ԕ', - 'Ԗ' => 'ԗ', - 'Ԙ' => 'ԙ', - 'Ԛ' => 'ԛ', - 'Ԝ' => 'ԝ', - 'Ԟ' => 'ԟ', - 'Ԡ' => 'ԡ', - 'Ԣ' => 'ԣ', - 'Ԥ' => 'ԥ', - 'Ԧ' => 'ԧ', - 'Ԩ' => 'ԩ', - 'Ԫ' => 'ԫ', - 'Ԭ' => 'ԭ', - 'Ԯ' => 'ԯ', - 'Ա' => 'ա', - 'Բ' => 'բ', - 'Գ' => 'գ', - 'Դ' => 'դ', - 'Ե' => 'ե', - 'Զ' => 'զ', - 'Է' => 'է', - 'Ը' => 'ը', - 'Թ' => 'թ', - 'Ժ' => 'ժ', - 'Ի' => 'ի', - 'Լ' => 'լ', - 'Խ' => 'խ', - 'Ծ' => 'ծ', - 'Կ' => 'կ', - 'Հ' => 'հ', - 'Ձ' => 'ձ', - 'Ղ' => 'ղ', - 'Ճ' => 'ճ', - 'Մ' => 'մ', - 'Յ' => 'յ', - 'Ն' => 'ն', - 'Շ' => 'շ', - 'Ո' => 'ո', - 'Չ' => 'չ', - 'Պ' => 'պ', - 'Ջ' => 'ջ', - 'Ռ' => 'ռ', - 'Ս' => 'ս', - 'Վ' => 'վ', - 'Տ' => 'տ', - 'Ր' => 'ր', - 'Ց' => 'ց', - 'Ւ' => 'ւ', - 'Փ' => 'փ', - 'Ք' => 'ք', - 'Օ' => 'օ', - 'Ֆ' => 'ֆ', - 'Ⴀ' => 'ⴀ', - 'Ⴁ' => 'ⴁ', - 'Ⴂ' => 'ⴂ', - 'Ⴃ' => 'ⴃ', - 'Ⴄ' => 'ⴄ', - 'Ⴅ' => 'ⴅ', - 'Ⴆ' => 'ⴆ', - 'Ⴇ' => 'ⴇ', - 'Ⴈ' => 'ⴈ', - 'Ⴉ' => 'ⴉ', - 'Ⴊ' => 'ⴊ', - 'Ⴋ' => 'ⴋ', - 'Ⴌ' => 'ⴌ', - 'Ⴍ' => 'ⴍ', - 'Ⴎ' => 'ⴎ', - 'Ⴏ' => 'ⴏ', - 'Ⴐ' => 'ⴐ', - 'Ⴑ' => 'ⴑ', - 'Ⴒ' => 'ⴒ', - 'Ⴓ' => 'ⴓ', - 'Ⴔ' => 'ⴔ', - 'Ⴕ' => 'ⴕ', - 'Ⴖ' => 'ⴖ', - 'Ⴗ' => 'ⴗ', - 'Ⴘ' => 'ⴘ', - 'Ⴙ' => 'ⴙ', - 'Ⴚ' => 'ⴚ', - 'Ⴛ' => 'ⴛ', - 'Ⴜ' => 'ⴜ', - 'Ⴝ' => 'ⴝ', - 'Ⴞ' => 'ⴞ', - 'Ⴟ' => 'ⴟ', - 'Ⴠ' => 'ⴠ', - 'Ⴡ' => 'ⴡ', - 'Ⴢ' => 'ⴢ', - 'Ⴣ' => 'ⴣ', - 'Ⴤ' => 'ⴤ', - 'Ⴥ' => 'ⴥ', - 'Ⴧ' => 'ⴧ', - 'Ⴭ' => 'ⴭ', - 'Ꭰ' => 'ꭰ', - 'Ꭱ' => 'ꭱ', - 'Ꭲ' => 'ꭲ', - 'Ꭳ' => 'ꭳ', - 'Ꭴ' => 'ꭴ', - 'Ꭵ' => 'ꭵ', - 'Ꭶ' => 'ꭶ', - 'Ꭷ' => 'ꭷ', - 'Ꭸ' => 'ꭸ', - 'Ꭹ' => 'ꭹ', - 'Ꭺ' => 'ꭺ', - 'Ꭻ' => 'ꭻ', - 'Ꭼ' => 'ꭼ', - 'Ꭽ' => 'ꭽ', - 'Ꭾ' => 'ꭾ', - 'Ꭿ' => 'ꭿ', - 'Ꮀ' => 'ꮀ', - 'Ꮁ' => 'ꮁ', - 'Ꮂ' => 'ꮂ', - 'Ꮃ' => 'ꮃ', - 'Ꮄ' => 'ꮄ', - 'Ꮅ' => 'ꮅ', - 'Ꮆ' => 'ꮆ', - 'Ꮇ' => 'ꮇ', - 'Ꮈ' => 'ꮈ', - 'Ꮉ' => 'ꮉ', - 'Ꮊ' => 'ꮊ', - 'Ꮋ' => 'ꮋ', - 'Ꮌ' => 'ꮌ', - 'Ꮍ' => 'ꮍ', - 'Ꮎ' => 'ꮎ', - 'Ꮏ' => 'ꮏ', - 'Ꮐ' => 'ꮐ', - 'Ꮑ' => 'ꮑ', - 'Ꮒ' => 'ꮒ', - 'Ꮓ' => 'ꮓ', - 'Ꮔ' => 'ꮔ', - 'Ꮕ' => 'ꮕ', - 'Ꮖ' => 'ꮖ', - 'Ꮗ' => 'ꮗ', - 'Ꮘ' => 'ꮘ', - 'Ꮙ' => 'ꮙ', - 'Ꮚ' => 'ꮚ', - 'Ꮛ' => 'ꮛ', - 'Ꮜ' => 'ꮜ', - 'Ꮝ' => 'ꮝ', - 'Ꮞ' => 'ꮞ', - 'Ꮟ' => 'ꮟ', - 'Ꮠ' => 'ꮠ', - 'Ꮡ' => 'ꮡ', - 'Ꮢ' => 'ꮢ', - 'Ꮣ' => 'ꮣ', - 'Ꮤ' => 'ꮤ', - 'Ꮥ' => 'ꮥ', - 'Ꮦ' => 'ꮦ', - 'Ꮧ' => 'ꮧ', - 'Ꮨ' => 'ꮨ', - 'Ꮩ' => 'ꮩ', - 'Ꮪ' => 'ꮪ', - 'Ꮫ' => 'ꮫ', - 'Ꮬ' => 'ꮬ', - 'Ꮭ' => 'ꮭ', - 'Ꮮ' => 'ꮮ', - 'Ꮯ' => 'ꮯ', - 'Ꮰ' => 'ꮰ', - 'Ꮱ' => 'ꮱ', - 'Ꮲ' => 'ꮲ', - 'Ꮳ' => 'ꮳ', - 'Ꮴ' => 'ꮴ', - 'Ꮵ' => 'ꮵ', - 'Ꮶ' => 'ꮶ', - 'Ꮷ' => 'ꮷ', - 'Ꮸ' => 'ꮸ', - 'Ꮹ' => 'ꮹ', - 'Ꮺ' => 'ꮺ', - 'Ꮻ' => 'ꮻ', - 'Ꮼ' => 'ꮼ', - 'Ꮽ' => 'ꮽ', - 'Ꮾ' => 'ꮾ', - 'Ꮿ' => 'ꮿ', - 'Ᏸ' => 'ᏸ', - 'Ᏹ' => 'ᏹ', - 'Ᏺ' => 'ᏺ', - 'Ᏻ' => 'ᏻ', - 'Ᏼ' => 'ᏼ', - 'Ᏽ' => 'ᏽ', - 'Ა' => 'ა', - 'Ბ' => 'ბ', - 'Გ' => 'გ', - 'Დ' => 'დ', - 'Ე' => 'ე', - 'Ვ' => 'ვ', - 'Ზ' => 'ზ', - 'Თ' => 'თ', - 'Ი' => 'ი', - 'Კ' => 'კ', - 'Ლ' => 'ლ', - 'Მ' => 'მ', - 'Ნ' => 'ნ', - 'Ო' => 'ო', - 'Პ' => 'პ', - 'Ჟ' => 'ჟ', - 'Რ' => 'რ', - 'Ს' => 'ს', - 'Ტ' => 'ტ', - 'Უ' => 'უ', - 'Ფ' => 'ფ', - 'Ქ' => 'ქ', - 'Ღ' => 'ღ', - 'Ყ' => 'ყ', - 'Შ' => 'შ', - 'Ჩ' => 'ჩ', - 'Ც' => 'ც', - 'Ძ' => 'ძ', - 'Წ' => 'წ', - 'Ჭ' => 'ჭ', - 'Ხ' => 'ხ', - 'Ჯ' => 'ჯ', - 'Ჰ' => 'ჰ', - 'Ჱ' => 'ჱ', - 'Ჲ' => 'ჲ', - 'Ჳ' => 'ჳ', - 'Ჴ' => 'ჴ', - 'Ჵ' => 'ჵ', - 'Ჶ' => 'ჶ', - 'Ჷ' => 'ჷ', - 'Ჸ' => 'ჸ', - 'Ჹ' => 'ჹ', - 'Ჺ' => 'ჺ', - 'Ჽ' => 'ჽ', - 'Ჾ' => 'ჾ', - 'Ჿ' => 'ჿ', - 'Ḁ' => 'ḁ', - 'Ḃ' => 'ḃ', - 'Ḅ' => 'ḅ', - 'Ḇ' => 'ḇ', - 'Ḉ' => 'ḉ', - 'Ḋ' => 'ḋ', - 'Ḍ' => 'ḍ', - 'Ḏ' => 'ḏ', - 'Ḑ' => 'ḑ', - 'Ḓ' => 'ḓ', - 'Ḕ' => 'ḕ', - 'Ḗ' => 'ḗ', - 'Ḙ' => 'ḙ', - 'Ḛ' => 'ḛ', - 'Ḝ' => 'ḝ', - 'Ḟ' => 'ḟ', - 'Ḡ' => 'ḡ', - 'Ḣ' => 'ḣ', - 'Ḥ' => 'ḥ', - 'Ḧ' => 'ḧ', - 'Ḩ' => 'ḩ', - 'Ḫ' => 'ḫ', - 'Ḭ' => 'ḭ', - 'Ḯ' => 'ḯ', - 'Ḱ' => 'ḱ', - 'Ḳ' => 'ḳ', - 'Ḵ' => 'ḵ', - 'Ḷ' => 'ḷ', - 'Ḹ' => 'ḹ', - 'Ḻ' => 'ḻ', - 'Ḽ' => 'ḽ', - 'Ḿ' => 'ḿ', - 'Ṁ' => 'ṁ', - 'Ṃ' => 'ṃ', - 'Ṅ' => 'ṅ', - 'Ṇ' => 'ṇ', - 'Ṉ' => 'ṉ', - 'Ṋ' => 'ṋ', - 'Ṍ' => 'ṍ', - 'Ṏ' => 'ṏ', - 'Ṑ' => 'ṑ', - 'Ṓ' => 'ṓ', - 'Ṕ' => 'ṕ', - 'Ṗ' => 'ṗ', - 'Ṙ' => 'ṙ', - 'Ṛ' => 'ṛ', - 'Ṝ' => 'ṝ', - 'Ṟ' => 'ṟ', - 'Ṡ' => 'ṡ', - 'Ṣ' => 'ṣ', - 'Ṥ' => 'ṥ', - 'Ṧ' => 'ṧ', - 'Ṩ' => 'ṩ', - 'Ṫ' => 'ṫ', - 'Ṭ' => 'ṭ', - 'Ṯ' => 'ṯ', - 'Ṱ' => 'ṱ', - 'Ṳ' => 'ṳ', - 'Ṵ' => 'ṵ', - 'Ṷ' => 'ṷ', - 'Ṹ' => 'ṹ', - 'Ṻ' => 'ṻ', - 'Ṽ' => 'ṽ', - 'Ṿ' => 'ṿ', - 'Ẁ' => 'ẁ', - 'Ẃ' => 'ẃ', - 'Ẅ' => 'ẅ', - 'Ẇ' => 'ẇ', - 'Ẉ' => 'ẉ', - 'Ẋ' => 'ẋ', - 'Ẍ' => 'ẍ', - 'Ẏ' => 'ẏ', - 'Ẑ' => 'ẑ', - 'Ẓ' => 'ẓ', - 'Ẕ' => 'ẕ', - 'ẞ' => 'ß', - 'Ạ' => 'ạ', - 'Ả' => 'ả', - 'Ấ' => 'ấ', - 'Ầ' => 'ầ', - 'Ẩ' => 'ẩ', - 'Ẫ' => 'ẫ', - 'Ậ' => 'ậ', - 'Ắ' => 'ắ', - 'Ằ' => 'ằ', - 'Ẳ' => 'ẳ', - 'Ẵ' => 'ẵ', - 'Ặ' => 'ặ', - 'Ẹ' => 'ẹ', - 'Ẻ' => 'ẻ', - 'Ẽ' => 'ẽ', - 'Ế' => 'ế', - 'Ề' => 'ề', - 'Ể' => 'ể', - 'Ễ' => 'ễ', - 'Ệ' => 'ệ', - 'Ỉ' => 'ỉ', - 'Ị' => 'ị', - 'Ọ' => 'ọ', - 'Ỏ' => 'ỏ', - 'Ố' => 'ố', - 'Ồ' => 'ồ', - 'Ổ' => 'ổ', - 'Ỗ' => 'ỗ', - 'Ộ' => 'ộ', - 'Ớ' => 'ớ', - 'Ờ' => 'ờ', - 'Ở' => 'ở', - 'Ỡ' => 'ỡ', - 'Ợ' => 'ợ', - 'Ụ' => 'ụ', - 'Ủ' => 'ủ', - 'Ứ' => 'ứ', - 'Ừ' => 'ừ', - 'Ử' => 'ử', - 'Ữ' => 'ữ', - 'Ự' => 'ự', - 'Ỳ' => 'ỳ', - 'Ỵ' => 'ỵ', - 'Ỷ' => 'ỷ', - 'Ỹ' => 'ỹ', - 'Ỻ' => 'ỻ', - 'Ỽ' => 'ỽ', - 'Ỿ' => 'ỿ', - 'Ἀ' => 'ἀ', - 'Ἁ' => 'ἁ', - 'Ἂ' => 'ἂ', - 'Ἃ' => 'ἃ', - 'Ἄ' => 'ἄ', - 'Ἅ' => 'ἅ', - 'Ἆ' => 'ἆ', - 'Ἇ' => 'ἇ', - 'Ἐ' => 'ἐ', - 'Ἑ' => 'ἑ', - 'Ἒ' => 'ἒ', - 'Ἓ' => 'ἓ', - 'Ἔ' => 'ἔ', - 'Ἕ' => 'ἕ', - 'Ἠ' => 'ἠ', - 'Ἡ' => 'ἡ', - 'Ἢ' => 'ἢ', - 'Ἣ' => 'ἣ', - 'Ἤ' => 'ἤ', - 'Ἥ' => 'ἥ', - 'Ἦ' => 'ἦ', - 'Ἧ' => 'ἧ', - 'Ἰ' => 'ἰ', - 'Ἱ' => 'ἱ', - 'Ἲ' => 'ἲ', - 'Ἳ' => 'ἳ', - 'Ἴ' => 'ἴ', - 'Ἵ' => 'ἵ', - 'Ἶ' => 'ἶ', - 'Ἷ' => 'ἷ', - 'Ὀ' => 'ὀ', - 'Ὁ' => 'ὁ', - 'Ὂ' => 'ὂ', - 'Ὃ' => 'ὃ', - 'Ὄ' => 'ὄ', - 'Ὅ' => 'ὅ', - 'Ὑ' => 'ὑ', - 'Ὓ' => 'ὓ', - 'Ὕ' => 'ὕ', - 'Ὗ' => 'ὗ', - 'Ὠ' => 'ὠ', - 'Ὡ' => 'ὡ', - 'Ὢ' => 'ὢ', - 'Ὣ' => 'ὣ', - 'Ὤ' => 'ὤ', - 'Ὥ' => 'ὥ', - 'Ὦ' => 'ὦ', - 'Ὧ' => 'ὧ', - 'ᾈ' => 'ᾀ', - 'ᾉ' => 'ᾁ', - 'ᾊ' => 'ᾂ', - 'ᾋ' => 'ᾃ', - 'ᾌ' => 'ᾄ', - 'ᾍ' => 'ᾅ', - 'ᾎ' => 'ᾆ', - 'ᾏ' => 'ᾇ', - 'ᾘ' => 'ᾐ', - 'ᾙ' => 'ᾑ', - 'ᾚ' => 'ᾒ', - 'ᾛ' => 'ᾓ', - 'ᾜ' => 'ᾔ', - 'ᾝ' => 'ᾕ', - 'ᾞ' => 'ᾖ', - 'ᾟ' => 'ᾗ', - 'ᾨ' => 'ᾠ', - 'ᾩ' => 'ᾡ', - 'ᾪ' => 'ᾢ', - 'ᾫ' => 'ᾣ', - 'ᾬ' => 'ᾤ', - 'ᾭ' => 'ᾥ', - 'ᾮ' => 'ᾦ', - 'ᾯ' => 'ᾧ', - 'Ᾰ' => 'ᾰ', - 'Ᾱ' => 'ᾱ', - 'Ὰ' => 'ὰ', - 'Ά' => 'ά', - 'ᾼ' => 'ᾳ', - 'Ὲ' => 'ὲ', - 'Έ' => 'έ', - 'Ὴ' => 'ὴ', - 'Ή' => 'ή', - 'ῌ' => 'ῃ', - 'Ῐ' => 'ῐ', - 'Ῑ' => 'ῑ', - 'Ὶ' => 'ὶ', - 'Ί' => 'ί', - 'Ῠ' => 'ῠ', - 'Ῡ' => 'ῡ', - 'Ὺ' => 'ὺ', - 'Ύ' => 'ύ', - 'Ῥ' => 'ῥ', - 'Ὸ' => 'ὸ', - 'Ό' => 'ό', - 'Ὼ' => 'ὼ', - 'Ώ' => 'ώ', - 'ῼ' => 'ῳ', - 'Ω' => 'ω', - 'K' => 'k', - 'Å' => 'å', - 'Ⅎ' => 'ⅎ', - 'Ⅰ' => 'ⅰ', - 'Ⅱ' => 'ⅱ', - 'Ⅲ' => 'ⅲ', - 'Ⅳ' => 'ⅳ', - 'Ⅴ' => 'ⅴ', - 'Ⅵ' => 'ⅵ', - 'Ⅶ' => 'ⅶ', - 'Ⅷ' => 'ⅷ', - 'Ⅸ' => 'ⅸ', - 'Ⅹ' => 'ⅹ', - 'Ⅺ' => 'ⅺ', - 'Ⅻ' => 'ⅻ', - 'Ⅼ' => 'ⅼ', - 'Ⅽ' => 'ⅽ', - 'Ⅾ' => 'ⅾ', - 'Ⅿ' => 'ⅿ', - 'Ↄ' => 'ↄ', - 'Ⓐ' => 'ⓐ', - 'Ⓑ' => 'ⓑ', - 'Ⓒ' => 'ⓒ', - 'Ⓓ' => 'ⓓ', - 'Ⓔ' => 'ⓔ', - 'Ⓕ' => 'ⓕ', - 'Ⓖ' => 'ⓖ', - 'Ⓗ' => 'ⓗ', - 'Ⓘ' => 'ⓘ', - 'Ⓙ' => 'ⓙ', - 'Ⓚ' => 'ⓚ', - 'Ⓛ' => 'ⓛ', - 'Ⓜ' => 'ⓜ', - 'Ⓝ' => 'ⓝ', - 'Ⓞ' => 'ⓞ', - 'Ⓟ' => 'ⓟ', - 'Ⓠ' => 'ⓠ', - 'Ⓡ' => 'ⓡ', - 'Ⓢ' => 'ⓢ', - 'Ⓣ' => 'ⓣ', - 'Ⓤ' => 'ⓤ', - 'Ⓥ' => 'ⓥ', - 'Ⓦ' => 'ⓦ', - 'Ⓧ' => 'ⓧ', - 'Ⓨ' => 'ⓨ', - 'Ⓩ' => 'ⓩ', - 'Ⰰ' => 'ⰰ', - 'Ⰱ' => 'ⰱ', - 'Ⰲ' => 'ⰲ', - 'Ⰳ' => 'ⰳ', - 'Ⰴ' => 'ⰴ', - 'Ⰵ' => 'ⰵ', - 'Ⰶ' => 'ⰶ', - 'Ⰷ' => 'ⰷ', - 'Ⰸ' => 'ⰸ', - 'Ⰹ' => 'ⰹ', - 'Ⰺ' => 'ⰺ', - 'Ⰻ' => 'ⰻ', - 'Ⰼ' => 'ⰼ', - 'Ⰽ' => 'ⰽ', - 'Ⰾ' => 'ⰾ', - 'Ⰿ' => 'ⰿ', - 'Ⱀ' => 'ⱀ', - 'Ⱁ' => 'ⱁ', - 'Ⱂ' => 'ⱂ', - 'Ⱃ' => 'ⱃ', - 'Ⱄ' => 'ⱄ', - 'Ⱅ' => 'ⱅ', - 'Ⱆ' => 'ⱆ', - 'Ⱇ' => 'ⱇ', - 'Ⱈ' => 'ⱈ', - 'Ⱉ' => 'ⱉ', - 'Ⱊ' => 'ⱊ', - 'Ⱋ' => 'ⱋ', - 'Ⱌ' => 'ⱌ', - 'Ⱍ' => 'ⱍ', - 'Ⱎ' => 'ⱎ', - 'Ⱏ' => 'ⱏ', - 'Ⱐ' => 'ⱐ', - 'Ⱑ' => 'ⱑ', - 'Ⱒ' => 'ⱒ', - 'Ⱓ' => 'ⱓ', - 'Ⱔ' => 'ⱔ', - 'Ⱕ' => 'ⱕ', - 'Ⱖ' => 'ⱖ', - 'Ⱗ' => 'ⱗ', - 'Ⱘ' => 'ⱘ', - 'Ⱙ' => 'ⱙ', - 'Ⱚ' => 'ⱚ', - 'Ⱛ' => 'ⱛ', - 'Ⱜ' => 'ⱜ', - 'Ⱝ' => 'ⱝ', - 'Ⱞ' => 'ⱞ', - 'Ⱡ' => 'ⱡ', - 'Ɫ' => 'ɫ', - 'Ᵽ' => 'ᵽ', - 'Ɽ' => 'ɽ', - 'Ⱨ' => 'ⱨ', - 'Ⱪ' => 'ⱪ', - 'Ⱬ' => 'ⱬ', - 'Ɑ' => 'ɑ', - 'Ɱ' => 'ɱ', - 'Ɐ' => 'ɐ', - 'Ɒ' => 'ɒ', - 'Ⱳ' => 'ⱳ', - 'Ⱶ' => 'ⱶ', - 'Ȿ' => 'ȿ', - 'Ɀ' => 'ɀ', - 'Ⲁ' => 'ⲁ', - 'Ⲃ' => 'ⲃ', - 'Ⲅ' => 'ⲅ', - 'Ⲇ' => 'ⲇ', - 'Ⲉ' => 'ⲉ', - 'Ⲋ' => 'ⲋ', - 'Ⲍ' => 'ⲍ', - 'Ⲏ' => 'ⲏ', - 'Ⲑ' => 'ⲑ', - 'Ⲓ' => 'ⲓ', - 'Ⲕ' => 'ⲕ', - 'Ⲗ' => 'ⲗ', - 'Ⲙ' => 'ⲙ', - 'Ⲛ' => 'ⲛ', - 'Ⲝ' => 'ⲝ', - 'Ⲟ' => 'ⲟ', - 'Ⲡ' => 'ⲡ', - 'Ⲣ' => 'ⲣ', - 'Ⲥ' => 'ⲥ', - 'Ⲧ' => 'ⲧ', - 'Ⲩ' => 'ⲩ', - 'Ⲫ' => 'ⲫ', - 'Ⲭ' => 'ⲭ', - 'Ⲯ' => 'ⲯ', - 'Ⲱ' => 'ⲱ', - 'Ⲳ' => 'ⲳ', - 'Ⲵ' => 'ⲵ', - 'Ⲷ' => 'ⲷ', - 'Ⲹ' => 'ⲹ', - 'Ⲻ' => 'ⲻ', - 'Ⲽ' => 'ⲽ', - 'Ⲿ' => 'ⲿ', - 'Ⳁ' => 'ⳁ', - 'Ⳃ' => 'ⳃ', - 'Ⳅ' => 'ⳅ', - 'Ⳇ' => 'ⳇ', - 'Ⳉ' => 'ⳉ', - 'Ⳋ' => 'ⳋ', - 'Ⳍ' => 'ⳍ', - 'Ⳏ' => 'ⳏ', - 'Ⳑ' => 'ⳑ', - 'Ⳓ' => 'ⳓ', - 'Ⳕ' => 'ⳕ', - 'Ⳗ' => 'ⳗ', - 'Ⳙ' => 'ⳙ', - 'Ⳛ' => 'ⳛ', - 'Ⳝ' => 'ⳝ', - 'Ⳟ' => 'ⳟ', - 'Ⳡ' => 'ⳡ', - 'Ⳣ' => 'ⳣ', - 'Ⳬ' => 'ⳬ', - 'Ⳮ' => 'ⳮ', - 'Ⳳ' => 'ⳳ', - 'Ꙁ' => 'ꙁ', - 'Ꙃ' => 'ꙃ', - 'Ꙅ' => 'ꙅ', - 'Ꙇ' => 'ꙇ', - 'Ꙉ' => 'ꙉ', - 'Ꙋ' => 'ꙋ', - 'Ꙍ' => 'ꙍ', - 'Ꙏ' => 'ꙏ', - 'Ꙑ' => 'ꙑ', - 'Ꙓ' => 'ꙓ', - 'Ꙕ' => 'ꙕ', - 'Ꙗ' => 'ꙗ', - 'Ꙙ' => 'ꙙ', - 'Ꙛ' => 'ꙛ', - 'Ꙝ' => 'ꙝ', - 'Ꙟ' => 'ꙟ', - 'Ꙡ' => 'ꙡ', - 'Ꙣ' => 'ꙣ', - 'Ꙥ' => 'ꙥ', - 'Ꙧ' => 'ꙧ', - 'Ꙩ' => 'ꙩ', - 'Ꙫ' => 'ꙫ', - 'Ꙭ' => 'ꙭ', - 'Ꚁ' => 'ꚁ', - 'Ꚃ' => 'ꚃ', - 'Ꚅ' => 'ꚅ', - 'Ꚇ' => 'ꚇ', - 'Ꚉ' => 'ꚉ', - 'Ꚋ' => 'ꚋ', - 'Ꚍ' => 'ꚍ', - 'Ꚏ' => 'ꚏ', - 'Ꚑ' => 'ꚑ', - 'Ꚓ' => 'ꚓ', - 'Ꚕ' => 'ꚕ', - 'Ꚗ' => 'ꚗ', - 'Ꚙ' => 'ꚙ', - 'Ꚛ' => 'ꚛ', - 'Ꜣ' => 'ꜣ', - 'Ꜥ' => 'ꜥ', - 'Ꜧ' => 'ꜧ', - 'Ꜩ' => 'ꜩ', - 'Ꜫ' => 'ꜫ', - 'Ꜭ' => 'ꜭ', - 'Ꜯ' => 'ꜯ', - 'Ꜳ' => 'ꜳ', - 'Ꜵ' => 'ꜵ', - 'Ꜷ' => 'ꜷ', - 'Ꜹ' => 'ꜹ', - 'Ꜻ' => 'ꜻ', - 'Ꜽ' => 'ꜽ', - 'Ꜿ' => 'ꜿ', - 'Ꝁ' => 'ꝁ', - 'Ꝃ' => 'ꝃ', - 'Ꝅ' => 'ꝅ', - 'Ꝇ' => 'ꝇ', - 'Ꝉ' => 'ꝉ', - 'Ꝋ' => 'ꝋ', - 'Ꝍ' => 'ꝍ', - 'Ꝏ' => 'ꝏ', - 'Ꝑ' => 'ꝑ', - 'Ꝓ' => 'ꝓ', - 'Ꝕ' => 'ꝕ', - 'Ꝗ' => 'ꝗ', - 'Ꝙ' => 'ꝙ', - 'Ꝛ' => 'ꝛ', - 'Ꝝ' => 'ꝝ', - 'Ꝟ' => 'ꝟ', - 'Ꝡ' => 'ꝡ', - 'Ꝣ' => 'ꝣ', - 'Ꝥ' => 'ꝥ', - 'Ꝧ' => 'ꝧ', - 'Ꝩ' => 'ꝩ', - 'Ꝫ' => 'ꝫ', - 'Ꝭ' => 'ꝭ', - 'Ꝯ' => 'ꝯ', - 'Ꝺ' => 'ꝺ', - 'Ꝼ' => 'ꝼ', - 'Ᵹ' => 'ᵹ', - 'Ꝿ' => 'ꝿ', - 'Ꞁ' => 'ꞁ', - 'Ꞃ' => 'ꞃ', - 'Ꞅ' => 'ꞅ', - 'Ꞇ' => 'ꞇ', - 'Ꞌ' => 'ꞌ', - 'Ɥ' => 'ɥ', - 'Ꞑ' => 'ꞑ', - 'Ꞓ' => 'ꞓ', - 'Ꞗ' => 'ꞗ', - 'Ꞙ' => 'ꞙ', - 'Ꞛ' => 'ꞛ', - 'Ꞝ' => 'ꞝ', - 'Ꞟ' => 'ꞟ', - 'Ꞡ' => 'ꞡ', - 'Ꞣ' => 'ꞣ', - 'Ꞥ' => 'ꞥ', - 'Ꞧ' => 'ꞧ', - 'Ꞩ' => 'ꞩ', - 'Ɦ' => 'ɦ', - 'Ɜ' => 'ɜ', - 'Ɡ' => 'ɡ', - 'Ɬ' => 'ɬ', - 'Ɪ' => 'ɪ', - 'Ʞ' => 'ʞ', - 'Ʇ' => 'ʇ', - 'Ʝ' => 'ʝ', - 'Ꭓ' => 'ꭓ', - 'Ꞵ' => 'ꞵ', - 'Ꞷ' => 'ꞷ', - 'Ꞹ' => 'ꞹ', - 'Ꞻ' => 'ꞻ', - 'Ꞽ' => 'ꞽ', - 'Ꞿ' => 'ꞿ', - 'Ꟃ' => 'ꟃ', - 'Ꞔ' => 'ꞔ', - 'Ʂ' => 'ʂ', - 'Ᶎ' => 'ᶎ', - 'Ꟈ' => 'ꟈ', - 'Ꟊ' => 'ꟊ', - 'Ꟶ' => 'ꟶ', - 'A' => 'a', - 'B' => 'b', - 'C' => 'c', - 'D' => 'd', - 'E' => 'e', - 'F' => 'f', - 'G' => 'g', - 'H' => 'h', - 'I' => 'i', - 'J' => 'j', - 'K' => 'k', - 'L' => 'l', - 'M' => 'm', - 'N' => 'n', - 'O' => 'o', - 'P' => 'p', - 'Q' => 'q', - 'R' => 'r', - 'S' => 's', - 'T' => 't', - 'U' => 'u', - 'V' => 'v', - 'W' => 'w', - 'X' => 'x', - 'Y' => 'y', - 'Z' => 'z', - '𐐀' => '𐐨', - '𐐁' => '𐐩', - '𐐂' => '𐐪', - '𐐃' => '𐐫', - '𐐄' => '𐐬', - '𐐅' => '𐐭', - '𐐆' => '𐐮', - '𐐇' => '𐐯', - '𐐈' => '𐐰', - '𐐉' => '𐐱', - '𐐊' => '𐐲', - '𐐋' => '𐐳', - '𐐌' => '𐐴', - '𐐍' => '𐐵', - '𐐎' => '𐐶', - '𐐏' => '𐐷', - '𐐐' => '𐐸', - '𐐑' => '𐐹', - '𐐒' => '𐐺', - '𐐓' => '𐐻', - '𐐔' => '𐐼', - '𐐕' => '𐐽', - '𐐖' => '𐐾', - '𐐗' => '𐐿', - '𐐘' => '𐑀', - '𐐙' => '𐑁', - '𐐚' => '𐑂', - '𐐛' => '𐑃', - '𐐜' => '𐑄', - '𐐝' => '𐑅', - '𐐞' => '𐑆', - '𐐟' => '𐑇', - '𐐠' => '𐑈', - '𐐡' => '𐑉', - '𐐢' => '𐑊', - '𐐣' => '𐑋', - '𐐤' => '𐑌', - '𐐥' => '𐑍', - '𐐦' => '𐑎', - '𐐧' => '𐑏', - '𐒰' => '𐓘', - '𐒱' => '𐓙', - '𐒲' => '𐓚', - '𐒳' => '𐓛', - '𐒴' => '𐓜', - '𐒵' => '𐓝', - '𐒶' => '𐓞', - '𐒷' => '𐓟', - '𐒸' => '𐓠', - '𐒹' => '𐓡', - '𐒺' => '𐓢', - '𐒻' => '𐓣', - '𐒼' => '𐓤', - '𐒽' => '𐓥', - '𐒾' => '𐓦', - '𐒿' => '𐓧', - '𐓀' => '𐓨', - '𐓁' => '𐓩', - '𐓂' => '𐓪', - '𐓃' => '𐓫', - '𐓄' => '𐓬', - '𐓅' => '𐓭', - '𐓆' => '𐓮', - '𐓇' => '𐓯', - '𐓈' => '𐓰', - '𐓉' => '𐓱', - '𐓊' => '𐓲', - '𐓋' => '𐓳', - '𐓌' => '𐓴', - '𐓍' => '𐓵', - '𐓎' => '𐓶', - '𐓏' => '𐓷', - '𐓐' => '𐓸', - '𐓑' => '𐓹', - '𐓒' => '𐓺', - '𐓓' => '𐓻', - '𐲀' => '𐳀', - '𐲁' => '𐳁', - '𐲂' => '𐳂', - '𐲃' => '𐳃', - '𐲄' => '𐳄', - '𐲅' => '𐳅', - '𐲆' => '𐳆', - '𐲇' => '𐳇', - '𐲈' => '𐳈', - '𐲉' => '𐳉', - '𐲊' => '𐳊', - '𐲋' => '𐳋', - '𐲌' => '𐳌', - '𐲍' => '𐳍', - '𐲎' => '𐳎', - '𐲏' => '𐳏', - '𐲐' => '𐳐', - '𐲑' => '𐳑', - '𐲒' => '𐳒', - '𐲓' => '𐳓', - '𐲔' => '𐳔', - '𐲕' => '𐳕', - '𐲖' => '𐳖', - '𐲗' => '𐳗', - '𐲘' => '𐳘', - '𐲙' => '𐳙', - '𐲚' => '𐳚', - '𐲛' => '𐳛', - '𐲜' => '𐳜', - '𐲝' => '𐳝', - '𐲞' => '𐳞', - '𐲟' => '𐳟', - '𐲠' => '𐳠', - '𐲡' => '𐳡', - '𐲢' => '𐳢', - '𐲣' => '𐳣', - '𐲤' => '𐳤', - '𐲥' => '𐳥', - '𐲦' => '𐳦', - '𐲧' => '𐳧', - '𐲨' => '𐳨', - '𐲩' => '𐳩', - '𐲪' => '𐳪', - '𐲫' => '𐳫', - '𐲬' => '𐳬', - '𐲭' => '𐳭', - '𐲮' => '𐳮', - '𐲯' => '𐳯', - '𐲰' => '𐳰', - '𐲱' => '𐳱', - '𐲲' => '𐳲', - '𑢠' => '𑣀', - '𑢡' => '𑣁', - '𑢢' => '𑣂', - '𑢣' => '𑣃', - '𑢤' => '𑣄', - '𑢥' => '𑣅', - '𑢦' => '𑣆', - '𑢧' => '𑣇', - '𑢨' => '𑣈', - '𑢩' => '𑣉', - '𑢪' => '𑣊', - '𑢫' => '𑣋', - '𑢬' => '𑣌', - '𑢭' => '𑣍', - '𑢮' => '𑣎', - '𑢯' => '𑣏', - '𑢰' => '𑣐', - '𑢱' => '𑣑', - '𑢲' => '𑣒', - '𑢳' => '𑣓', - '𑢴' => '𑣔', - '𑢵' => '𑣕', - '𑢶' => '𑣖', - '𑢷' => '𑣗', - '𑢸' => '𑣘', - '𑢹' => '𑣙', - '𑢺' => '𑣚', - '𑢻' => '𑣛', - '𑢼' => '𑣜', - '𑢽' => '𑣝', - '𑢾' => '𑣞', - '𑢿' => '𑣟', - '𖹀' => '𖹠', - '𖹁' => '𖹡', - '𖹂' => '𖹢', - '𖹃' => '𖹣', - '𖹄' => '𖹤', - '𖹅' => '𖹥', - '𖹆' => '𖹦', - '𖹇' => '𖹧', - '𖹈' => '𖹨', - '𖹉' => '𖹩', - '𖹊' => '𖹪', - '𖹋' => '𖹫', - '𖹌' => '𖹬', - '𖹍' => '𖹭', - '𖹎' => '𖹮', - '𖹏' => '𖹯', - '𖹐' => '𖹰', - '𖹑' => '𖹱', - '𖹒' => '𖹲', - '𖹓' => '𖹳', - '𖹔' => '𖹴', - '𖹕' => '𖹵', - '𖹖' => '𖹶', - '𖹗' => '𖹷', - '𖹘' => '𖹸', - '𖹙' => '𖹹', - '𖹚' => '𖹺', - '𖹛' => '𖹻', - '𖹜' => '𖹼', - '𖹝' => '𖹽', - '𖹞' => '𖹾', - '𖹟' => '𖹿', - '𞤀' => '𞤢', - '𞤁' => '𞤣', - '𞤂' => '𞤤', - '𞤃' => '𞤥', - '𞤄' => '𞤦', - '𞤅' => '𞤧', - '𞤆' => '𞤨', - '𞤇' => '𞤩', - '𞤈' => '𞤪', - '𞤉' => '𞤫', - '𞤊' => '𞤬', - '𞤋' => '𞤭', - '𞤌' => '𞤮', - '𞤍' => '𞤯', - '𞤎' => '𞤰', - '𞤏' => '𞤱', - '𞤐' => '𞤲', - '𞤑' => '𞤳', - '𞤒' => '𞤴', - '𞤓' => '𞤵', - '𞤔' => '𞤶', - '𞤕' => '𞤷', - '𞤖' => '𞤸', - '𞤗' => '𞤹', - '𞤘' => '𞤺', - '𞤙' => '𞤻', - '𞤚' => '𞤼', - '𞤛' => '𞤽', - '𞤜' => '𞤾', - '𞤝' => '𞤿', - '𞤞' => '𞥀', - '𞤟' => '𞥁', - '𞤠' => '𞥂', - '𞤡' => '𞥃', -); diff --git a/digital_doctor/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php b/digital_doctor/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php deleted file mode 100644 index 2a8f6e7..0000000 --- a/digital_doctor/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php +++ /dev/null @@ -1,5 +0,0 @@ - 'A', - 'b' => 'B', - 'c' => 'C', - 'd' => 'D', - 'e' => 'E', - 'f' => 'F', - 'g' => 'G', - 'h' => 'H', - 'i' => 'I', - 'j' => 'J', - 'k' => 'K', - 'l' => 'L', - 'm' => 'M', - 'n' => 'N', - 'o' => 'O', - 'p' => 'P', - 'q' => 'Q', - 'r' => 'R', - 's' => 'S', - 't' => 'T', - 'u' => 'U', - 'v' => 'V', - 'w' => 'W', - 'x' => 'X', - 'y' => 'Y', - 'z' => 'Z', - 'µ' => 'Μ', - 'à' => 'À', - 'á' => 'Á', - 'â' => 'Â', - 'ã' => 'Ã', - 'ä' => 'Ä', - 'å' => 'Å', - 'æ' => 'Æ', - 'ç' => 'Ç', - 'è' => 'È', - 'é' => 'É', - 'ê' => 'Ê', - 'ë' => 'Ë', - 'ì' => 'Ì', - 'í' => 'Í', - 'î' => 'Î', - 'ï' => 'Ï', - 'ð' => 'Ð', - 'ñ' => 'Ñ', - 'ò' => 'Ò', - 'ó' => 'Ó', - 'ô' => 'Ô', - 'õ' => 'Õ', - 'ö' => 'Ö', - 'ø' => 'Ø', - 'ù' => 'Ù', - 'ú' => 'Ú', - 'û' => 'Û', - 'ü' => 'Ü', - 'ý' => 'Ý', - 'þ' => 'Þ', - 'ÿ' => 'Ÿ', - 'ā' => 'Ā', - 'ă' => 'Ă', - 'ą' => 'Ą', - 'ć' => 'Ć', - 'ĉ' => 'Ĉ', - 'ċ' => 'Ċ', - 'č' => 'Č', - 'ď' => 'Ď', - 'đ' => 'Đ', - 'ē' => 'Ē', - 'ĕ' => 'Ĕ', - 'ė' => 'Ė', - 'ę' => 'Ę', - 'ě' => 'Ě', - 'ĝ' => 'Ĝ', - 'ğ' => 'Ğ', - 'ġ' => 'Ġ', - 'ģ' => 'Ģ', - 'ĥ' => 'Ĥ', - 'ħ' => 'Ħ', - 'ĩ' => 'Ĩ', - 'ī' => 'Ī', - 'ĭ' => 'Ĭ', - 'į' => 'Į', - 'ı' => 'I', - 'ij' => 'IJ', - 'ĵ' => 'Ĵ', - 'ķ' => 'Ķ', - 'ĺ' => 'Ĺ', - 'ļ' => 'Ļ', - 'ľ' => 'Ľ', - 'ŀ' => 'Ŀ', - 'ł' => 'Ł', - 'ń' => 'Ń', - 'ņ' => 'Ņ', - 'ň' => 'Ň', - 'ŋ' => 'Ŋ', - 'ō' => 'Ō', - 'ŏ' => 'Ŏ', - 'ő' => 'Ő', - 'œ' => 'Œ', - 'ŕ' => 'Ŕ', - 'ŗ' => 'Ŗ', - 'ř' => 'Ř', - 'ś' => 'Ś', - 'ŝ' => 'Ŝ', - 'ş' => 'Ş', - 'š' => 'Š', - 'ţ' => 'Ţ', - 'ť' => 'Ť', - 'ŧ' => 'Ŧ', - 'ũ' => 'Ũ', - 'ū' => 'Ū', - 'ŭ' => 'Ŭ', - 'ů' => 'Ů', - 'ű' => 'Ű', - 'ų' => 'Ų', - 'ŵ' => 'Ŵ', - 'ŷ' => 'Ŷ', - 'ź' => 'Ź', - 'ż' => 'Ż', - 'ž' => 'Ž', - 'ſ' => 'S', - 'ƀ' => 'Ƀ', - 'ƃ' => 'Ƃ', - 'ƅ' => 'Ƅ', - 'ƈ' => 'Ƈ', - 'ƌ' => 'Ƌ', - 'ƒ' => 'Ƒ', - 'ƕ' => 'Ƕ', - 'ƙ' => 'Ƙ', - 'ƚ' => 'Ƚ', - 'ƞ' => 'Ƞ', - 'ơ' => 'Ơ', - 'ƣ' => 'Ƣ', - 'ƥ' => 'Ƥ', - 'ƨ' => 'Ƨ', - 'ƭ' => 'Ƭ', - 'ư' => 'Ư', - 'ƴ' => 'Ƴ', - 'ƶ' => 'Ƶ', - 'ƹ' => 'Ƹ', - 'ƽ' => 'Ƽ', - 'ƿ' => 'Ƿ', - 'Dž' => 'DŽ', - 'dž' => 'DŽ', - 'Lj' => 'LJ', - 'lj' => 'LJ', - 'Nj' => 'NJ', - 'nj' => 'NJ', - 'ǎ' => 'Ǎ', - 'ǐ' => 'Ǐ', - 'ǒ' => 'Ǒ', - 'ǔ' => 'Ǔ', - 'ǖ' => 'Ǖ', - 'ǘ' => 'Ǘ', - 'ǚ' => 'Ǚ', - 'ǜ' => 'Ǜ', - 'ǝ' => 'Ǝ', - 'ǟ' => 'Ǟ', - 'ǡ' => 'Ǡ', - 'ǣ' => 'Ǣ', - 'ǥ' => 'Ǥ', - 'ǧ' => 'Ǧ', - 'ǩ' => 'Ǩ', - 'ǫ' => 'Ǫ', - 'ǭ' => 'Ǭ', - 'ǯ' => 'Ǯ', - 'Dz' => 'DZ', - 'dz' => 'DZ', - 'ǵ' => 'Ǵ', - 'ǹ' => 'Ǹ', - 'ǻ' => 'Ǻ', - 'ǽ' => 'Ǽ', - 'ǿ' => 'Ǿ', - 'ȁ' => 'Ȁ', - 'ȃ' => 'Ȃ', - 'ȅ' => 'Ȅ', - 'ȇ' => 'Ȇ', - 'ȉ' => 'Ȉ', - 'ȋ' => 'Ȋ', - 'ȍ' => 'Ȍ', - 'ȏ' => 'Ȏ', - 'ȑ' => 'Ȑ', - 'ȓ' => 'Ȓ', - 'ȕ' => 'Ȕ', - 'ȗ' => 'Ȗ', - 'ș' => 'Ș', - 'ț' => 'Ț', - 'ȝ' => 'Ȝ', - 'ȟ' => 'Ȟ', - 'ȣ' => 'Ȣ', - 'ȥ' => 'Ȥ', - 'ȧ' => 'Ȧ', - 'ȩ' => 'Ȩ', - 'ȫ' => 'Ȫ', - 'ȭ' => 'Ȭ', - 'ȯ' => 'Ȯ', - 'ȱ' => 'Ȱ', - 'ȳ' => 'Ȳ', - 'ȼ' => 'Ȼ', - 'ȿ' => 'Ȿ', - 'ɀ' => 'Ɀ', - 'ɂ' => 'Ɂ', - 'ɇ' => 'Ɇ', - 'ɉ' => 'Ɉ', - 'ɋ' => 'Ɋ', - 'ɍ' => 'Ɍ', - 'ɏ' => 'Ɏ', - 'ɐ' => 'Ɐ', - 'ɑ' => 'Ɑ', - 'ɒ' => 'Ɒ', - 'ɓ' => 'Ɓ', - 'ɔ' => 'Ɔ', - 'ɖ' => 'Ɖ', - 'ɗ' => 'Ɗ', - 'ə' => 'Ə', - 'ɛ' => 'Ɛ', - 'ɜ' => 'Ɜ', - 'ɠ' => 'Ɠ', - 'ɡ' => 'Ɡ', - 'ɣ' => 'Ɣ', - 'ɥ' => 'Ɥ', - 'ɦ' => 'Ɦ', - 'ɨ' => 'Ɨ', - 'ɩ' => 'Ɩ', - 'ɪ' => 'Ɪ', - 'ɫ' => 'Ɫ', - 'ɬ' => 'Ɬ', - 'ɯ' => 'Ɯ', - 'ɱ' => 'Ɱ', - 'ɲ' => 'Ɲ', - 'ɵ' => 'Ɵ', - 'ɽ' => 'Ɽ', - 'ʀ' => 'Ʀ', - 'ʂ' => 'Ʂ', - 'ʃ' => 'Ʃ', - 'ʇ' => 'Ʇ', - 'ʈ' => 'Ʈ', - 'ʉ' => 'Ʉ', - 'ʊ' => 'Ʊ', - 'ʋ' => 'Ʋ', - 'ʌ' => 'Ʌ', - 'ʒ' => 'Ʒ', - 'ʝ' => 'Ʝ', - 'ʞ' => 'Ʞ', - 'ͅ' => 'Ι', - 'ͱ' => 'Ͱ', - 'ͳ' => 'Ͳ', - 'ͷ' => 'Ͷ', - 'ͻ' => 'Ͻ', - 'ͼ' => 'Ͼ', - 'ͽ' => 'Ͽ', - 'ά' => 'Ά', - 'έ' => 'Έ', - 'ή' => 'Ή', - 'ί' => 'Ί', - 'α' => 'Α', - 'β' => 'Β', - 'γ' => 'Γ', - 'δ' => 'Δ', - 'ε' => 'Ε', - 'ζ' => 'Ζ', - 'η' => 'Η', - 'θ' => 'Θ', - 'ι' => 'Ι', - 'κ' => 'Κ', - 'λ' => 'Λ', - 'μ' => 'Μ', - 'ν' => 'Ν', - 'ξ' => 'Ξ', - 'ο' => 'Ο', - 'π' => 'Π', - 'ρ' => 'Ρ', - 'ς' => 'Σ', - 'σ' => 'Σ', - 'τ' => 'Τ', - 'υ' => 'Υ', - 'φ' => 'Φ', - 'χ' => 'Χ', - 'ψ' => 'Ψ', - 'ω' => 'Ω', - 'ϊ' => 'Ϊ', - 'ϋ' => 'Ϋ', - 'ό' => 'Ό', - 'ύ' => 'Ύ', - 'ώ' => 'Ώ', - 'ϐ' => 'Β', - 'ϑ' => 'Θ', - 'ϕ' => 'Φ', - 'ϖ' => 'Π', - 'ϗ' => 'Ϗ', - 'ϙ' => 'Ϙ', - 'ϛ' => 'Ϛ', - 'ϝ' => 'Ϝ', - 'ϟ' => 'Ϟ', - 'ϡ' => 'Ϡ', - 'ϣ' => 'Ϣ', - 'ϥ' => 'Ϥ', - 'ϧ' => 'Ϧ', - 'ϩ' => 'Ϩ', - 'ϫ' => 'Ϫ', - 'ϭ' => 'Ϭ', - 'ϯ' => 'Ϯ', - 'ϰ' => 'Κ', - 'ϱ' => 'Ρ', - 'ϲ' => 'Ϲ', - 'ϳ' => 'Ϳ', - 'ϵ' => 'Ε', - 'ϸ' => 'Ϸ', - 'ϻ' => 'Ϻ', - 'а' => 'А', - 'б' => 'Б', - 'в' => 'В', - 'г' => 'Г', - 'д' => 'Д', - 'е' => 'Е', - 'ж' => 'Ж', - 'з' => 'З', - 'и' => 'И', - 'й' => 'Й', - 'к' => 'К', - 'л' => 'Л', - 'м' => 'М', - 'н' => 'Н', - 'о' => 'О', - 'п' => 'П', - 'р' => 'Р', - 'с' => 'С', - 'т' => 'Т', - 'у' => 'У', - 'ф' => 'Ф', - 'х' => 'Х', - 'ц' => 'Ц', - 'ч' => 'Ч', - 'ш' => 'Ш', - 'щ' => 'Щ', - 'ъ' => 'Ъ', - 'ы' => 'Ы', - 'ь' => 'Ь', - 'э' => 'Э', - 'ю' => 'Ю', - 'я' => 'Я', - 'ѐ' => 'Ѐ', - 'ё' => 'Ё', - 'ђ' => 'Ђ', - 'ѓ' => 'Ѓ', - 'є' => 'Є', - 'ѕ' => 'Ѕ', - 'і' => 'І', - 'ї' => 'Ї', - 'ј' => 'Ј', - 'љ' => 'Љ', - 'њ' => 'Њ', - 'ћ' => 'Ћ', - 'ќ' => 'Ќ', - 'ѝ' => 'Ѝ', - 'ў' => 'Ў', - 'џ' => 'Џ', - 'ѡ' => 'Ѡ', - 'ѣ' => 'Ѣ', - 'ѥ' => 'Ѥ', - 'ѧ' => 'Ѧ', - 'ѩ' => 'Ѩ', - 'ѫ' => 'Ѫ', - 'ѭ' => 'Ѭ', - 'ѯ' => 'Ѯ', - 'ѱ' => 'Ѱ', - 'ѳ' => 'Ѳ', - 'ѵ' => 'Ѵ', - 'ѷ' => 'Ѷ', - 'ѹ' => 'Ѹ', - 'ѻ' => 'Ѻ', - 'ѽ' => 'Ѽ', - 'ѿ' => 'Ѿ', - 'ҁ' => 'Ҁ', - 'ҋ' => 'Ҋ', - 'ҍ' => 'Ҍ', - 'ҏ' => 'Ҏ', - 'ґ' => 'Ґ', - 'ғ' => 'Ғ', - 'ҕ' => 'Ҕ', - 'җ' => 'Җ', - 'ҙ' => 'Ҙ', - 'қ' => 'Қ', - 'ҝ' => 'Ҝ', - 'ҟ' => 'Ҟ', - 'ҡ' => 'Ҡ', - 'ң' => 'Ң', - 'ҥ' => 'Ҥ', - 'ҧ' => 'Ҧ', - 'ҩ' => 'Ҩ', - 'ҫ' => 'Ҫ', - 'ҭ' => 'Ҭ', - 'ү' => 'Ү', - 'ұ' => 'Ұ', - 'ҳ' => 'Ҳ', - 'ҵ' => 'Ҵ', - 'ҷ' => 'Ҷ', - 'ҹ' => 'Ҹ', - 'һ' => 'Һ', - 'ҽ' => 'Ҽ', - 'ҿ' => 'Ҿ', - 'ӂ' => 'Ӂ', - 'ӄ' => 'Ӄ', - 'ӆ' => 'Ӆ', - 'ӈ' => 'Ӈ', - 'ӊ' => 'Ӊ', - 'ӌ' => 'Ӌ', - 'ӎ' => 'Ӎ', - 'ӏ' => 'Ӏ', - 'ӑ' => 'Ӑ', - 'ӓ' => 'Ӓ', - 'ӕ' => 'Ӕ', - 'ӗ' => 'Ӗ', - 'ә' => 'Ә', - 'ӛ' => 'Ӛ', - 'ӝ' => 'Ӝ', - 'ӟ' => 'Ӟ', - 'ӡ' => 'Ӡ', - 'ӣ' => 'Ӣ', - 'ӥ' => 'Ӥ', - 'ӧ' => 'Ӧ', - 'ө' => 'Ө', - 'ӫ' => 'Ӫ', - 'ӭ' => 'Ӭ', - 'ӯ' => 'Ӯ', - 'ӱ' => 'Ӱ', - 'ӳ' => 'Ӳ', - 'ӵ' => 'Ӵ', - 'ӷ' => 'Ӷ', - 'ӹ' => 'Ӹ', - 'ӻ' => 'Ӻ', - 'ӽ' => 'Ӽ', - 'ӿ' => 'Ӿ', - 'ԁ' => 'Ԁ', - 'ԃ' => 'Ԃ', - 'ԅ' => 'Ԅ', - 'ԇ' => 'Ԇ', - 'ԉ' => 'Ԉ', - 'ԋ' => 'Ԋ', - 'ԍ' => 'Ԍ', - 'ԏ' => 'Ԏ', - 'ԑ' => 'Ԑ', - 'ԓ' => 'Ԓ', - 'ԕ' => 'Ԕ', - 'ԗ' => 'Ԗ', - 'ԙ' => 'Ԙ', - 'ԛ' => 'Ԛ', - 'ԝ' => 'Ԝ', - 'ԟ' => 'Ԟ', - 'ԡ' => 'Ԡ', - 'ԣ' => 'Ԣ', - 'ԥ' => 'Ԥ', - 'ԧ' => 'Ԧ', - 'ԩ' => 'Ԩ', - 'ԫ' => 'Ԫ', - 'ԭ' => 'Ԭ', - 'ԯ' => 'Ԯ', - 'ա' => 'Ա', - 'բ' => 'Բ', - 'գ' => 'Գ', - 'դ' => 'Դ', - 'ե' => 'Ե', - 'զ' => 'Զ', - 'է' => 'Է', - 'ը' => 'Ը', - 'թ' => 'Թ', - 'ժ' => 'Ժ', - 'ի' => 'Ի', - 'լ' => 'Լ', - 'խ' => 'Խ', - 'ծ' => 'Ծ', - 'կ' => 'Կ', - 'հ' => 'Հ', - 'ձ' => 'Ձ', - 'ղ' => 'Ղ', - 'ճ' => 'Ճ', - 'մ' => 'Մ', - 'յ' => 'Յ', - 'ն' => 'Ն', - 'շ' => 'Շ', - 'ո' => 'Ո', - 'չ' => 'Չ', - 'պ' => 'Պ', - 'ջ' => 'Ջ', - 'ռ' => 'Ռ', - 'ս' => 'Ս', - 'վ' => 'Վ', - 'տ' => 'Տ', - 'ր' => 'Ր', - 'ց' => 'Ց', - 'ւ' => 'Ւ', - 'փ' => 'Փ', - 'ք' => 'Ք', - 'օ' => 'Օ', - 'ֆ' => 'Ֆ', - 'ა' => 'Ა', - 'ბ' => 'Ბ', - 'გ' => 'Გ', - 'დ' => 'Დ', - 'ე' => 'Ე', - 'ვ' => 'Ვ', - 'ზ' => 'Ზ', - 'თ' => 'Თ', - 'ი' => 'Ი', - 'კ' => 'Კ', - 'ლ' => 'Ლ', - 'მ' => 'Მ', - 'ნ' => 'Ნ', - 'ო' => 'Ო', - 'პ' => 'Პ', - 'ჟ' => 'Ჟ', - 'რ' => 'Რ', - 'ს' => 'Ს', - 'ტ' => 'Ტ', - 'უ' => 'Უ', - 'ფ' => 'Ფ', - 'ქ' => 'Ქ', - 'ღ' => 'Ღ', - 'ყ' => 'Ყ', - 'შ' => 'Შ', - 'ჩ' => 'Ჩ', - 'ც' => 'Ც', - 'ძ' => 'Ძ', - 'წ' => 'Წ', - 'ჭ' => 'Ჭ', - 'ხ' => 'Ხ', - 'ჯ' => 'Ჯ', - 'ჰ' => 'Ჰ', - 'ჱ' => 'Ჱ', - 'ჲ' => 'Ჲ', - 'ჳ' => 'Ჳ', - 'ჴ' => 'Ჴ', - 'ჵ' => 'Ჵ', - 'ჶ' => 'Ჶ', - 'ჷ' => 'Ჷ', - 'ჸ' => 'Ჸ', - 'ჹ' => 'Ჹ', - 'ჺ' => 'Ჺ', - 'ჽ' => 'Ჽ', - 'ჾ' => 'Ჾ', - 'ჿ' => 'Ჿ', - 'ᏸ' => 'Ᏸ', - 'ᏹ' => 'Ᏹ', - 'ᏺ' => 'Ᏺ', - 'ᏻ' => 'Ᏻ', - 'ᏼ' => 'Ᏼ', - 'ᏽ' => 'Ᏽ', - 'ᲀ' => 'В', - 'ᲁ' => 'Д', - 'ᲂ' => 'О', - 'ᲃ' => 'С', - 'ᲄ' => 'Т', - 'ᲅ' => 'Т', - 'ᲆ' => 'Ъ', - 'ᲇ' => 'Ѣ', - 'ᲈ' => 'Ꙋ', - 'ᵹ' => 'Ᵹ', - 'ᵽ' => 'Ᵽ', - 'ᶎ' => 'Ᶎ', - 'ḁ' => 'Ḁ', - 'ḃ' => 'Ḃ', - 'ḅ' => 'Ḅ', - 'ḇ' => 'Ḇ', - 'ḉ' => 'Ḉ', - 'ḋ' => 'Ḋ', - 'ḍ' => 'Ḍ', - 'ḏ' => 'Ḏ', - 'ḑ' => 'Ḑ', - 'ḓ' => 'Ḓ', - 'ḕ' => 'Ḕ', - 'ḗ' => 'Ḗ', - 'ḙ' => 'Ḙ', - 'ḛ' => 'Ḛ', - 'ḝ' => 'Ḝ', - 'ḟ' => 'Ḟ', - 'ḡ' => 'Ḡ', - 'ḣ' => 'Ḣ', - 'ḥ' => 'Ḥ', - 'ḧ' => 'Ḧ', - 'ḩ' => 'Ḩ', - 'ḫ' => 'Ḫ', - 'ḭ' => 'Ḭ', - 'ḯ' => 'Ḯ', - 'ḱ' => 'Ḱ', - 'ḳ' => 'Ḳ', - 'ḵ' => 'Ḵ', - 'ḷ' => 'Ḷ', - 'ḹ' => 'Ḹ', - 'ḻ' => 'Ḻ', - 'ḽ' => 'Ḽ', - 'ḿ' => 'Ḿ', - 'ṁ' => 'Ṁ', - 'ṃ' => 'Ṃ', - 'ṅ' => 'Ṅ', - 'ṇ' => 'Ṇ', - 'ṉ' => 'Ṉ', - 'ṋ' => 'Ṋ', - 'ṍ' => 'Ṍ', - 'ṏ' => 'Ṏ', - 'ṑ' => 'Ṑ', - 'ṓ' => 'Ṓ', - 'ṕ' => 'Ṕ', - 'ṗ' => 'Ṗ', - 'ṙ' => 'Ṙ', - 'ṛ' => 'Ṛ', - 'ṝ' => 'Ṝ', - 'ṟ' => 'Ṟ', - 'ṡ' => 'Ṡ', - 'ṣ' => 'Ṣ', - 'ṥ' => 'Ṥ', - 'ṧ' => 'Ṧ', - 'ṩ' => 'Ṩ', - 'ṫ' => 'Ṫ', - 'ṭ' => 'Ṭ', - 'ṯ' => 'Ṯ', - 'ṱ' => 'Ṱ', - 'ṳ' => 'Ṳ', - 'ṵ' => 'Ṵ', - 'ṷ' => 'Ṷ', - 'ṹ' => 'Ṹ', - 'ṻ' => 'Ṻ', - 'ṽ' => 'Ṽ', - 'ṿ' => 'Ṿ', - 'ẁ' => 'Ẁ', - 'ẃ' => 'Ẃ', - 'ẅ' => 'Ẅ', - 'ẇ' => 'Ẇ', - 'ẉ' => 'Ẉ', - 'ẋ' => 'Ẋ', - 'ẍ' => 'Ẍ', - 'ẏ' => 'Ẏ', - 'ẑ' => 'Ẑ', - 'ẓ' => 'Ẓ', - 'ẕ' => 'Ẕ', - 'ẛ' => 'Ṡ', - 'ạ' => 'Ạ', - 'ả' => 'Ả', - 'ấ' => 'Ấ', - 'ầ' => 'Ầ', - 'ẩ' => 'Ẩ', - 'ẫ' => 'Ẫ', - 'ậ' => 'Ậ', - 'ắ' => 'Ắ', - 'ằ' => 'Ằ', - 'ẳ' => 'Ẳ', - 'ẵ' => 'Ẵ', - 'ặ' => 'Ặ', - 'ẹ' => 'Ẹ', - 'ẻ' => 'Ẻ', - 'ẽ' => 'Ẽ', - 'ế' => 'Ế', - 'ề' => 'Ề', - 'ể' => 'Ể', - 'ễ' => 'Ễ', - 'ệ' => 'Ệ', - 'ỉ' => 'Ỉ', - 'ị' => 'Ị', - 'ọ' => 'Ọ', - 'ỏ' => 'Ỏ', - 'ố' => 'Ố', - 'ồ' => 'Ồ', - 'ổ' => 'Ổ', - 'ỗ' => 'Ỗ', - 'ộ' => 'Ộ', - 'ớ' => 'Ớ', - 'ờ' => 'Ờ', - 'ở' => 'Ở', - 'ỡ' => 'Ỡ', - 'ợ' => 'Ợ', - 'ụ' => 'Ụ', - 'ủ' => 'Ủ', - 'ứ' => 'Ứ', - 'ừ' => 'Ừ', - 'ử' => 'Ử', - 'ữ' => 'Ữ', - 'ự' => 'Ự', - 'ỳ' => 'Ỳ', - 'ỵ' => 'Ỵ', - 'ỷ' => 'Ỷ', - 'ỹ' => 'Ỹ', - 'ỻ' => 'Ỻ', - 'ỽ' => 'Ỽ', - 'ỿ' => 'Ỿ', - 'ἀ' => 'Ἀ', - 'ἁ' => 'Ἁ', - 'ἂ' => 'Ἂ', - 'ἃ' => 'Ἃ', - 'ἄ' => 'Ἄ', - 'ἅ' => 'Ἅ', - 'ἆ' => 'Ἆ', - 'ἇ' => 'Ἇ', - 'ἐ' => 'Ἐ', - 'ἑ' => 'Ἑ', - 'ἒ' => 'Ἒ', - 'ἓ' => 'Ἓ', - 'ἔ' => 'Ἔ', - 'ἕ' => 'Ἕ', - 'ἠ' => 'Ἠ', - 'ἡ' => 'Ἡ', - 'ἢ' => 'Ἢ', - 'ἣ' => 'Ἣ', - 'ἤ' => 'Ἤ', - 'ἥ' => 'Ἥ', - 'ἦ' => 'Ἦ', - 'ἧ' => 'Ἧ', - 'ἰ' => 'Ἰ', - 'ἱ' => 'Ἱ', - 'ἲ' => 'Ἲ', - 'ἳ' => 'Ἳ', - 'ἴ' => 'Ἴ', - 'ἵ' => 'Ἵ', - 'ἶ' => 'Ἶ', - 'ἷ' => 'Ἷ', - 'ὀ' => 'Ὀ', - 'ὁ' => 'Ὁ', - 'ὂ' => 'Ὂ', - 'ὃ' => 'Ὃ', - 'ὄ' => 'Ὄ', - 'ὅ' => 'Ὅ', - 'ὑ' => 'Ὑ', - 'ὓ' => 'Ὓ', - 'ὕ' => 'Ὕ', - 'ὗ' => 'Ὗ', - 'ὠ' => 'Ὠ', - 'ὡ' => 'Ὡ', - 'ὢ' => 'Ὢ', - 'ὣ' => 'Ὣ', - 'ὤ' => 'Ὤ', - 'ὥ' => 'Ὥ', - 'ὦ' => 'Ὦ', - 'ὧ' => 'Ὧ', - 'ὰ' => 'Ὰ', - 'ά' => 'Ά', - 'ὲ' => 'Ὲ', - 'έ' => 'Έ', - 'ὴ' => 'Ὴ', - 'ή' => 'Ή', - 'ὶ' => 'Ὶ', - 'ί' => 'Ί', - 'ὸ' => 'Ὸ', - 'ό' => 'Ό', - 'ὺ' => 'Ὺ', - 'ύ' => 'Ύ', - 'ὼ' => 'Ὼ', - 'ώ' => 'Ώ', - 'ᾀ' => 'ἈΙ', - 'ᾁ' => 'ἉΙ', - 'ᾂ' => 'ἊΙ', - 'ᾃ' => 'ἋΙ', - 'ᾄ' => 'ἌΙ', - 'ᾅ' => 'ἍΙ', - 'ᾆ' => 'ἎΙ', - 'ᾇ' => 'ἏΙ', - 'ᾐ' => 'ἨΙ', - 'ᾑ' => 'ἩΙ', - 'ᾒ' => 'ἪΙ', - 'ᾓ' => 'ἫΙ', - 'ᾔ' => 'ἬΙ', - 'ᾕ' => 'ἭΙ', - 'ᾖ' => 'ἮΙ', - 'ᾗ' => 'ἯΙ', - 'ᾠ' => 'ὨΙ', - 'ᾡ' => 'ὩΙ', - 'ᾢ' => 'ὪΙ', - 'ᾣ' => 'ὫΙ', - 'ᾤ' => 'ὬΙ', - 'ᾥ' => 'ὭΙ', - 'ᾦ' => 'ὮΙ', - 'ᾧ' => 'ὯΙ', - 'ᾰ' => 'Ᾰ', - 'ᾱ' => 'Ᾱ', - 'ᾳ' => 'ΑΙ', - 'ι' => 'Ι', - 'ῃ' => 'ΗΙ', - 'ῐ' => 'Ῐ', - 'ῑ' => 'Ῑ', - 'ῠ' => 'Ῠ', - 'ῡ' => 'Ῡ', - 'ῥ' => 'Ῥ', - 'ῳ' => 'ΩΙ', - 'ⅎ' => 'Ⅎ', - 'ⅰ' => 'Ⅰ', - 'ⅱ' => 'Ⅱ', - 'ⅲ' => 'Ⅲ', - 'ⅳ' => 'Ⅳ', - 'ⅴ' => 'Ⅴ', - 'ⅵ' => 'Ⅵ', - 'ⅶ' => 'Ⅶ', - 'ⅷ' => 'Ⅷ', - 'ⅸ' => 'Ⅸ', - 'ⅹ' => 'Ⅹ', - 'ⅺ' => 'Ⅺ', - 'ⅻ' => 'Ⅻ', - 'ⅼ' => 'Ⅼ', - 'ⅽ' => 'Ⅽ', - 'ⅾ' => 'Ⅾ', - 'ⅿ' => 'Ⅿ', - 'ↄ' => 'Ↄ', - 'ⓐ' => 'Ⓐ', - 'ⓑ' => 'Ⓑ', - 'ⓒ' => 'Ⓒ', - 'ⓓ' => 'Ⓓ', - 'ⓔ' => 'Ⓔ', - 'ⓕ' => 'Ⓕ', - 'ⓖ' => 'Ⓖ', - 'ⓗ' => 'Ⓗ', - 'ⓘ' => 'Ⓘ', - 'ⓙ' => 'Ⓙ', - 'ⓚ' => 'Ⓚ', - 'ⓛ' => 'Ⓛ', - 'ⓜ' => 'Ⓜ', - 'ⓝ' => 'Ⓝ', - 'ⓞ' => 'Ⓞ', - 'ⓟ' => 'Ⓟ', - 'ⓠ' => 'Ⓠ', - 'ⓡ' => 'Ⓡ', - 'ⓢ' => 'Ⓢ', - 'ⓣ' => 'Ⓣ', - 'ⓤ' => 'Ⓤ', - 'ⓥ' => 'Ⓥ', - 'ⓦ' => 'Ⓦ', - 'ⓧ' => 'Ⓧ', - 'ⓨ' => 'Ⓨ', - 'ⓩ' => 'Ⓩ', - 'ⰰ' => 'Ⰰ', - 'ⰱ' => 'Ⰱ', - 'ⰲ' => 'Ⰲ', - 'ⰳ' => 'Ⰳ', - 'ⰴ' => 'Ⰴ', - 'ⰵ' => 'Ⰵ', - 'ⰶ' => 'Ⰶ', - 'ⰷ' => 'Ⰷ', - 'ⰸ' => 'Ⰸ', - 'ⰹ' => 'Ⰹ', - 'ⰺ' => 'Ⰺ', - 'ⰻ' => 'Ⰻ', - 'ⰼ' => 'Ⰼ', - 'ⰽ' => 'Ⰽ', - 'ⰾ' => 'Ⰾ', - 'ⰿ' => 'Ⰿ', - 'ⱀ' => 'Ⱀ', - 'ⱁ' => 'Ⱁ', - 'ⱂ' => 'Ⱂ', - 'ⱃ' => 'Ⱃ', - 'ⱄ' => 'Ⱄ', - 'ⱅ' => 'Ⱅ', - 'ⱆ' => 'Ⱆ', - 'ⱇ' => 'Ⱇ', - 'ⱈ' => 'Ⱈ', - 'ⱉ' => 'Ⱉ', - 'ⱊ' => 'Ⱊ', - 'ⱋ' => 'Ⱋ', - 'ⱌ' => 'Ⱌ', - 'ⱍ' => 'Ⱍ', - 'ⱎ' => 'Ⱎ', - 'ⱏ' => 'Ⱏ', - 'ⱐ' => 'Ⱐ', - 'ⱑ' => 'Ⱑ', - 'ⱒ' => 'Ⱒ', - 'ⱓ' => 'Ⱓ', - 'ⱔ' => 'Ⱔ', - 'ⱕ' => 'Ⱕ', - 'ⱖ' => 'Ⱖ', - 'ⱗ' => 'Ⱗ', - 'ⱘ' => 'Ⱘ', - 'ⱙ' => 'Ⱙ', - 'ⱚ' => 'Ⱚ', - 'ⱛ' => 'Ⱛ', - 'ⱜ' => 'Ⱜ', - 'ⱝ' => 'Ⱝ', - 'ⱞ' => 'Ⱞ', - 'ⱡ' => 'Ⱡ', - 'ⱥ' => 'Ⱥ', - 'ⱦ' => 'Ⱦ', - 'ⱨ' => 'Ⱨ', - 'ⱪ' => 'Ⱪ', - 'ⱬ' => 'Ⱬ', - 'ⱳ' => 'Ⱳ', - 'ⱶ' => 'Ⱶ', - 'ⲁ' => 'Ⲁ', - 'ⲃ' => 'Ⲃ', - 'ⲅ' => 'Ⲅ', - 'ⲇ' => 'Ⲇ', - 'ⲉ' => 'Ⲉ', - 'ⲋ' => 'Ⲋ', - 'ⲍ' => 'Ⲍ', - 'ⲏ' => 'Ⲏ', - 'ⲑ' => 'Ⲑ', - 'ⲓ' => 'Ⲓ', - 'ⲕ' => 'Ⲕ', - 'ⲗ' => 'Ⲗ', - 'ⲙ' => 'Ⲙ', - 'ⲛ' => 'Ⲛ', - 'ⲝ' => 'Ⲝ', - 'ⲟ' => 'Ⲟ', - 'ⲡ' => 'Ⲡ', - 'ⲣ' => 'Ⲣ', - 'ⲥ' => 'Ⲥ', - 'ⲧ' => 'Ⲧ', - 'ⲩ' => 'Ⲩ', - 'ⲫ' => 'Ⲫ', - 'ⲭ' => 'Ⲭ', - 'ⲯ' => 'Ⲯ', - 'ⲱ' => 'Ⲱ', - 'ⲳ' => 'Ⲳ', - 'ⲵ' => 'Ⲵ', - 'ⲷ' => 'Ⲷ', - 'ⲹ' => 'Ⲹ', - 'ⲻ' => 'Ⲻ', - 'ⲽ' => 'Ⲽ', - 'ⲿ' => 'Ⲿ', - 'ⳁ' => 'Ⳁ', - 'ⳃ' => 'Ⳃ', - 'ⳅ' => 'Ⳅ', - 'ⳇ' => 'Ⳇ', - 'ⳉ' => 'Ⳉ', - 'ⳋ' => 'Ⳋ', - 'ⳍ' => 'Ⳍ', - 'ⳏ' => 'Ⳏ', - 'ⳑ' => 'Ⳑ', - 'ⳓ' => 'Ⳓ', - 'ⳕ' => 'Ⳕ', - 'ⳗ' => 'Ⳗ', - 'ⳙ' => 'Ⳙ', - 'ⳛ' => 'Ⳛ', - 'ⳝ' => 'Ⳝ', - 'ⳟ' => 'Ⳟ', - 'ⳡ' => 'Ⳡ', - 'ⳣ' => 'Ⳣ', - 'ⳬ' => 'Ⳬ', - 'ⳮ' => 'Ⳮ', - 'ⳳ' => 'Ⳳ', - 'ⴀ' => 'Ⴀ', - 'ⴁ' => 'Ⴁ', - 'ⴂ' => 'Ⴂ', - 'ⴃ' => 'Ⴃ', - 'ⴄ' => 'Ⴄ', - 'ⴅ' => 'Ⴅ', - 'ⴆ' => 'Ⴆ', - 'ⴇ' => 'Ⴇ', - 'ⴈ' => 'Ⴈ', - 'ⴉ' => 'Ⴉ', - 'ⴊ' => 'Ⴊ', - 'ⴋ' => 'Ⴋ', - 'ⴌ' => 'Ⴌ', - 'ⴍ' => 'Ⴍ', - 'ⴎ' => 'Ⴎ', - 'ⴏ' => 'Ⴏ', - 'ⴐ' => 'Ⴐ', - 'ⴑ' => 'Ⴑ', - 'ⴒ' => 'Ⴒ', - 'ⴓ' => 'Ⴓ', - 'ⴔ' => 'Ⴔ', - 'ⴕ' => 'Ⴕ', - 'ⴖ' => 'Ⴖ', - 'ⴗ' => 'Ⴗ', - 'ⴘ' => 'Ⴘ', - 'ⴙ' => 'Ⴙ', - 'ⴚ' => 'Ⴚ', - 'ⴛ' => 'Ⴛ', - 'ⴜ' => 'Ⴜ', - 'ⴝ' => 'Ⴝ', - 'ⴞ' => 'Ⴞ', - 'ⴟ' => 'Ⴟ', - 'ⴠ' => 'Ⴠ', - 'ⴡ' => 'Ⴡ', - 'ⴢ' => 'Ⴢ', - 'ⴣ' => 'Ⴣ', - 'ⴤ' => 'Ⴤ', - 'ⴥ' => 'Ⴥ', - 'ⴧ' => 'Ⴧ', - 'ⴭ' => 'Ⴭ', - 'ꙁ' => 'Ꙁ', - 'ꙃ' => 'Ꙃ', - 'ꙅ' => 'Ꙅ', - 'ꙇ' => 'Ꙇ', - 'ꙉ' => 'Ꙉ', - 'ꙋ' => 'Ꙋ', - 'ꙍ' => 'Ꙍ', - 'ꙏ' => 'Ꙏ', - 'ꙑ' => 'Ꙑ', - 'ꙓ' => 'Ꙓ', - 'ꙕ' => 'Ꙕ', - 'ꙗ' => 'Ꙗ', - 'ꙙ' => 'Ꙙ', - 'ꙛ' => 'Ꙛ', - 'ꙝ' => 'Ꙝ', - 'ꙟ' => 'Ꙟ', - 'ꙡ' => 'Ꙡ', - 'ꙣ' => 'Ꙣ', - 'ꙥ' => 'Ꙥ', - 'ꙧ' => 'Ꙧ', - 'ꙩ' => 'Ꙩ', - 'ꙫ' => 'Ꙫ', - 'ꙭ' => 'Ꙭ', - 'ꚁ' => 'Ꚁ', - 'ꚃ' => 'Ꚃ', - 'ꚅ' => 'Ꚅ', - 'ꚇ' => 'Ꚇ', - 'ꚉ' => 'Ꚉ', - 'ꚋ' => 'Ꚋ', - 'ꚍ' => 'Ꚍ', - 'ꚏ' => 'Ꚏ', - 'ꚑ' => 'Ꚑ', - 'ꚓ' => 'Ꚓ', - 'ꚕ' => 'Ꚕ', - 'ꚗ' => 'Ꚗ', - 'ꚙ' => 'Ꚙ', - 'ꚛ' => 'Ꚛ', - 'ꜣ' => 'Ꜣ', - 'ꜥ' => 'Ꜥ', - 'ꜧ' => 'Ꜧ', - 'ꜩ' => 'Ꜩ', - 'ꜫ' => 'Ꜫ', - 'ꜭ' => 'Ꜭ', - 'ꜯ' => 'Ꜯ', - 'ꜳ' => 'Ꜳ', - 'ꜵ' => 'Ꜵ', - 'ꜷ' => 'Ꜷ', - 'ꜹ' => 'Ꜹ', - 'ꜻ' => 'Ꜻ', - 'ꜽ' => 'Ꜽ', - 'ꜿ' => 'Ꜿ', - 'ꝁ' => 'Ꝁ', - 'ꝃ' => 'Ꝃ', - 'ꝅ' => 'Ꝅ', - 'ꝇ' => 'Ꝇ', - 'ꝉ' => 'Ꝉ', - 'ꝋ' => 'Ꝋ', - 'ꝍ' => 'Ꝍ', - 'ꝏ' => 'Ꝏ', - 'ꝑ' => 'Ꝑ', - 'ꝓ' => 'Ꝓ', - 'ꝕ' => 'Ꝕ', - 'ꝗ' => 'Ꝗ', - 'ꝙ' => 'Ꝙ', - 'ꝛ' => 'Ꝛ', - 'ꝝ' => 'Ꝝ', - 'ꝟ' => 'Ꝟ', - 'ꝡ' => 'Ꝡ', - 'ꝣ' => 'Ꝣ', - 'ꝥ' => 'Ꝥ', - 'ꝧ' => 'Ꝧ', - 'ꝩ' => 'Ꝩ', - 'ꝫ' => 'Ꝫ', - 'ꝭ' => 'Ꝭ', - 'ꝯ' => 'Ꝯ', - 'ꝺ' => 'Ꝺ', - 'ꝼ' => 'Ꝼ', - 'ꝿ' => 'Ꝿ', - 'ꞁ' => 'Ꞁ', - 'ꞃ' => 'Ꞃ', - 'ꞅ' => 'Ꞅ', - 'ꞇ' => 'Ꞇ', - 'ꞌ' => 'Ꞌ', - 'ꞑ' => 'Ꞑ', - 'ꞓ' => 'Ꞓ', - 'ꞔ' => 'Ꞔ', - 'ꞗ' => 'Ꞗ', - 'ꞙ' => 'Ꞙ', - 'ꞛ' => 'Ꞛ', - 'ꞝ' => 'Ꞝ', - 'ꞟ' => 'Ꞟ', - 'ꞡ' => 'Ꞡ', - 'ꞣ' => 'Ꞣ', - 'ꞥ' => 'Ꞥ', - 'ꞧ' => 'Ꞧ', - 'ꞩ' => 'Ꞩ', - 'ꞵ' => 'Ꞵ', - 'ꞷ' => 'Ꞷ', - 'ꞹ' => 'Ꞹ', - 'ꞻ' => 'Ꞻ', - 'ꞽ' => 'Ꞽ', - 'ꞿ' => 'Ꞿ', - 'ꟃ' => 'Ꟃ', - 'ꟈ' => 'Ꟈ', - 'ꟊ' => 'Ꟊ', - 'ꟶ' => 'Ꟶ', - 'ꭓ' => 'Ꭓ', - 'ꭰ' => 'Ꭰ', - 'ꭱ' => 'Ꭱ', - 'ꭲ' => 'Ꭲ', - 'ꭳ' => 'Ꭳ', - 'ꭴ' => 'Ꭴ', - 'ꭵ' => 'Ꭵ', - 'ꭶ' => 'Ꭶ', - 'ꭷ' => 'Ꭷ', - 'ꭸ' => 'Ꭸ', - 'ꭹ' => 'Ꭹ', - 'ꭺ' => 'Ꭺ', - 'ꭻ' => 'Ꭻ', - 'ꭼ' => 'Ꭼ', - 'ꭽ' => 'Ꭽ', - 'ꭾ' => 'Ꭾ', - 'ꭿ' => 'Ꭿ', - 'ꮀ' => 'Ꮀ', - 'ꮁ' => 'Ꮁ', - 'ꮂ' => 'Ꮂ', - 'ꮃ' => 'Ꮃ', - 'ꮄ' => 'Ꮄ', - 'ꮅ' => 'Ꮅ', - 'ꮆ' => 'Ꮆ', - 'ꮇ' => 'Ꮇ', - 'ꮈ' => 'Ꮈ', - 'ꮉ' => 'Ꮉ', - 'ꮊ' => 'Ꮊ', - 'ꮋ' => 'Ꮋ', - 'ꮌ' => 'Ꮌ', - 'ꮍ' => 'Ꮍ', - 'ꮎ' => 'Ꮎ', - 'ꮏ' => 'Ꮏ', - 'ꮐ' => 'Ꮐ', - 'ꮑ' => 'Ꮑ', - 'ꮒ' => 'Ꮒ', - 'ꮓ' => 'Ꮓ', - 'ꮔ' => 'Ꮔ', - 'ꮕ' => 'Ꮕ', - 'ꮖ' => 'Ꮖ', - 'ꮗ' => 'Ꮗ', - 'ꮘ' => 'Ꮘ', - 'ꮙ' => 'Ꮙ', - 'ꮚ' => 'Ꮚ', - 'ꮛ' => 'Ꮛ', - 'ꮜ' => 'Ꮜ', - 'ꮝ' => 'Ꮝ', - 'ꮞ' => 'Ꮞ', - 'ꮟ' => 'Ꮟ', - 'ꮠ' => 'Ꮠ', - 'ꮡ' => 'Ꮡ', - 'ꮢ' => 'Ꮢ', - 'ꮣ' => 'Ꮣ', - 'ꮤ' => 'Ꮤ', - 'ꮥ' => 'Ꮥ', - 'ꮦ' => 'Ꮦ', - 'ꮧ' => 'Ꮧ', - 'ꮨ' => 'Ꮨ', - 'ꮩ' => 'Ꮩ', - 'ꮪ' => 'Ꮪ', - 'ꮫ' => 'Ꮫ', - 'ꮬ' => 'Ꮬ', - 'ꮭ' => 'Ꮭ', - 'ꮮ' => 'Ꮮ', - 'ꮯ' => 'Ꮯ', - 'ꮰ' => 'Ꮰ', - 'ꮱ' => 'Ꮱ', - 'ꮲ' => 'Ꮲ', - 'ꮳ' => 'Ꮳ', - 'ꮴ' => 'Ꮴ', - 'ꮵ' => 'Ꮵ', - 'ꮶ' => 'Ꮶ', - 'ꮷ' => 'Ꮷ', - 'ꮸ' => 'Ꮸ', - 'ꮹ' => 'Ꮹ', - 'ꮺ' => 'Ꮺ', - 'ꮻ' => 'Ꮻ', - 'ꮼ' => 'Ꮼ', - 'ꮽ' => 'Ꮽ', - 'ꮾ' => 'Ꮾ', - 'ꮿ' => 'Ꮿ', - 'a' => 'A', - 'b' => 'B', - 'c' => 'C', - 'd' => 'D', - 'e' => 'E', - 'f' => 'F', - 'g' => 'G', - 'h' => 'H', - 'i' => 'I', - 'j' => 'J', - 'k' => 'K', - 'l' => 'L', - 'm' => 'M', - 'n' => 'N', - 'o' => 'O', - 'p' => 'P', - 'q' => 'Q', - 'r' => 'R', - 's' => 'S', - 't' => 'T', - 'u' => 'U', - 'v' => 'V', - 'w' => 'W', - 'x' => 'X', - 'y' => 'Y', - 'z' => 'Z', - '𐐨' => '𐐀', - '𐐩' => '𐐁', - '𐐪' => '𐐂', - '𐐫' => '𐐃', - '𐐬' => '𐐄', - '𐐭' => '𐐅', - '𐐮' => '𐐆', - '𐐯' => '𐐇', - '𐐰' => '𐐈', - '𐐱' => '𐐉', - '𐐲' => '𐐊', - '𐐳' => '𐐋', - '𐐴' => '𐐌', - '𐐵' => '𐐍', - '𐐶' => '𐐎', - '𐐷' => '𐐏', - '𐐸' => '𐐐', - '𐐹' => '𐐑', - '𐐺' => '𐐒', - '𐐻' => '𐐓', - '𐐼' => '𐐔', - '𐐽' => '𐐕', - '𐐾' => '𐐖', - '𐐿' => '𐐗', - '𐑀' => '𐐘', - '𐑁' => '𐐙', - '𐑂' => '𐐚', - '𐑃' => '𐐛', - '𐑄' => '𐐜', - '𐑅' => '𐐝', - '𐑆' => '𐐞', - '𐑇' => '𐐟', - '𐑈' => '𐐠', - '𐑉' => '𐐡', - '𐑊' => '𐐢', - '𐑋' => '𐐣', - '𐑌' => '𐐤', - '𐑍' => '𐐥', - '𐑎' => '𐐦', - '𐑏' => '𐐧', - '𐓘' => '𐒰', - '𐓙' => '𐒱', - '𐓚' => '𐒲', - '𐓛' => '𐒳', - '𐓜' => '𐒴', - '𐓝' => '𐒵', - '𐓞' => '𐒶', - '𐓟' => '𐒷', - '𐓠' => '𐒸', - '𐓡' => '𐒹', - '𐓢' => '𐒺', - '𐓣' => '𐒻', - '𐓤' => '𐒼', - '𐓥' => '𐒽', - '𐓦' => '𐒾', - '𐓧' => '𐒿', - '𐓨' => '𐓀', - '𐓩' => '𐓁', - '𐓪' => '𐓂', - '𐓫' => '𐓃', - '𐓬' => '𐓄', - '𐓭' => '𐓅', - '𐓮' => '𐓆', - '𐓯' => '𐓇', - '𐓰' => '𐓈', - '𐓱' => '𐓉', - '𐓲' => '𐓊', - '𐓳' => '𐓋', - '𐓴' => '𐓌', - '𐓵' => '𐓍', - '𐓶' => '𐓎', - '𐓷' => '𐓏', - '𐓸' => '𐓐', - '𐓹' => '𐓑', - '𐓺' => '𐓒', - '𐓻' => '𐓓', - '𐳀' => '𐲀', - '𐳁' => '𐲁', - '𐳂' => '𐲂', - '𐳃' => '𐲃', - '𐳄' => '𐲄', - '𐳅' => '𐲅', - '𐳆' => '𐲆', - '𐳇' => '𐲇', - '𐳈' => '𐲈', - '𐳉' => '𐲉', - '𐳊' => '𐲊', - '𐳋' => '𐲋', - '𐳌' => '𐲌', - '𐳍' => '𐲍', - '𐳎' => '𐲎', - '𐳏' => '𐲏', - '𐳐' => '𐲐', - '𐳑' => '𐲑', - '𐳒' => '𐲒', - '𐳓' => '𐲓', - '𐳔' => '𐲔', - '𐳕' => '𐲕', - '𐳖' => '𐲖', - '𐳗' => '𐲗', - '𐳘' => '𐲘', - '𐳙' => '𐲙', - '𐳚' => '𐲚', - '𐳛' => '𐲛', - '𐳜' => '𐲜', - '𐳝' => '𐲝', - '𐳞' => '𐲞', - '𐳟' => '𐲟', - '𐳠' => '𐲠', - '𐳡' => '𐲡', - '𐳢' => '𐲢', - '𐳣' => '𐲣', - '𐳤' => '𐲤', - '𐳥' => '𐲥', - '𐳦' => '𐲦', - '𐳧' => '𐲧', - '𐳨' => '𐲨', - '𐳩' => '𐲩', - '𐳪' => '𐲪', - '𐳫' => '𐲫', - '𐳬' => '𐲬', - '𐳭' => '𐲭', - '𐳮' => '𐲮', - '𐳯' => '𐲯', - '𐳰' => '𐲰', - '𐳱' => '𐲱', - '𐳲' => '𐲲', - '𑣀' => '𑢠', - '𑣁' => '𑢡', - '𑣂' => '𑢢', - '𑣃' => '𑢣', - '𑣄' => '𑢤', - '𑣅' => '𑢥', - '𑣆' => '𑢦', - '𑣇' => '𑢧', - '𑣈' => '𑢨', - '𑣉' => '𑢩', - '𑣊' => '𑢪', - '𑣋' => '𑢫', - '𑣌' => '𑢬', - '𑣍' => '𑢭', - '𑣎' => '𑢮', - '𑣏' => '𑢯', - '𑣐' => '𑢰', - '𑣑' => '𑢱', - '𑣒' => '𑢲', - '𑣓' => '𑢳', - '𑣔' => '𑢴', - '𑣕' => '𑢵', - '𑣖' => '𑢶', - '𑣗' => '𑢷', - '𑣘' => '𑢸', - '𑣙' => '𑢹', - '𑣚' => '𑢺', - '𑣛' => '𑢻', - '𑣜' => '𑢼', - '𑣝' => '𑢽', - '𑣞' => '𑢾', - '𑣟' => '𑢿', - '𖹠' => '𖹀', - '𖹡' => '𖹁', - '𖹢' => '𖹂', - '𖹣' => '𖹃', - '𖹤' => '𖹄', - '𖹥' => '𖹅', - '𖹦' => '𖹆', - '𖹧' => '𖹇', - '𖹨' => '𖹈', - '𖹩' => '𖹉', - '𖹪' => '𖹊', - '𖹫' => '𖹋', - '𖹬' => '𖹌', - '𖹭' => '𖹍', - '𖹮' => '𖹎', - '𖹯' => '𖹏', - '𖹰' => '𖹐', - '𖹱' => '𖹑', - '𖹲' => '𖹒', - '𖹳' => '𖹓', - '𖹴' => '𖹔', - '𖹵' => '𖹕', - '𖹶' => '𖹖', - '𖹷' => '𖹗', - '𖹸' => '𖹘', - '𖹹' => '𖹙', - '𖹺' => '𖹚', - '𖹻' => '𖹛', - '𖹼' => '𖹜', - '𖹽' => '𖹝', - '𖹾' => '𖹞', - '𖹿' => '𖹟', - '𞤢' => '𞤀', - '𞤣' => '𞤁', - '𞤤' => '𞤂', - '𞤥' => '𞤃', - '𞤦' => '𞤄', - '𞤧' => '𞤅', - '𞤨' => '𞤆', - '𞤩' => '𞤇', - '𞤪' => '𞤈', - '𞤫' => '𞤉', - '𞤬' => '𞤊', - '𞤭' => '𞤋', - '𞤮' => '𞤌', - '𞤯' => '𞤍', - '𞤰' => '𞤎', - '𞤱' => '𞤏', - '𞤲' => '𞤐', - '𞤳' => '𞤑', - '𞤴' => '𞤒', - '𞤵' => '𞤓', - '𞤶' => '𞤔', - '𞤷' => '𞤕', - '𞤸' => '𞤖', - '𞤹' => '𞤗', - '𞤺' => '𞤘', - '𞤻' => '𞤙', - '𞤼' => '𞤚', - '𞤽' => '𞤛', - '𞤾' => '𞤜', - '𞤿' => '𞤝', - '𞥀' => '𞤞', - '𞥁' => '𞤟', - '𞥂' => '𞤠', - '𞥃' => '𞤡', - 'ß' => 'SS', - 'ff' => 'FF', - 'fi' => 'FI', - 'fl' => 'FL', - 'ffi' => 'FFI', - 'ffl' => 'FFL', - 'ſt' => 'ST', - 'st' => 'ST', - 'և' => 'ԵՒ', - 'ﬓ' => 'ՄՆ', - 'ﬔ' => 'ՄԵ', - 'ﬕ' => 'ՄԻ', - 'ﬖ' => 'ՎՆ', - 'ﬗ' => 'ՄԽ', - 'ʼn' => 'ʼN', - 'ΐ' => 'Ϊ́', - 'ΰ' => 'Ϋ́', - 'ǰ' => 'J̌', - 'ẖ' => 'H̱', - 'ẗ' => 'T̈', - 'ẘ' => 'W̊', - 'ẙ' => 'Y̊', - 'ẚ' => 'Aʾ', - 'ὐ' => 'Υ̓', - 'ὒ' => 'Υ̓̀', - 'ὔ' => 'Υ̓́', - 'ὖ' => 'Υ̓͂', - 'ᾶ' => 'Α͂', - 'ῆ' => 'Η͂', - 'ῒ' => 'Ϊ̀', - 'ΐ' => 'Ϊ́', - 'ῖ' => 'Ι͂', - 'ῗ' => 'Ϊ͂', - 'ῢ' => 'Ϋ̀', - 'ΰ' => 'Ϋ́', - 'ῤ' => 'Ρ̓', - 'ῦ' => 'Υ͂', - 'ῧ' => 'Ϋ͂', - 'ῶ' => 'Ω͂', - 'ᾈ' => 'ἈΙ', - 'ᾉ' => 'ἉΙ', - 'ᾊ' => 'ἊΙ', - 'ᾋ' => 'ἋΙ', - 'ᾌ' => 'ἌΙ', - 'ᾍ' => 'ἍΙ', - 'ᾎ' => 'ἎΙ', - 'ᾏ' => 'ἏΙ', - 'ᾘ' => 'ἨΙ', - 'ᾙ' => 'ἩΙ', - 'ᾚ' => 'ἪΙ', - 'ᾛ' => 'ἫΙ', - 'ᾜ' => 'ἬΙ', - 'ᾝ' => 'ἭΙ', - 'ᾞ' => 'ἮΙ', - 'ᾟ' => 'ἯΙ', - 'ᾨ' => 'ὨΙ', - 'ᾩ' => 'ὩΙ', - 'ᾪ' => 'ὪΙ', - 'ᾫ' => 'ὫΙ', - 'ᾬ' => 'ὬΙ', - 'ᾭ' => 'ὭΙ', - 'ᾮ' => 'ὮΙ', - 'ᾯ' => 'ὯΙ', - 'ᾼ' => 'ΑΙ', - 'ῌ' => 'ΗΙ', - 'ῼ' => 'ΩΙ', - 'ᾲ' => 'ᾺΙ', - 'ᾴ' => 'ΆΙ', - 'ῂ' => 'ῊΙ', - 'ῄ' => 'ΉΙ', - 'ῲ' => 'ῺΙ', - 'ῴ' => 'ΏΙ', - 'ᾷ' => 'Α͂Ι', - 'ῇ' => 'Η͂Ι', - 'ῷ' => 'Ω͂Ι', -); diff --git a/digital_doctor/vendor/symfony/polyfill-mbstring/bootstrap.php b/digital_doctor/vendor/symfony/polyfill-mbstring/bootstrap.php deleted file mode 100644 index 6e4b5fc..0000000 --- a/digital_doctor/vendor/symfony/polyfill-mbstring/bootstrap.php +++ /dev/null @@ -1,159 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use Symfony\Polyfill\Mbstring as p; - -if (\PHP_VERSION_ID >= 80000) { - return require __DIR__.'/bootstrap80.php'; -} - -if (!function_exists('mb_convert_encoding')) { - function mb_convert_encoding($string, $to_encoding, $from_encoding = null) { return p\Mbstring::mb_convert_encoding($string, $to_encoding, $from_encoding); } -} -if (!function_exists('mb_decode_mimeheader')) { - function mb_decode_mimeheader($string) { return p\Mbstring::mb_decode_mimeheader($string); } -} -if (!function_exists('mb_encode_mimeheader')) { - function mb_encode_mimeheader($string, $charset = null, $transfer_encoding = null, $newline = "\r\n", $indent = 0) { return p\Mbstring::mb_encode_mimeheader($string, $charset, $transfer_encoding, $newline, $indent); } -} -if (!function_exists('mb_decode_numericentity')) { - function mb_decode_numericentity($string, $map, $encoding = null) { return p\Mbstring::mb_decode_numericentity($string, $map, $encoding); } -} -if (!function_exists('mb_encode_numericentity')) { - function mb_encode_numericentity($string, $map, $encoding = null, $hex = false) { return p\Mbstring::mb_encode_numericentity($string, $map, $encoding, $hex); } -} -if (!function_exists('mb_convert_case')) { - function mb_convert_case($string, $mode, $encoding = null) { return p\Mbstring::mb_convert_case($string, $mode, $encoding); } -} -if (!function_exists('mb_internal_encoding')) { - function mb_internal_encoding($encoding = null) { return p\Mbstring::mb_internal_encoding($encoding); } -} -if (!function_exists('mb_language')) { - function mb_language($language = null) { return p\Mbstring::mb_language($language); } -} -if (!function_exists('mb_list_encodings')) { - function mb_list_encodings() { return p\Mbstring::mb_list_encodings(); } -} -if (!function_exists('mb_encoding_aliases')) { - function mb_encoding_aliases($encoding) { return p\Mbstring::mb_encoding_aliases($encoding); } -} -if (!function_exists('mb_check_encoding')) { - function mb_check_encoding($value = null, $encoding = null) { return p\Mbstring::mb_check_encoding($value, $encoding); } -} -if (!function_exists('mb_detect_encoding')) { - function mb_detect_encoding($string, $encodings = null, $strict = false) { return p\Mbstring::mb_detect_encoding($string, $encodings, $strict); } -} -if (!function_exists('mb_detect_order')) { - function mb_detect_order($encoding = null) { return p\Mbstring::mb_detect_order($encoding); } -} -if (!function_exists('mb_parse_str')) { - function mb_parse_str($string, &$result = []) { parse_str($string, $result); return (bool) $result; } -} -if (!function_exists('mb_strlen')) { - function mb_strlen($string, $encoding = null) { return p\Mbstring::mb_strlen($string, $encoding); } -} -if (!function_exists('mb_strpos')) { - function mb_strpos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strpos($haystack, $needle, $offset, $encoding); } -} -if (!function_exists('mb_strtolower')) { - function mb_strtolower($string, $encoding = null) { return p\Mbstring::mb_strtolower($string, $encoding); } -} -if (!function_exists('mb_strtoupper')) { - function mb_strtoupper($string, $encoding = null) { return p\Mbstring::mb_strtoupper($string, $encoding); } -} -if (!function_exists('mb_substitute_character')) { - function mb_substitute_character($substitute_character = null) { return p\Mbstring::mb_substitute_character($substitute_character); } -} -if (!function_exists('mb_substr')) { - function mb_substr($string, $start, $length = 2147483647, $encoding = null) { return p\Mbstring::mb_substr($string, $start, $length, $encoding); } -} -if (!function_exists('mb_stripos')) { - function mb_stripos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_stripos($haystack, $needle, $offset, $encoding); } -} -if (!function_exists('mb_stristr')) { - function mb_stristr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_stristr($haystack, $needle, $before_needle, $encoding); } -} -if (!function_exists('mb_strrchr')) { - function mb_strrchr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strrchr($haystack, $needle, $before_needle, $encoding); } -} -if (!function_exists('mb_strrichr')) { - function mb_strrichr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strrichr($haystack, $needle, $before_needle, $encoding); } -} -if (!function_exists('mb_strripos')) { - function mb_strripos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strripos($haystack, $needle, $offset, $encoding); } -} -if (!function_exists('mb_strrpos')) { - function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strrpos($haystack, $needle, $offset, $encoding); } -} -if (!function_exists('mb_strstr')) { - function mb_strstr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strstr($haystack, $needle, $before_needle, $encoding); } -} -if (!function_exists('mb_get_info')) { - function mb_get_info($type = 'all') { return p\Mbstring::mb_get_info($type); } -} -if (!function_exists('mb_http_output')) { - function mb_http_output($encoding = null) { return p\Mbstring::mb_http_output($encoding); } -} -if (!function_exists('mb_strwidth')) { - function mb_strwidth($string, $encoding = null) { return p\Mbstring::mb_strwidth($string, $encoding); } -} -if (!function_exists('mb_substr_count')) { - function mb_substr_count($haystack, $needle, $encoding = null) { return p\Mbstring::mb_substr_count($haystack, $needle, $encoding); } -} -if (!function_exists('mb_output_handler')) { - function mb_output_handler($string, $status) { return p\Mbstring::mb_output_handler($string, $status); } -} -if (!function_exists('mb_http_input')) { - function mb_http_input($type = null) { return p\Mbstring::mb_http_input($type); } -} - -if (!function_exists('mb_convert_variables')) { - function mb_convert_variables($to_encoding, $from_encoding, &...$vars) { return p\Mbstring::mb_convert_variables($to_encoding, $from_encoding, ...$vars); } -} - -if (!function_exists('mb_ord')) { - function mb_ord($string, $encoding = null) { return p\Mbstring::mb_ord($string, $encoding); } -} -if (!function_exists('mb_chr')) { - function mb_chr($codepoint, $encoding = null) { return p\Mbstring::mb_chr($codepoint, $encoding); } -} -if (!function_exists('mb_scrub')) { - function mb_scrub($string, $encoding = null) { $encoding = null === $encoding ? mb_internal_encoding() : $encoding; return mb_convert_encoding($string, $encoding, $encoding); } -} -if (!function_exists('mb_str_split')) { - function mb_str_split($string, $length = 1, $encoding = null) { return p\Mbstring::mb_str_split($string, $length, $encoding); } -} - -if (!function_exists('mb_str_pad')) { - function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = STR_PAD_RIGHT, ?string $encoding = null): string { return p\Mbstring::mb_str_pad($string, $length, $pad_string, $pad_type, $encoding); } -} - -if (!function_exists('mb_ucfirst')) { - function mb_ucfirst(string $string, ?string $encoding = null): string { return p\Mbstring::mb_ucfirst($string, $encoding); } -} - -if (!function_exists('mb_lcfirst')) { - function mb_lcfirst(string $string, ?string $encoding = null): string { return p\Mbstring::mb_lcfirst($string, $encoding); } -} - -if (extension_loaded('mbstring')) { - return; -} - -if (!defined('MB_CASE_UPPER')) { - define('MB_CASE_UPPER', 0); -} -if (!defined('MB_CASE_LOWER')) { - define('MB_CASE_LOWER', 1); -} -if (!defined('MB_CASE_TITLE')) { - define('MB_CASE_TITLE', 2); -} diff --git a/digital_doctor/vendor/symfony/polyfill-mbstring/bootstrap80.php b/digital_doctor/vendor/symfony/polyfill-mbstring/bootstrap80.php deleted file mode 100644 index ec2ae42..0000000 --- a/digital_doctor/vendor/symfony/polyfill-mbstring/bootstrap80.php +++ /dev/null @@ -1,155 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use Symfony\Polyfill\Mbstring as p; - -if (!function_exists('mb_convert_encoding')) { - function mb_convert_encoding(array|string|null $string, ?string $to_encoding, array|string|null $from_encoding = null): array|string|false { return p\Mbstring::mb_convert_encoding($string ?? '', (string) $to_encoding, $from_encoding); } -} -if (!function_exists('mb_decode_mimeheader')) { - function mb_decode_mimeheader(?string $string): string { return p\Mbstring::mb_decode_mimeheader((string) $string); } -} -if (!function_exists('mb_encode_mimeheader')) { - function mb_encode_mimeheader(?string $string, ?string $charset = null, ?string $transfer_encoding = null, ?string $newline = "\r\n", ?int $indent = 0): string { return p\Mbstring::mb_encode_mimeheader((string) $string, $charset, $transfer_encoding, (string) $newline, (int) $indent); } -} -if (!function_exists('mb_decode_numericentity')) { - function mb_decode_numericentity(?string $string, array $map, ?string $encoding = null): string { return p\Mbstring::mb_decode_numericentity((string) $string, $map, $encoding); } -} -if (!function_exists('mb_encode_numericentity')) { - function mb_encode_numericentity(?string $string, array $map, ?string $encoding = null, ?bool $hex = false): string { return p\Mbstring::mb_encode_numericentity((string) $string, $map, $encoding, (bool) $hex); } -} -if (!function_exists('mb_convert_case')) { - function mb_convert_case(?string $string, ?int $mode, ?string $encoding = null): string { return p\Mbstring::mb_convert_case((string) $string, (int) $mode, $encoding); } -} -if (!function_exists('mb_internal_encoding')) { - function mb_internal_encoding(?string $encoding = null): string|bool { return p\Mbstring::mb_internal_encoding($encoding); } -} -if (!function_exists('mb_language')) { - function mb_language(?string $language = null): string|bool { return p\Mbstring::mb_language($language); } -} -if (!function_exists('mb_list_encodings')) { - function mb_list_encodings(): array { return p\Mbstring::mb_list_encodings(); } -} -if (!function_exists('mb_encoding_aliases')) { - function mb_encoding_aliases(?string $encoding): array { return p\Mbstring::mb_encoding_aliases((string) $encoding); } -} -if (!function_exists('mb_check_encoding')) { - function mb_check_encoding(array|string|null $value = null, ?string $encoding = null): bool { return p\Mbstring::mb_check_encoding($value, $encoding); } -} -if (!function_exists('mb_detect_encoding')) { - function mb_detect_encoding(?string $string, array|string|null $encodings = null, ?bool $strict = false): string|false { return p\Mbstring::mb_detect_encoding((string) $string, $encodings, (bool) $strict); } -} -if (!function_exists('mb_detect_order')) { - function mb_detect_order(array|string|null $encoding = null): array|bool { return p\Mbstring::mb_detect_order($encoding); } -} -if (!function_exists('mb_parse_str')) { - function mb_parse_str(?string $string, &$result = []): bool { parse_str((string) $string, $result); return (bool) $result; } -} -if (!function_exists('mb_strlen')) { - function mb_strlen(?string $string, ?string $encoding = null): int { return p\Mbstring::mb_strlen((string) $string, $encoding); } -} -if (!function_exists('mb_strpos')) { - function mb_strpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strpos((string) $haystack, (string) $needle, (int) $offset, $encoding); } -} -if (!function_exists('mb_strtolower')) { - function mb_strtolower(?string $string, ?string $encoding = null): string { return p\Mbstring::mb_strtolower((string) $string, $encoding); } -} -if (!function_exists('mb_strtoupper')) { - function mb_strtoupper(?string $string, ?string $encoding = null): string { return p\Mbstring::mb_strtoupper((string) $string, $encoding); } -} -if (!function_exists('mb_substitute_character')) { - function mb_substitute_character(string|int|null $substitute_character = null): string|int|bool { return p\Mbstring::mb_substitute_character($substitute_character); } -} -if (!function_exists('mb_substr')) { - function mb_substr(?string $string, ?int $start, ?int $length = null, ?string $encoding = null): string { return p\Mbstring::mb_substr((string) $string, (int) $start, $length, $encoding); } -} -if (!function_exists('mb_stripos')) { - function mb_stripos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_stripos((string) $haystack, (string) $needle, (int) $offset, $encoding); } -} -if (!function_exists('mb_stristr')) { - function mb_stristr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_stristr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); } -} -if (!function_exists('mb_strrchr')) { - function mb_strrchr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strrchr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); } -} -if (!function_exists('mb_strrichr')) { - function mb_strrichr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strrichr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); } -} -if (!function_exists('mb_strripos')) { - function mb_strripos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strripos((string) $haystack, (string) $needle, (int) $offset, $encoding); } -} -if (!function_exists('mb_strrpos')) { - function mb_strrpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strrpos((string) $haystack, (string) $needle, (int) $offset, $encoding); } -} -if (!function_exists('mb_strstr')) { - function mb_strstr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strstr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); } -} -if (!function_exists('mb_get_info')) { - function mb_get_info(?string $type = 'all'): array|string|int|false { return p\Mbstring::mb_get_info((string) $type); } -} -if (!function_exists('mb_http_output')) { - function mb_http_output(?string $encoding = null): string|bool { return p\Mbstring::mb_http_output($encoding); } -} -if (!function_exists('mb_strwidth')) { - function mb_strwidth(?string $string, ?string $encoding = null): int { return p\Mbstring::mb_strwidth((string) $string, $encoding); } -} -if (!function_exists('mb_substr_count')) { - function mb_substr_count(?string $haystack, ?string $needle, ?string $encoding = null): int { return p\Mbstring::mb_substr_count((string) $haystack, (string) $needle, $encoding); } -} -if (!function_exists('mb_output_handler')) { - function mb_output_handler(?string $string, ?int $status): string { return p\Mbstring::mb_output_handler((string) $string, (int) $status); } -} -if (!function_exists('mb_http_input')) { - function mb_http_input(?string $type = null): array|string|false { return p\Mbstring::mb_http_input($type); } -} - -if (!function_exists('mb_convert_variables')) { - function mb_convert_variables(?string $to_encoding, array|string|null $from_encoding, mixed &$var, mixed &...$vars): string|false { return p\Mbstring::mb_convert_variables((string) $to_encoding, $from_encoding ?? '', $var, ...$vars); } -} - -if (!function_exists('mb_ord')) { - function mb_ord(?string $string, ?string $encoding = null): int|false { return p\Mbstring::mb_ord((string) $string, $encoding); } -} -if (!function_exists('mb_chr')) { - function mb_chr(?int $codepoint, ?string $encoding = null): string|false { return p\Mbstring::mb_chr((int) $codepoint, $encoding); } -} -if (!function_exists('mb_scrub')) { - function mb_scrub(?string $string, ?string $encoding = null): string { $encoding ??= mb_internal_encoding(); return mb_convert_encoding((string) $string, $encoding, $encoding); } -} -if (!function_exists('mb_str_split')) { - function mb_str_split(?string $string, ?int $length = 1, ?string $encoding = null): array { return p\Mbstring::mb_str_split((string) $string, (int) $length, $encoding); } -} - -if (!function_exists('mb_str_pad')) { - function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = STR_PAD_RIGHT, ?string $encoding = null): string { return p\Mbstring::mb_str_pad($string, $length, $pad_string, $pad_type, $encoding); } -} - -if (!function_exists('mb_ucfirst')) { - function mb_ucfirst($string, ?string $encoding = null): string { return p\Mbstring::mb_ucfirst($string, $encoding); } -} - -if (!function_exists('mb_lcfirst')) { - function mb_lcfirst($string, ?string $encoding = null): string { return p\Mbstring::mb_lcfirst($string, $encoding); } -} - -if (extension_loaded('mbstring')) { - return; -} - -if (!defined('MB_CASE_UPPER')) { - define('MB_CASE_UPPER', 0); -} -if (!defined('MB_CASE_LOWER')) { - define('MB_CASE_LOWER', 1); -} -if (!defined('MB_CASE_TITLE')) { - define('MB_CASE_TITLE', 2); -} diff --git a/digital_doctor/vendor/symfony/polyfill-mbstring/composer.json b/digital_doctor/vendor/symfony/polyfill-mbstring/composer.json deleted file mode 100644 index bd99d4b..0000000 --- a/digital_doctor/vendor/symfony/polyfill-mbstring/composer.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "name": "symfony/polyfill-mbstring", - "type": "library", - "description": "Symfony polyfill for the Mbstring extension", - "keywords": ["polyfill", "shim", "compatibility", "portable", "mbstring"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.1" - }, - "provide": { - "ext-mbstring": "*" - }, - "autoload": { - "psr-4": { "Symfony\\Polyfill\\Mbstring\\": "" }, - "files": [ "bootstrap.php" ] - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "minimum-stability": "dev", - "extra": { - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - } -} diff --git a/digital_doctor/vendor/symfony/polyfill-php80/LICENSE b/digital_doctor/vendor/symfony/polyfill-php80/LICENSE deleted file mode 100644 index 0ed3a24..0000000 --- a/digital_doctor/vendor/symfony/polyfill-php80/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2020-present Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/digital_doctor/vendor/symfony/polyfill-php80/Php80.php b/digital_doctor/vendor/symfony/polyfill-php80/Php80.php deleted file mode 100644 index 362dd1a..0000000 --- a/digital_doctor/vendor/symfony/polyfill-php80/Php80.php +++ /dev/null @@ -1,115 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Php80; - -/** - * @author Ion Bazan - * @author Nico Oelgart - * @author Nicolas Grekas - * - * @internal - */ -final class Php80 -{ - public static function fdiv(float $dividend, float $divisor): float - { - return @($dividend / $divisor); - } - - public static function get_debug_type($value): string - { - switch (true) { - case null === $value: return 'null'; - case \is_bool($value): return 'bool'; - case \is_string($value): return 'string'; - case \is_array($value): return 'array'; - case \is_int($value): return 'int'; - case \is_float($value): return 'float'; - case \is_object($value): break; - case $value instanceof \__PHP_Incomplete_Class: return '__PHP_Incomplete_Class'; - default: - if (null === $type = @get_resource_type($value)) { - return 'unknown'; - } - - if ('Unknown' === $type) { - $type = 'closed'; - } - - return "resource ($type)"; - } - - $class = \get_class($value); - - if (false === strpos($class, '@')) { - return $class; - } - - return (get_parent_class($class) ?: key(class_implements($class)) ?: 'class').'@anonymous'; - } - - public static function get_resource_id($res): int - { - if (!\is_resource($res) && null === @get_resource_type($res)) { - throw new \TypeError(sprintf('Argument 1 passed to get_resource_id() must be of the type resource, %s given', get_debug_type($res))); - } - - return (int) $res; - } - - public static function preg_last_error_msg(): string - { - switch (preg_last_error()) { - case \PREG_INTERNAL_ERROR: - return 'Internal error'; - case \PREG_BAD_UTF8_ERROR: - return 'Malformed UTF-8 characters, possibly incorrectly encoded'; - case \PREG_BAD_UTF8_OFFSET_ERROR: - return 'The offset did not correspond to the beginning of a valid UTF-8 code point'; - case \PREG_BACKTRACK_LIMIT_ERROR: - return 'Backtrack limit exhausted'; - case \PREG_RECURSION_LIMIT_ERROR: - return 'Recursion limit exhausted'; - case \PREG_JIT_STACKLIMIT_ERROR: - return 'JIT stack limit exhausted'; - case \PREG_NO_ERROR: - return 'No error'; - default: - return 'Unknown error'; - } - } - - public static function str_contains(string $haystack, string $needle): bool - { - return '' === $needle || false !== strpos($haystack, $needle); - } - - public static function str_starts_with(string $haystack, string $needle): bool - { - return 0 === strncmp($haystack, $needle, \strlen($needle)); - } - - public static function str_ends_with(string $haystack, string $needle): bool - { - if ('' === $needle || $needle === $haystack) { - return true; - } - - if ('' === $haystack) { - return false; - } - - $needleLength = \strlen($needle); - - return $needleLength <= \strlen($haystack) && 0 === substr_compare($haystack, $needle, -$needleLength); - } -} diff --git a/digital_doctor/vendor/symfony/polyfill-php80/PhpToken.php b/digital_doctor/vendor/symfony/polyfill-php80/PhpToken.php deleted file mode 100644 index fe6e691..0000000 --- a/digital_doctor/vendor/symfony/polyfill-php80/PhpToken.php +++ /dev/null @@ -1,103 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Php80; - -/** - * @author Fedonyuk Anton - * - * @internal - */ -class PhpToken implements \Stringable -{ - /** - * @var int - */ - public $id; - - /** - * @var string - */ - public $text; - - /** - * @var int - */ - public $line; - - /** - * @var int - */ - public $pos; - - public function __construct(int $id, string $text, int $line = -1, int $position = -1) - { - $this->id = $id; - $this->text = $text; - $this->line = $line; - $this->pos = $position; - } - - public function getTokenName(): ?string - { - if ('UNKNOWN' === $name = token_name($this->id)) { - $name = \strlen($this->text) > 1 || \ord($this->text) < 32 ? null : $this->text; - } - - return $name; - } - - /** - * @param int|string|array $kind - */ - public function is($kind): bool - { - foreach ((array) $kind as $value) { - if (\in_array($value, [$this->id, $this->text], true)) { - return true; - } - } - - return false; - } - - public function isIgnorable(): bool - { - return \in_array($this->id, [\T_WHITESPACE, \T_COMMENT, \T_DOC_COMMENT, \T_OPEN_TAG], true); - } - - public function __toString(): string - { - return (string) $this->text; - } - - /** - * @return static[] - */ - public static function tokenize(string $code, int $flags = 0): array - { - $line = 1; - $position = 0; - $tokens = token_get_all($code, $flags); - foreach ($tokens as $index => $token) { - if (\is_string($token)) { - $id = \ord($token); - $text = $token; - } else { - [$id, $text, $line] = $token; - } - $tokens[$index] = new static($id, $text, $line, $position); - $position += \strlen($text); - } - - return $tokens; - } -} diff --git a/digital_doctor/vendor/symfony/polyfill-php80/README.md b/digital_doctor/vendor/symfony/polyfill-php80/README.md deleted file mode 100644 index 3816c55..0000000 --- a/digital_doctor/vendor/symfony/polyfill-php80/README.md +++ /dev/null @@ -1,25 +0,0 @@ -Symfony Polyfill / Php80 -======================== - -This component provides features added to PHP 8.0 core: - -- [`Stringable`](https://php.net/stringable) interface -- [`fdiv`](https://php.net/fdiv) -- [`ValueError`](https://php.net/valueerror) class -- [`UnhandledMatchError`](https://php.net/unhandledmatcherror) class -- `FILTER_VALIDATE_BOOL` constant -- [`get_debug_type`](https://php.net/get_debug_type) -- [`PhpToken`](https://php.net/phptoken) class -- [`preg_last_error_msg`](https://php.net/preg_last_error_msg) -- [`str_contains`](https://php.net/str_contains) -- [`str_starts_with`](https://php.net/str_starts_with) -- [`str_ends_with`](https://php.net/str_ends_with) -- [`get_resource_id`](https://php.net/get_resource_id) - -More information can be found in the -[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). - -License -======= - -This library is released under the [MIT license](LICENSE). diff --git a/digital_doctor/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php b/digital_doctor/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php deleted file mode 100644 index 2b95542..0000000 --- a/digital_doctor/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php +++ /dev/null @@ -1,31 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -#[Attribute(Attribute::TARGET_CLASS)] -final class Attribute -{ - public const TARGET_CLASS = 1; - public const TARGET_FUNCTION = 2; - public const TARGET_METHOD = 4; - public const TARGET_PROPERTY = 8; - public const TARGET_CLASS_CONSTANT = 16; - public const TARGET_PARAMETER = 32; - public const TARGET_ALL = 63; - public const IS_REPEATABLE = 64; - - /** @var int */ - public $flags; - - public function __construct(int $flags = self::TARGET_ALL) - { - $this->flags = $flags; - } -} diff --git a/digital_doctor/vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php b/digital_doctor/vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php deleted file mode 100644 index bd1212f..0000000 --- a/digital_doctor/vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php +++ /dev/null @@ -1,16 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -if (\PHP_VERSION_ID < 80000 && extension_loaded('tokenizer')) { - class PhpToken extends Symfony\Polyfill\Php80\PhpToken - { - } -} diff --git a/digital_doctor/vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php b/digital_doctor/vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php deleted file mode 100644 index 7c62d75..0000000 --- a/digital_doctor/vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php +++ /dev/null @@ -1,20 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -if (\PHP_VERSION_ID < 80000) { - interface Stringable - { - /** - * @return string - */ - public function __toString(); - } -} diff --git a/digital_doctor/vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php b/digital_doctor/vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php deleted file mode 100644 index 01c6c6c..0000000 --- a/digital_doctor/vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php +++ /dev/null @@ -1,16 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -if (\PHP_VERSION_ID < 80000) { - class UnhandledMatchError extends Error - { - } -} diff --git a/digital_doctor/vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php b/digital_doctor/vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php deleted file mode 100644 index 783dbc2..0000000 --- a/digital_doctor/vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php +++ /dev/null @@ -1,16 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -if (\PHP_VERSION_ID < 80000) { - class ValueError extends Error - { - } -} diff --git a/digital_doctor/vendor/symfony/polyfill-php80/bootstrap.php b/digital_doctor/vendor/symfony/polyfill-php80/bootstrap.php deleted file mode 100644 index e5f7dbc..0000000 --- a/digital_doctor/vendor/symfony/polyfill-php80/bootstrap.php +++ /dev/null @@ -1,42 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use Symfony\Polyfill\Php80 as p; - -if (\PHP_VERSION_ID >= 80000) { - return; -} - -if (!defined('FILTER_VALIDATE_BOOL') && defined('FILTER_VALIDATE_BOOLEAN')) { - define('FILTER_VALIDATE_BOOL', \FILTER_VALIDATE_BOOLEAN); -} - -if (!function_exists('fdiv')) { - function fdiv(float $num1, float $num2): float { return p\Php80::fdiv($num1, $num2); } -} -if (!function_exists('preg_last_error_msg')) { - function preg_last_error_msg(): string { return p\Php80::preg_last_error_msg(); } -} -if (!function_exists('str_contains')) { - function str_contains(?string $haystack, ?string $needle): bool { return p\Php80::str_contains($haystack ?? '', $needle ?? ''); } -} -if (!function_exists('str_starts_with')) { - function str_starts_with(?string $haystack, ?string $needle): bool { return p\Php80::str_starts_with($haystack ?? '', $needle ?? ''); } -} -if (!function_exists('str_ends_with')) { - function str_ends_with(?string $haystack, ?string $needle): bool { return p\Php80::str_ends_with($haystack ?? '', $needle ?? ''); } -} -if (!function_exists('get_debug_type')) { - function get_debug_type($value): string { return p\Php80::get_debug_type($value); } -} -if (!function_exists('get_resource_id')) { - function get_resource_id($resource): int { return p\Php80::get_resource_id($resource); } -} diff --git a/digital_doctor/vendor/symfony/polyfill-php80/composer.json b/digital_doctor/vendor/symfony/polyfill-php80/composer.json deleted file mode 100644 index 46ccde2..0000000 --- a/digital_doctor/vendor/symfony/polyfill-php80/composer.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "symfony/polyfill-php80", - "type": "library", - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", - "keywords": ["polyfill", "shim", "compatibility", "portable"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.1" - }, - "autoload": { - "psr-4": { "Symfony\\Polyfill\\Php80\\": "" }, - "files": [ "bootstrap.php" ], - "classmap": [ "Resources/stubs" ] - }, - "minimum-stability": "dev", - "extra": { - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - } -} diff --git a/digital_doctor/vendor/symfony/routing/Alias.php b/digital_doctor/vendor/symfony/routing/Alias.php deleted file mode 100644 index f3e1d5a..0000000 --- a/digital_doctor/vendor/symfony/routing/Alias.php +++ /dev/null @@ -1,96 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing; - -use Symfony\Component\Routing\Exception\InvalidArgumentException; - -class Alias -{ - private $id; - private $deprecation = []; - - public function __construct(string $id) - { - $this->id = $id; - } - - /** - * @return static - */ - public function withId(string $id): self - { - $new = clone $this; - - $new->id = $id; - - return $new; - } - - /** - * Returns the target name of this alias. - * - * @return string The target name - */ - public function getId(): string - { - return $this->id; - } - - /** - * Whether this alias is deprecated, that means it should not be referenced anymore. - * - * @param string $package The name of the composer package that is triggering the deprecation - * @param string $version The version of the package that introduced the deprecation - * @param string $message The deprecation message to use - * - * @return $this - * - * @throws InvalidArgumentException when the message template is invalid - */ - public function setDeprecated(string $package, string $version, string $message): self - { - if ('' !== $message) { - if (preg_match('#[\r\n]|\*/#', $message)) { - throw new InvalidArgumentException('Invalid characters found in deprecation template.'); - } - - if (!str_contains($message, '%alias_id%')) { - throw new InvalidArgumentException('The deprecation template must contain the "%alias_id%" placeholder.'); - } - } - - $this->deprecation = [ - 'package' => $package, - 'version' => $version, - 'message' => $message ?: 'The "%alias_id%" route alias is deprecated. You should stop using it, as it will be removed in the future.', - ]; - - return $this; - } - - public function isDeprecated(): bool - { - return (bool) $this->deprecation; - } - - /** - * @param string $name Route name relying on this alias - */ - public function getDeprecation(string $name): array - { - return [ - 'package' => $this->deprecation['package'], - 'version' => $this->deprecation['version'], - 'message' => str_replace('%alias_id%', $name, $this->deprecation['message']), - ]; - } -} diff --git a/digital_doctor/vendor/symfony/routing/Annotation/Route.php b/digital_doctor/vendor/symfony/routing/Annotation/Route.php deleted file mode 100644 index 957344f..0000000 --- a/digital_doctor/vendor/symfony/routing/Annotation/Route.php +++ /dev/null @@ -1,272 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Annotation; - -/** - * Annotation class for @Route(). - * - * @Annotation - * @NamedArgumentConstructor - * @Target({"CLASS", "METHOD"}) - * - * @author Fabien Potencier - * @author Alexander M. Turek - */ -#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD)] -class Route -{ - private $path; - private $localizedPaths = []; - private $name; - private $requirements = []; - private $options = []; - private $defaults = []; - private $host; - private $methods = []; - private $schemes = []; - private $condition; - private $priority; - private $env; - - /** - * @param array|string $data data array managed by the Doctrine Annotations library or the path - * @param array|string|null $path - * @param string[] $requirements - * @param string[]|string $methods - * @param string[]|string $schemes - * - * @throws \BadMethodCallException - */ - public function __construct( - $data = [], - $path = null, - ?string $name = null, - array $requirements = [], - array $options = [], - array $defaults = [], - ?string $host = null, - $methods = [], - $schemes = [], - ?string $condition = null, - ?int $priority = null, - ?string $locale = null, - ?string $format = null, - ?bool $utf8 = null, - ?bool $stateless = null, - ?string $env = null - ) { - if (\is_string($data)) { - $data = ['path' => $data]; - } elseif (!\is_array($data)) { - throw new \TypeError(sprintf('"%s": Argument $data is expected to be a string or array, got "%s".', __METHOD__, get_debug_type($data))); - } elseif ([] !== $data) { - $deprecation = false; - foreach ($data as $key => $val) { - if (\in_array($key, ['path', 'name', 'requirements', 'options', 'defaults', 'host', 'methods', 'schemes', 'condition', 'priority', 'locale', 'format', 'utf8', 'stateless', 'env', 'value'])) { - $deprecation = true; - } - } - - if ($deprecation) { - trigger_deprecation('symfony/routing', '5.3', 'Passing an array as first argument to "%s" is deprecated. Use named arguments instead.', __METHOD__); - } else { - $localizedPaths = $data; - $data = ['path' => $localizedPaths]; - } - } - if (null !== $path && !\is_string($path) && !\is_array($path)) { - throw new \TypeError(sprintf('"%s": Argument $path is expected to be a string, array or null, got "%s".', __METHOD__, get_debug_type($path))); - } - - $data['path'] = $data['path'] ?? $path; - $data['name'] = $data['name'] ?? $name; - $data['requirements'] = $data['requirements'] ?? $requirements; - $data['options'] = $data['options'] ?? $options; - $data['defaults'] = $data['defaults'] ?? $defaults; - $data['host'] = $data['host'] ?? $host; - $data['methods'] = $data['methods'] ?? $methods; - $data['schemes'] = $data['schemes'] ?? $schemes; - $data['condition'] = $data['condition'] ?? $condition; - $data['priority'] = $data['priority'] ?? $priority; - $data['locale'] = $data['locale'] ?? $locale; - $data['format'] = $data['format'] ?? $format; - $data['utf8'] = $data['utf8'] ?? $utf8; - $data['stateless'] = $data['stateless'] ?? $stateless; - $data['env'] = $data['env'] ?? $env; - - $data = array_filter($data, static function ($value): bool { - return null !== $value; - }); - - if (isset($data['localized_paths'])) { - throw new \BadMethodCallException(sprintf('Unknown property "localized_paths" on annotation "%s".', static::class)); - } - - if (isset($data['value'])) { - $data[\is_array($data['value']) ? 'localized_paths' : 'path'] = $data['value']; - unset($data['value']); - } - - if (isset($data['path']) && \is_array($data['path'])) { - $data['localized_paths'] = $data['path']; - unset($data['path']); - } - - if (isset($data['locale'])) { - $data['defaults']['_locale'] = $data['locale']; - unset($data['locale']); - } - - if (isset($data['format'])) { - $data['defaults']['_format'] = $data['format']; - unset($data['format']); - } - - if (isset($data['utf8'])) { - $data['options']['utf8'] = filter_var($data['utf8'], \FILTER_VALIDATE_BOOLEAN) ?: false; - unset($data['utf8']); - } - - if (isset($data['stateless'])) { - $data['defaults']['_stateless'] = filter_var($data['stateless'], \FILTER_VALIDATE_BOOLEAN) ?: false; - unset($data['stateless']); - } - - foreach ($data as $key => $value) { - $method = 'set'.str_replace('_', '', $key); - if (!method_exists($this, $method)) { - throw new \BadMethodCallException(sprintf('Unknown property "%s" on annotation "%s".', $key, static::class)); - } - $this->$method($value); - } - } - - public function setPath(string $path) - { - $this->path = $path; - } - - public function getPath() - { - return $this->path; - } - - public function setLocalizedPaths(array $localizedPaths) - { - $this->localizedPaths = $localizedPaths; - } - - public function getLocalizedPaths(): array - { - return $this->localizedPaths; - } - - public function setHost(string $pattern) - { - $this->host = $pattern; - } - - public function getHost() - { - return $this->host; - } - - public function setName(string $name) - { - $this->name = $name; - } - - public function getName() - { - return $this->name; - } - - public function setRequirements(array $requirements) - { - $this->requirements = $requirements; - } - - public function getRequirements() - { - return $this->requirements; - } - - public function setOptions(array $options) - { - $this->options = $options; - } - - public function getOptions() - { - return $this->options; - } - - public function setDefaults(array $defaults) - { - $this->defaults = $defaults; - } - - public function getDefaults() - { - return $this->defaults; - } - - public function setSchemes($schemes) - { - $this->schemes = \is_array($schemes) ? $schemes : [$schemes]; - } - - public function getSchemes() - { - return $this->schemes; - } - - public function setMethods($methods) - { - $this->methods = \is_array($methods) ? $methods : [$methods]; - } - - public function getMethods() - { - return $this->methods; - } - - public function setCondition(?string $condition) - { - $this->condition = $condition; - } - - public function getCondition() - { - return $this->condition; - } - - public function setPriority(int $priority): void - { - $this->priority = $priority; - } - - public function getPriority(): ?int - { - return $this->priority; - } - - public function setEnv(?string $env): void - { - $this->env = $env; - } - - public function getEnv(): ?string - { - return $this->env; - } -} diff --git a/digital_doctor/vendor/symfony/routing/CHANGELOG.md b/digital_doctor/vendor/symfony/routing/CHANGELOG.md deleted file mode 100644 index b966389..0000000 --- a/digital_doctor/vendor/symfony/routing/CHANGELOG.md +++ /dev/null @@ -1,296 +0,0 @@ -CHANGELOG -========= - -5.3 ---- - - * Already encoded slashes are not decoded nor double-encoded anymore when generating URLs - * Add support for per-env configuration in XML and Yaml loaders - * Deprecate creating instances of the `Route` annotation class by passing an array of parameters - * Add `RoutingConfigurator::env()` to get the current environment - -5.2.0 ------ - - * Added support for inline definition of requirements and defaults for host - * Added support for `\A` and `\z` as regex start and end for route requirement - * Added support for `#[Route]` attributes - -5.1.0 ------ - - * added the protected method `PhpFileLoader::callConfigurator()` as extension point to ease custom routing configuration - * deprecated `RouteCollectionBuilder` in favor of `RoutingConfigurator`. - * added "priority" option to annotated routes - * added argument `$priority` to `RouteCollection::add()` - * deprecated the `RouteCompiler::REGEX_DELIMITER` constant - * added `ExpressionLanguageProvider` to expose extra functions to route conditions - * added support for a `stateless` keyword for configuring route stateless in PHP, YAML and XML configurations. - * added the "hosts" option to be able to configure the host per locale. - * added `RequestContext::fromUri()` to ease building the default context - -5.0.0 ------ - - * removed `PhpGeneratorDumper` and `PhpMatcherDumper` - * removed `generator_base_class`, `generator_cache_class`, `matcher_base_class` and `matcher_cache_class` router options - * `Serializable` implementing methods for `Route` and `CompiledRoute` are final - * removed referencing service route loaders with a single colon - * Removed `ServiceRouterLoader` and `ObjectRouteLoader`. - -4.4.0 ------ - - * Deprecated `ServiceRouterLoader` in favor of `ContainerLoader`. - * Deprecated `ObjectRouteLoader` in favor of `ObjectLoader`. - * Added a way to exclude patterns of resources from being imported by the `import()` method - -4.3.0 ------ - - * added `CompiledUrlMatcher` and `CompiledUrlMatcherDumper` - * added `CompiledUrlGenerator` and `CompiledUrlGeneratorDumper` - * deprecated `PhpGeneratorDumper` and `PhpMatcherDumper` - * deprecated `generator_base_class`, `generator_cache_class`, `matcher_base_class` and `matcher_cache_class` router options - * `Serializable` implementing methods for `Route` and `CompiledRoute` are marked as `@internal` and `@final`. - Instead of overwriting them, use `__serialize` and `__unserialize` as extension points which are forward compatible - with the new serialization methods in PHP 7.4. - * exposed `utf8` Route option, defaults "locale" and "format" in configuration loaders and configurators - * added support for invokable service route loaders - -4.2.0 ------ - - * added fallback to cultureless locale for internationalized routes - -4.0.0 ------ - - * dropped support for using UTF-8 route patterns without using the `utf8` option - * dropped support for using UTF-8 route requirements without using the `utf8` option - -3.4.0 ------ - - * Added `NoConfigurationException`. - * Added the possibility to define a prefix for all routes of a controller via @Route(name="prefix_") - * Added support for prioritized routing loaders. - * Add matched and default parameters to redirect responses - * Added support for a `controller` keyword for configuring route controllers in YAML and XML configurations. - -3.3.0 ------ - - * [DEPRECATION] Class parameters have been deprecated and will be removed in 4.0. - * router.options.generator_class - * router.options.generator_base_class - * router.options.generator_dumper_class - * router.options.matcher_class - * router.options.matcher_base_class - * router.options.matcher_dumper_class - * router.options.matcher.cache_class - * router.options.generator.cache_class - -3.2.0 ------ - - * Added support for `bool`, `int`, `float`, `string`, `list` and `map` defaults in XML configurations. - * Added support for UTF-8 requirements - -2.8.0 ------ - - * allowed specifying a directory to recursively load all routing configuration files it contains - * Added ObjectRouteLoader and ServiceRouteLoader that allow routes to be loaded - by calling a method on an object/service. - * [DEPRECATION] Deprecated the hardcoded value for the `$referenceType` argument of the `UrlGeneratorInterface::generate` method. - Use the constants defined in the `UrlGeneratorInterface` instead. - - Before: - - ```php - $router->generate('blog_show', ['slug' => 'my-blog-post'], true); - ``` - - After: - - ```php - use Symfony\Component\Routing\Generator\UrlGeneratorInterface; - - $router->generate('blog_show', ['slug' => 'my-blog-post'], UrlGeneratorInterface::ABSOLUTE_URL); - ``` - -2.5.0 ------ - - * [DEPRECATION] The `ApacheMatcherDumper` and `ApacheUrlMatcher` were deprecated and - will be removed in Symfony 3.0, since the performance gains were minimal and - it's hard to replicate the behavior of PHP implementation. - -2.3.0 ------ - - * added RequestContext::getQueryString() - -2.2.0 ------ - - * [DEPRECATION] Several route settings have been renamed (the old ones will be removed in 3.0): - - * The `pattern` setting for a route has been deprecated in favor of `path` - * The `_scheme` and `_method` requirements have been moved to the `schemes` and `methods` settings - - Before: - - ```yaml - article_edit: - pattern: /article/{id} - requirements: { '_method': 'POST|PUT', '_scheme': 'https', 'id': '\d+' } - ``` - - ```xml - - POST|PUT - https - \d+ - - ``` - - ```php - $route = new Route(); - $route->setPattern('/article/{id}'); - $route->setRequirement('_method', 'POST|PUT'); - $route->setRequirement('_scheme', 'https'); - ``` - - After: - - ```yaml - article_edit: - path: /article/{id} - methods: [POST, PUT] - schemes: https - requirements: { 'id': '\d+' } - ``` - - ```xml - - \d+ - - ``` - - ```php - $route = new Route(); - $route->setPath('/article/{id}'); - $route->setMethods(['POST', 'PUT']); - $route->setSchemes('https'); - ``` - - * [BC BREAK] RouteCollection does not behave like a tree structure anymore but as - a flat array of Routes. So when using PHP to build the RouteCollection, you must - make sure to add routes to the sub-collection before adding it to the parent - collection (this is not relevant when using YAML or XML for Route definitions). - - Before: - - ```php - $rootCollection = new RouteCollection(); - $subCollection = new RouteCollection(); - $rootCollection->addCollection($subCollection); - $subCollection->add('foo', new Route('/foo')); - ``` - - After: - - ```php - $rootCollection = new RouteCollection(); - $subCollection = new RouteCollection(); - $subCollection->add('foo', new Route('/foo')); - $rootCollection->addCollection($subCollection); - ``` - - Also one must call `addCollection` from the bottom to the top hierarchy. - So the correct sequence is the following (and not the reverse): - - ```php - $childCollection->addCollection($grandchildCollection); - $rootCollection->addCollection($childCollection); - ``` - - * [DEPRECATION] The methods `RouteCollection::getParent()` and `RouteCollection::getRoot()` - have been deprecated and will be removed in Symfony 2.3. - * [BC BREAK] Misusing the `RouteCollection::addPrefix` method to add defaults, requirements - or options without adding a prefix is not supported anymore. So if you called `addPrefix` - with an empty prefix or `/` only (both have no relevance), like - `addPrefix('', $defaultsArray, $requirementsArray, $optionsArray)` - you need to use the new dedicated methods `addDefaults($defaultsArray)`, - `addRequirements($requirementsArray)` or `addOptions($optionsArray)` instead. - * [DEPRECATION] The `$options` parameter to `RouteCollection::addPrefix()` has been deprecated - because adding options has nothing to do with adding a path prefix. If you want to add options - to all child routes of a RouteCollection, you can use `addOptions()`. - * [DEPRECATION] The method `RouteCollection::getPrefix()` has been deprecated - because it suggested that all routes in the collection would have this prefix, which is - not necessarily true. On top of that, since there is no tree structure anymore, this method - is also useless. Don't worry about performance, prefix optimization for matching is still done - in the dumper, which was also improved in 2.2.0 to find even more grouping possibilities. - * [DEPRECATION] `RouteCollection::addCollection(RouteCollection $collection)` should now only be - used with a single parameter. The other params `$prefix`, `$default`, `$requirements` and `$options` - will still work, but have been deprecated. The `addPrefix` method should be used for this - use-case instead. - Before: `$parentCollection->addCollection($collection, '/prefix', [...], [...])` - After: - ```php - $collection->addPrefix('/prefix', [...], [...]); - $parentCollection->addCollection($collection); - ``` - * added support for the method default argument values when defining a @Route - * Adjacent placeholders without separator work now, e.g. `/{x}{y}{z}.{_format}`. - * Characters that function as separator between placeholders are now whitelisted - to fix routes with normal text around a variable, e.g. `/prefix{var}suffix`. - * [BC BREAK] The default requirement of a variable has been changed slightly. - Previously it disallowed the previous and the next char around a variable. Now - it disallows the slash (`/`) and the next char. Using the previous char added - no value and was problematic because the route `/index.{_format}` would be - matched by `/index.ht/ml`. - * The default requirement now uses possessive quantifiers when possible which - improves matching performance by up to 20% because it prevents backtracking - when it's not needed. - * The ConfigurableRequirementsInterface can now also be used to disable the requirements - check on URL generation completely by calling `setStrictRequirements(null)`. It - improves performance in production environment as you should know that params always - pass the requirements (otherwise it would break your link anyway). - * There is no restriction on the route name anymore. So non-alphanumeric characters - are now also allowed. - * [BC BREAK] `RouteCompilerInterface::compile(Route $route)` was made static - (only relevant if you implemented your own RouteCompiler). - * Added possibility to generate relative paths and network paths in the UrlGenerator, e.g. - "../parent-file" and "//example.com/dir/file". The third parameter in - `UrlGeneratorInterface::generate($name, $parameters = [], $referenceType = self::ABSOLUTE_PATH)` - now accepts more values and you should use the constants defined in `UrlGeneratorInterface` for - claritiy. The old method calls with a Boolean parameter will continue to work because they - equal the signature using the constants. - -2.1.0 ------ - - * added RequestMatcherInterface - * added RequestContext::fromRequest() - * the UrlMatcher does not throw a \LogicException anymore when the required - scheme is not the current one - * added TraceableUrlMatcher - * added the possibility to define options, default values and requirements - for placeholders in prefix, including imported routes - * added RouterInterface::getRouteCollection - * [BC BREAK] the UrlMatcher urldecodes the route parameters only once, they - were decoded twice before. Note that the `urldecode()` calls have been - changed for a single `rawurldecode()` in order to support `+` for input - paths. - * added RouteCollection::getRoot method to retrieve the root of a - RouteCollection tree - * [BC BREAK] made RouteCollection::setParent private which could not have - been used anyway without creating inconsistencies - * [BC BREAK] RouteCollection::remove also removes a route from parent - collections (not only from its children) - * added ConfigurableRequirementsInterface that allows to disable exceptions - (and generate empty URLs instead) when generating a route with an invalid - parameter value diff --git a/digital_doctor/vendor/symfony/routing/CompiledRoute.php b/digital_doctor/vendor/symfony/routing/CompiledRoute.php deleted file mode 100644 index 64bf9ca..0000000 --- a/digital_doctor/vendor/symfony/routing/CompiledRoute.php +++ /dev/null @@ -1,173 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing; - -/** - * CompiledRoutes are returned by the RouteCompiler class. - * - * @author Fabien Potencier - */ -class CompiledRoute implements \Serializable -{ - private $variables; - private $tokens; - private $staticPrefix; - private $regex; - private $pathVariables; - private $hostVariables; - private $hostRegex; - private $hostTokens; - - /** - * @param string $staticPrefix The static prefix of the compiled route - * @param string $regex The regular expression to use to match this route - * @param array $tokens An array of tokens to use to generate URL for this route - * @param array $pathVariables An array of path variables - * @param string|null $hostRegex Host regex - * @param array $hostTokens Host tokens - * @param array $hostVariables An array of host variables - * @param array $variables An array of variables (variables defined in the path and in the host patterns) - */ - public function __construct(string $staticPrefix, string $regex, array $tokens, array $pathVariables, ?string $hostRegex = null, array $hostTokens = [], array $hostVariables = [], array $variables = []) - { - $this->staticPrefix = $staticPrefix; - $this->regex = $regex; - $this->tokens = $tokens; - $this->pathVariables = $pathVariables; - $this->hostRegex = $hostRegex; - $this->hostTokens = $hostTokens; - $this->hostVariables = $hostVariables; - $this->variables = $variables; - } - - public function __serialize(): array - { - return [ - 'vars' => $this->variables, - 'path_prefix' => $this->staticPrefix, - 'path_regex' => $this->regex, - 'path_tokens' => $this->tokens, - 'path_vars' => $this->pathVariables, - 'host_regex' => $this->hostRegex, - 'host_tokens' => $this->hostTokens, - 'host_vars' => $this->hostVariables, - ]; - } - - /** - * @internal - */ - final public function serialize(): string - { - return serialize($this->__serialize()); - } - - public function __unserialize(array $data): void - { - $this->variables = $data['vars']; - $this->staticPrefix = $data['path_prefix']; - $this->regex = $data['path_regex']; - $this->tokens = $data['path_tokens']; - $this->pathVariables = $data['path_vars']; - $this->hostRegex = $data['host_regex']; - $this->hostTokens = $data['host_tokens']; - $this->hostVariables = $data['host_vars']; - } - - /** - * @internal - */ - final public function unserialize($serialized) - { - $this->__unserialize(unserialize($serialized, ['allowed_classes' => false])); - } - - /** - * Returns the static prefix. - * - * @return string - */ - public function getStaticPrefix() - { - return $this->staticPrefix; - } - - /** - * Returns the regex. - * - * @return string - */ - public function getRegex() - { - return $this->regex; - } - - /** - * Returns the host regex. - * - * @return string|null - */ - public function getHostRegex() - { - return $this->hostRegex; - } - - /** - * Returns the tokens. - * - * @return array - */ - public function getTokens() - { - return $this->tokens; - } - - /** - * Returns the host tokens. - * - * @return array - */ - public function getHostTokens() - { - return $this->hostTokens; - } - - /** - * Returns the variables. - * - * @return array - */ - public function getVariables() - { - return $this->variables; - } - - /** - * Returns the path variables. - * - * @return array - */ - public function getPathVariables() - { - return $this->pathVariables; - } - - /** - * Returns the host variables. - * - * @return array - */ - public function getHostVariables() - { - return $this->hostVariables; - } -} diff --git a/digital_doctor/vendor/symfony/routing/DependencyInjection/RoutingResolverPass.php b/digital_doctor/vendor/symfony/routing/DependencyInjection/RoutingResolverPass.php deleted file mode 100644 index 0e9b9c8..0000000 --- a/digital_doctor/vendor/symfony/routing/DependencyInjection/RoutingResolverPass.php +++ /dev/null @@ -1,53 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\DependencyInjection; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Adds tagged routing.loader services to routing.resolver service. - * - * @author Fabien Potencier - */ -class RoutingResolverPass implements CompilerPassInterface -{ - use PriorityTaggedServiceTrait; - - private $resolverServiceId; - private $loaderTag; - - public function __construct(string $resolverServiceId = 'routing.resolver', string $loaderTag = 'routing.loader') - { - if (0 < \func_num_args()) { - trigger_deprecation('symfony/routing', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); - } - - $this->resolverServiceId = $resolverServiceId; - $this->loaderTag = $loaderTag; - } - - public function process(ContainerBuilder $container) - { - if (false === $container->hasDefinition($this->resolverServiceId)) { - return; - } - - $definition = $container->getDefinition($this->resolverServiceId); - - foreach ($this->findAndSortTaggedServices($this->loaderTag, $container) as $id) { - $definition->addMethodCall('addLoader', [new Reference($id)]); - } - } -} diff --git a/digital_doctor/vendor/symfony/routing/Exception/ExceptionInterface.php b/digital_doctor/vendor/symfony/routing/Exception/ExceptionInterface.php deleted file mode 100644 index 22e72b1..0000000 --- a/digital_doctor/vendor/symfony/routing/Exception/ExceptionInterface.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Exception; - -/** - * ExceptionInterface. - * - * @author Alexandre Salomé - */ -interface ExceptionInterface extends \Throwable -{ -} diff --git a/digital_doctor/vendor/symfony/routing/Exception/InvalidArgumentException.php b/digital_doctor/vendor/symfony/routing/Exception/InvalidArgumentException.php deleted file mode 100644 index 950b9b1..0000000 --- a/digital_doctor/vendor/symfony/routing/Exception/InvalidArgumentException.php +++ /dev/null @@ -1,16 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Exception; - -class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface -{ -} diff --git a/digital_doctor/vendor/symfony/routing/Exception/InvalidParameterException.php b/digital_doctor/vendor/symfony/routing/Exception/InvalidParameterException.php deleted file mode 100644 index 94d841f..0000000 --- a/digital_doctor/vendor/symfony/routing/Exception/InvalidParameterException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Exception; - -/** - * Exception thrown when a parameter is not valid. - * - * @author Alexandre Salomé - */ -class InvalidParameterException extends \InvalidArgumentException implements ExceptionInterface -{ -} diff --git a/digital_doctor/vendor/symfony/routing/Exception/MethodNotAllowedException.php b/digital_doctor/vendor/symfony/routing/Exception/MethodNotAllowedException.php deleted file mode 100644 index a73e1e6..0000000 --- a/digital_doctor/vendor/symfony/routing/Exception/MethodNotAllowedException.php +++ /dev/null @@ -1,50 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Exception; - -/** - * The resource was found but the request method is not allowed. - * - * This exception should trigger an HTTP 405 response in your application code. - * - * @author Kris Wallsmith - */ -class MethodNotAllowedException extends \RuntimeException implements ExceptionInterface -{ - protected $allowedMethods = []; - - /** - * @param string[] $allowedMethods - */ - public function __construct(array $allowedMethods, ?string $message = '', int $code = 0, ?\Throwable $previous = null) - { - if (null === $message) { - trigger_deprecation('symfony/routing', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__); - - $message = ''; - } - - $this->allowedMethods = array_map('strtoupper', $allowedMethods); - - parent::__construct($message, $code, $previous); - } - - /** - * Gets the allowed HTTP methods. - * - * @return string[] - */ - public function getAllowedMethods() - { - return $this->allowedMethods; - } -} diff --git a/digital_doctor/vendor/symfony/routing/Exception/MissingMandatoryParametersException.php b/digital_doctor/vendor/symfony/routing/Exception/MissingMandatoryParametersException.php deleted file mode 100644 index 57f3a40..0000000 --- a/digital_doctor/vendor/symfony/routing/Exception/MissingMandatoryParametersException.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Exception; - -/** - * Exception thrown when a route cannot be generated because of missing - * mandatory parameters. - * - * @author Alexandre Salomé - */ -class MissingMandatoryParametersException extends \InvalidArgumentException implements ExceptionInterface -{ -} diff --git a/digital_doctor/vendor/symfony/routing/Exception/NoConfigurationException.php b/digital_doctor/vendor/symfony/routing/Exception/NoConfigurationException.php deleted file mode 100644 index 333bc74..0000000 --- a/digital_doctor/vendor/symfony/routing/Exception/NoConfigurationException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Exception; - -/** - * Exception thrown when no routes are configured. - * - * @author Yonel Ceruto - */ -class NoConfigurationException extends ResourceNotFoundException -{ -} diff --git a/digital_doctor/vendor/symfony/routing/Exception/ResourceNotFoundException.php b/digital_doctor/vendor/symfony/routing/Exception/ResourceNotFoundException.php deleted file mode 100644 index ccbca15..0000000 --- a/digital_doctor/vendor/symfony/routing/Exception/ResourceNotFoundException.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Exception; - -/** - * The resource was not found. - * - * This exception should trigger an HTTP 404 response in your application code. - * - * @author Kris Wallsmith - */ -class ResourceNotFoundException extends \RuntimeException implements ExceptionInterface -{ -} diff --git a/digital_doctor/vendor/symfony/routing/Exception/RouteCircularReferenceException.php b/digital_doctor/vendor/symfony/routing/Exception/RouteCircularReferenceException.php deleted file mode 100644 index 841e359..0000000 --- a/digital_doctor/vendor/symfony/routing/Exception/RouteCircularReferenceException.php +++ /dev/null @@ -1,20 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Exception; - -class RouteCircularReferenceException extends RuntimeException -{ - public function __construct(string $routeId, array $path) - { - parent::__construct(sprintf('Circular reference detected for route "%s", path: "%s".', $routeId, implode(' -> ', $path))); - } -} diff --git a/digital_doctor/vendor/symfony/routing/Exception/RouteNotFoundException.php b/digital_doctor/vendor/symfony/routing/Exception/RouteNotFoundException.php deleted file mode 100644 index 24ab0b4..0000000 --- a/digital_doctor/vendor/symfony/routing/Exception/RouteNotFoundException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Exception; - -/** - * Exception thrown when a route does not exist. - * - * @author Alexandre Salomé - */ -class RouteNotFoundException extends \InvalidArgumentException implements ExceptionInterface -{ -} diff --git a/digital_doctor/vendor/symfony/routing/Exception/RuntimeException.php b/digital_doctor/vendor/symfony/routing/Exception/RuntimeException.php deleted file mode 100644 index 48da62e..0000000 --- a/digital_doctor/vendor/symfony/routing/Exception/RuntimeException.php +++ /dev/null @@ -1,16 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Exception; - -class RuntimeException extends \RuntimeException implements ExceptionInterface -{ -} diff --git a/digital_doctor/vendor/symfony/routing/Generator/CompiledUrlGenerator.php b/digital_doctor/vendor/symfony/routing/Generator/CompiledUrlGenerator.php deleted file mode 100644 index 8af3ae7..0000000 --- a/digital_doctor/vendor/symfony/routing/Generator/CompiledUrlGenerator.php +++ /dev/null @@ -1,69 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Generator; - -use Psr\Log\LoggerInterface; -use Symfony\Component\Routing\Exception\RouteNotFoundException; -use Symfony\Component\Routing\RequestContext; - -/** - * Generates URLs based on rules dumped by CompiledUrlGeneratorDumper. - */ -class CompiledUrlGenerator extends UrlGenerator -{ - private $compiledRoutes = []; - private $defaultLocale; - - public function __construct(array $compiledRoutes, RequestContext $context, ?LoggerInterface $logger = null, ?string $defaultLocale = null) - { - $this->compiledRoutes = $compiledRoutes; - $this->context = $context; - $this->logger = $logger; - $this->defaultLocale = $defaultLocale; - } - - public function generate(string $name, array $parameters = [], int $referenceType = self::ABSOLUTE_PATH) - { - $locale = $parameters['_locale'] - ?? $this->context->getParameter('_locale') - ?: $this->defaultLocale; - - if (null !== $locale) { - do { - if (($this->compiledRoutes[$name.'.'.$locale][1]['_canonical_route'] ?? null) === $name) { - $name .= '.'.$locale; - break; - } - } while (false !== $locale = strstr($locale, '_', true)); - } - - if (!isset($this->compiledRoutes[$name])) { - throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name)); - } - - [$variables, $defaults, $requirements, $tokens, $hostTokens, $requiredSchemes, $deprecations] = $this->compiledRoutes[$name] + [6 => []]; - - foreach ($deprecations as $deprecation) { - trigger_deprecation($deprecation['package'], $deprecation['version'], $deprecation['message']); - } - - if (isset($defaults['_canonical_route']) && isset($defaults['_locale'])) { - if (!\in_array('_locale', $variables, true)) { - unset($parameters['_locale']); - } elseif (!isset($parameters['_locale'])) { - $parameters['_locale'] = $defaults['_locale']; - } - } - - return $this->doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens, $requiredSchemes); - } -} diff --git a/digital_doctor/vendor/symfony/routing/Generator/ConfigurableRequirementsInterface.php b/digital_doctor/vendor/symfony/routing/Generator/ConfigurableRequirementsInterface.php deleted file mode 100644 index 568f7f7..0000000 --- a/digital_doctor/vendor/symfony/routing/Generator/ConfigurableRequirementsInterface.php +++ /dev/null @@ -1,53 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Generator; - -/** - * ConfigurableRequirementsInterface must be implemented by URL generators that - * can be configured whether an exception should be generated when the parameters - * do not match the requirements. It is also possible to disable the requirements - * check for URL generation completely. - * - * The possible configurations and use-cases: - * - setStrictRequirements(true): Throw an exception for mismatching requirements. This - * is mostly useful in development environment. - * - setStrictRequirements(false): Don't throw an exception but return an empty string as URL for - * mismatching requirements and log the problem. Useful when you cannot control all - * params because they come from third party libs but don't want to have a 404 in - * production environment. It should log the mismatch so one can review it. - * - setStrictRequirements(null): Return the URL with the given parameters without - * checking the requirements at all. When generating a URL you should either trust - * your params or you validated them beforehand because otherwise it would break your - * link anyway. So in production environment you should know that params always pass - * the requirements. Thus this option allows to disable the check on URL generation for - * performance reasons (saving a preg_match for each requirement every time a URL is - * generated). - * - * @author Fabien Potencier - * @author Tobias Schultze - */ -interface ConfigurableRequirementsInterface -{ - /** - * Enables or disables the exception on incorrect parameters. - * Passing null will deactivate the requirements check completely. - */ - public function setStrictRequirements(?bool $enabled); - - /** - * Returns whether to throw an exception on incorrect parameters. - * Null means the requirements check is deactivated completely. - * - * @return bool|null - */ - public function isStrictRequirements(); -} diff --git a/digital_doctor/vendor/symfony/routing/Generator/Dumper/CompiledUrlGeneratorDumper.php b/digital_doctor/vendor/symfony/routing/Generator/Dumper/CompiledUrlGeneratorDumper.php deleted file mode 100644 index 9c6740b..0000000 --- a/digital_doctor/vendor/symfony/routing/Generator/Dumper/CompiledUrlGeneratorDumper.php +++ /dev/null @@ -1,124 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Generator\Dumper; - -use Symfony\Component\Routing\Exception\RouteCircularReferenceException; -use Symfony\Component\Routing\Exception\RouteNotFoundException; -use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper; - -/** - * CompiledUrlGeneratorDumper creates a PHP array to be used with CompiledUrlGenerator. - * - * @author Fabien Potencier - * @author Tobias Schultze - * @author Nicolas Grekas - */ -class CompiledUrlGeneratorDumper extends GeneratorDumper -{ - public function getCompiledRoutes(): array - { - $compiledRoutes = []; - foreach ($this->getRoutes()->all() as $name => $route) { - $compiledRoute = $route->compile(); - - $compiledRoutes[$name] = [ - $compiledRoute->getVariables(), - $route->getDefaults(), - $route->getRequirements(), - $compiledRoute->getTokens(), - $compiledRoute->getHostTokens(), - $route->getSchemes(), - [], - ]; - } - - return $compiledRoutes; - } - - public function getCompiledAliases(): array - { - $routes = $this->getRoutes(); - $compiledAliases = []; - foreach ($routes->getAliases() as $name => $alias) { - $deprecations = $alias->isDeprecated() ? [$alias->getDeprecation($name)] : []; - $currentId = $alias->getId(); - $visited = []; - while (null !== $alias = $routes->getAlias($currentId) ?? null) { - if (false !== $searchKey = array_search($currentId, $visited)) { - $visited[] = $currentId; - - throw new RouteCircularReferenceException($currentId, \array_slice($visited, $searchKey)); - } - - if ($alias->isDeprecated()) { - $deprecations[] = $deprecation = $alias->getDeprecation($currentId); - trigger_deprecation($deprecation['package'], $deprecation['version'], $deprecation['message']); - } - - $visited[] = $currentId; - $currentId = $alias->getId(); - } - - if (null === $target = $routes->get($currentId)) { - throw new RouteNotFoundException(sprintf('Target route "%s" for alias "%s" does not exist.', $currentId, $name)); - } - - $compiledTarget = $target->compile(); - - $compiledAliases[$name] = [ - $compiledTarget->getVariables(), - $target->getDefaults(), - $target->getRequirements(), - $compiledTarget->getTokens(), - $compiledTarget->getHostTokens(), - $target->getSchemes(), - $deprecations, - ]; - } - - return $compiledAliases; - } - - /** - * {@inheritdoc} - */ - public function dump(array $options = []) - { - return <<generateDeclaredRoutes()} -]; - -EOF; - } - - /** - * Generates PHP code representing an array of defined routes - * together with the routes properties (e.g. requirements). - */ - private function generateDeclaredRoutes(): string - { - $routes = ''; - foreach ($this->getCompiledRoutes() as $name => $properties) { - $routes .= sprintf("\n '%s' => %s,", $name, CompiledUrlMatcherDumper::export($properties)); - } - - foreach ($this->getCompiledAliases() as $alias => $properties) { - $routes .= sprintf("\n '%s' => %s,", $alias, CompiledUrlMatcherDumper::export($properties)); - } - - return $routes; - } -} diff --git a/digital_doctor/vendor/symfony/routing/Generator/Dumper/GeneratorDumper.php b/digital_doctor/vendor/symfony/routing/Generator/Dumper/GeneratorDumper.php deleted file mode 100644 index 659c5ba..0000000 --- a/digital_doctor/vendor/symfony/routing/Generator/Dumper/GeneratorDumper.php +++ /dev/null @@ -1,37 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Generator\Dumper; - -use Symfony\Component\Routing\RouteCollection; - -/** - * GeneratorDumper is the base class for all built-in generator dumpers. - * - * @author Fabien Potencier - */ -abstract class GeneratorDumper implements GeneratorDumperInterface -{ - private $routes; - - public function __construct(RouteCollection $routes) - { - $this->routes = $routes; - } - - /** - * {@inheritdoc} - */ - public function getRoutes() - { - return $this->routes; - } -} diff --git a/digital_doctor/vendor/symfony/routing/Generator/Dumper/GeneratorDumperInterface.php b/digital_doctor/vendor/symfony/routing/Generator/Dumper/GeneratorDumperInterface.php deleted file mode 100644 index d4a248a..0000000 --- a/digital_doctor/vendor/symfony/routing/Generator/Dumper/GeneratorDumperInterface.php +++ /dev/null @@ -1,37 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Generator\Dumper; - -use Symfony\Component\Routing\RouteCollection; - -/** - * GeneratorDumperInterface is the interface that all generator dumper classes must implement. - * - * @author Fabien Potencier - */ -interface GeneratorDumperInterface -{ - /** - * Dumps a set of routes to a string representation of executable code - * that can then be used to generate a URL of such a route. - * - * @return string - */ - public function dump(array $options = []); - - /** - * Gets the routes to dump. - * - * @return RouteCollection - */ - public function getRoutes(); -} diff --git a/digital_doctor/vendor/symfony/routing/Generator/UrlGenerator.php b/digital_doctor/vendor/symfony/routing/Generator/UrlGenerator.php deleted file mode 100644 index 4419e9e..0000000 --- a/digital_doctor/vendor/symfony/routing/Generator/UrlGenerator.php +++ /dev/null @@ -1,378 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Generator; - -use Psr\Log\LoggerInterface; -use Symfony\Component\Routing\Exception\InvalidParameterException; -use Symfony\Component\Routing\Exception\MissingMandatoryParametersException; -use Symfony\Component\Routing\Exception\RouteNotFoundException; -use Symfony\Component\Routing\RequestContext; -use Symfony\Component\Routing\RouteCollection; - -/** - * UrlGenerator can generate a URL or a path for any route in the RouteCollection - * based on the passed parameters. - * - * @author Fabien Potencier - * @author Tobias Schultze - */ -class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInterface -{ - private const QUERY_FRAGMENT_DECODED = [ - // RFC 3986 explicitly allows those in the query/fragment to reference other URIs unencoded - '%2F' => '/', - '%3F' => '?', - // reserved chars that have no special meaning for HTTP URIs in a query or fragment - // this excludes esp. "&", "=" and also "+" because PHP would treat it as a space (form-encoded) - '%40' => '@', - '%3A' => ':', - '%21' => '!', - '%3B' => ';', - '%2C' => ',', - '%2A' => '*', - ]; - - protected $routes; - protected $context; - - /** - * @var bool|null - */ - protected $strictRequirements = true; - - protected $logger; - - private $defaultLocale; - - /** - * This array defines the characters (besides alphanumeric ones) that will not be percent-encoded in the path segment of the generated URL. - * - * PHP's rawurlencode() encodes all chars except "a-zA-Z0-9-._~" according to RFC 3986. But we want to allow some chars - * to be used in their literal form (reasons below). Other chars inside the path must of course be encoded, e.g. - * "?" and "#" (would be interpreted wrongly as query and fragment identifier), - * "'" and """ (are used as delimiters in HTML). - */ - protected $decodedChars = [ - // the slash can be used to designate a hierarchical structure and we want allow using it with this meaning - // some webservers don't allow the slash in encoded form in the path for security reasons anyway - // see http://stackoverflow.com/questions/4069002/http-400-if-2f-part-of-get-url-in-jboss - '%2F' => '/', - '%252F' => '%2F', - // the following chars are general delimiters in the URI specification but have only special meaning in the authority component - // so they can safely be used in the path in unencoded form - '%40' => '@', - '%3A' => ':', - // these chars are only sub-delimiters that have no predefined meaning and can therefore be used literally - // so URI producing applications can use these chars to delimit subcomponents in a path segment without being encoded for better readability - '%3B' => ';', - '%2C' => ',', - '%3D' => '=', - '%2B' => '+', - '%21' => '!', - '%2A' => '*', - '%7C' => '|', - ]; - - public function __construct(RouteCollection $routes, RequestContext $context, ?LoggerInterface $logger = null, ?string $defaultLocale = null) - { - $this->routes = $routes; - $this->context = $context; - $this->logger = $logger; - $this->defaultLocale = $defaultLocale; - } - - /** - * {@inheritdoc} - */ - public function setContext(RequestContext $context) - { - $this->context = $context; - } - - /** - * {@inheritdoc} - */ - public function getContext() - { - return $this->context; - } - - /** - * {@inheritdoc} - */ - public function setStrictRequirements(?bool $enabled) - { - $this->strictRequirements = $enabled; - } - - /** - * {@inheritdoc} - */ - public function isStrictRequirements() - { - return $this->strictRequirements; - } - - /** - * {@inheritdoc} - */ - public function generate(string $name, array $parameters = [], int $referenceType = self::ABSOLUTE_PATH) - { - $route = null; - $locale = $parameters['_locale'] - ?? $this->context->getParameter('_locale') - ?: $this->defaultLocale; - - if (null !== $locale) { - do { - if (null !== ($route = $this->routes->get($name.'.'.$locale)) && $route->getDefault('_canonical_route') === $name) { - break; - } - } while (false !== $locale = strstr($locale, '_', true)); - } - - if (null === $route = $route ?? $this->routes->get($name)) { - throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name)); - } - - // the Route has a cache of its own and is not recompiled as long as it does not get modified - $compiledRoute = $route->compile(); - - $defaults = $route->getDefaults(); - $variables = $compiledRoute->getVariables(); - - if (isset($defaults['_canonical_route']) && isset($defaults['_locale'])) { - if (!\in_array('_locale', $variables, true)) { - unset($parameters['_locale']); - } elseif (!isset($parameters['_locale'])) { - $parameters['_locale'] = $defaults['_locale']; - } - } - - return $this->doGenerate($variables, $defaults, $route->getRequirements(), $compiledRoute->getTokens(), $parameters, $name, $referenceType, $compiledRoute->getHostTokens(), $route->getSchemes()); - } - - /** - * @return string - * - * @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route - * @throws InvalidParameterException When a parameter value for a placeholder is not correct because - * it does not match the requirement - */ - protected function doGenerate(array $variables, array $defaults, array $requirements, array $tokens, array $parameters, string $name, int $referenceType, array $hostTokens, array $requiredSchemes = []) - { - $variables = array_flip($variables); - $mergedParams = array_replace($defaults, $this->context->getParameters(), $parameters); - - // all params must be given - if ($diff = array_diff_key($variables, $mergedParams)) { - throw new MissingMandatoryParametersException(sprintf('Some mandatory parameters are missing ("%s") to generate a URL for route "%s".', implode('", "', array_keys($diff)), $name)); - } - - $url = ''; - $optional = true; - $message = 'Parameter "{parameter}" for route "{route}" must match "{expected}" ("{given}" given) to generate a corresponding URL.'; - foreach ($tokens as $token) { - if ('variable' === $token[0]) { - $varName = $token[3]; - // variable is not important by default - $important = $token[5] ?? false; - - if (!$optional || $important || !\array_key_exists($varName, $defaults) || (null !== $mergedParams[$varName] && (string) $mergedParams[$varName] !== (string) $defaults[$varName])) { - // check requirement (while ignoring look-around patterns) - if (null !== $this->strictRequirements && !preg_match('#^'.preg_replace('/\(\?(?:=|<=|!|strictRequirements) { - throw new InvalidParameterException(strtr($message, ['{parameter}' => $varName, '{route}' => $name, '{expected}' => $token[2], '{given}' => $mergedParams[$varName]])); - } - - if ($this->logger) { - $this->logger->error($message, ['parameter' => $varName, 'route' => $name, 'expected' => $token[2], 'given' => $mergedParams[$varName]]); - } - - return ''; - } - - $url = $token[1].$mergedParams[$varName].$url; - $optional = false; - } - } else { - // static text - $url = $token[1].$url; - $optional = false; - } - } - - if ('' === $url) { - $url = '/'; - } - - // the contexts base URL is already encoded (see Symfony\Component\HttpFoundation\Request) - $url = strtr(rawurlencode($url), $this->decodedChars); - - // the path segments "." and ".." are interpreted as relative reference when resolving a URI; see http://tools.ietf.org/html/rfc3986#section-3.3 - // so we need to encode them as they are not used for this purpose here - // otherwise we would generate a URI that, when followed by a user agent (e.g. browser), does not match this route - $url = strtr($url, ['/../' => '/%2E%2E/', '/./' => '/%2E/']); - if (str_ends_with($url, '/..')) { - $url = substr($url, 0, -2).'%2E%2E'; - } elseif (str_ends_with($url, '/.')) { - $url = substr($url, 0, -1).'%2E'; - } - - $schemeAuthority = ''; - $host = $this->context->getHost(); - $scheme = $this->context->getScheme(); - - if ($requiredSchemes) { - if (!\in_array($scheme, $requiredSchemes, true)) { - $referenceType = self::ABSOLUTE_URL; - $scheme = current($requiredSchemes); - } - } - - if ($hostTokens) { - $routeHost = ''; - foreach ($hostTokens as $token) { - if ('variable' === $token[0]) { - // check requirement (while ignoring look-around patterns) - if (null !== $this->strictRequirements && !preg_match('#^'.preg_replace('/\(\?(?:=|<=|!|strictRequirements) { - throw new InvalidParameterException(strtr($message, ['{parameter}' => $token[3], '{route}' => $name, '{expected}' => $token[2], '{given}' => $mergedParams[$token[3]]])); - } - - if ($this->logger) { - $this->logger->error($message, ['parameter' => $token[3], 'route' => $name, 'expected' => $token[2], 'given' => $mergedParams[$token[3]]]); - } - - return ''; - } - - $routeHost = $token[1].$mergedParams[$token[3]].$routeHost; - } else { - $routeHost = $token[1].$routeHost; - } - } - - if ($routeHost !== $host) { - $host = $routeHost; - if (self::ABSOLUTE_URL !== $referenceType) { - $referenceType = self::NETWORK_PATH; - } - } - } - - if (self::ABSOLUTE_URL === $referenceType || self::NETWORK_PATH === $referenceType) { - if ('' !== $host || ('' !== $scheme && 'http' !== $scheme && 'https' !== $scheme)) { - $port = ''; - if ('http' === $scheme && 80 !== $this->context->getHttpPort()) { - $port = ':'.$this->context->getHttpPort(); - } elseif ('https' === $scheme && 443 !== $this->context->getHttpsPort()) { - $port = ':'.$this->context->getHttpsPort(); - } - - $schemeAuthority = self::NETWORK_PATH === $referenceType || '' === $scheme ? '//' : "$scheme://"; - $schemeAuthority .= $host.$port; - } - } - - if (self::RELATIVE_PATH === $referenceType) { - $url = self::getRelativePath($this->context->getPathInfo(), $url); - } else { - $url = $schemeAuthority.$this->context->getBaseUrl().$url; - } - - // add a query string if needed - $extra = array_udiff_assoc(array_diff_key($parameters, $variables), $defaults, function ($a, $b) { - return $a == $b ? 0 : 1; - }); - - array_walk_recursive($extra, $caster = static function (&$v) use (&$caster) { - if (\is_object($v)) { - if ($vars = get_object_vars($v)) { - array_walk_recursive($vars, $caster); - $v = $vars; - } elseif (method_exists($v, '__toString')) { - $v = (string) $v; - } - } - }); - - // extract fragment - $fragment = $defaults['_fragment'] ?? ''; - - if (isset($extra['_fragment'])) { - $fragment = $extra['_fragment']; - unset($extra['_fragment']); - } - - if ($extra && $query = http_build_query($extra, '', '&', \PHP_QUERY_RFC3986)) { - $url .= '?'.strtr($query, self::QUERY_FRAGMENT_DECODED); - } - - if ('' !== $fragment) { - $url .= '#'.strtr(rawurlencode($fragment), self::QUERY_FRAGMENT_DECODED); - } - - return $url; - } - - /** - * Returns the target path as relative reference from the base path. - * - * Only the URIs path component (no schema, host etc.) is relevant and must be given, starting with a slash. - * Both paths must be absolute and not contain relative parts. - * Relative URLs from one resource to another are useful when generating self-contained downloadable document archives. - * Furthermore, they can be used to reduce the link size in documents. - * - * Example target paths, given a base path of "/a/b/c/d": - * - "/a/b/c/d" -> "" - * - "/a/b/c/" -> "./" - * - "/a/b/" -> "../" - * - "/a/b/c/other" -> "other" - * - "/a/x/y" -> "../../x/y" - * - * @param string $basePath The base path - * @param string $targetPath The target path - * - * @return string - */ - public static function getRelativePath(string $basePath, string $targetPath) - { - if ($basePath === $targetPath) { - return ''; - } - - $sourceDirs = explode('/', isset($basePath[0]) && '/' === $basePath[0] ? substr($basePath, 1) : $basePath); - $targetDirs = explode('/', isset($targetPath[0]) && '/' === $targetPath[0] ? substr($targetPath, 1) : $targetPath); - array_pop($sourceDirs); - $targetFile = array_pop($targetDirs); - - foreach ($sourceDirs as $i => $dir) { - if (isset($targetDirs[$i]) && $dir === $targetDirs[$i]) { - unset($sourceDirs[$i], $targetDirs[$i]); - } else { - break; - } - } - - $targetDirs[] = $targetFile; - $path = str_repeat('../', \count($sourceDirs)).implode('/', $targetDirs); - - // A reference to the same base directory or an empty subdirectory must be prefixed with "./". - // This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used - // as the first segment of a relative-path reference, as it would be mistaken for a scheme name - // (see http://tools.ietf.org/html/rfc3986#section-4.2). - return '' === $path || '/' === $path[0] - || false !== ($colonPos = strpos($path, ':')) && ($colonPos < ($slashPos = strpos($path, '/')) || false === $slashPos) - ? "./$path" : $path; - } -} diff --git a/digital_doctor/vendor/symfony/routing/Generator/UrlGeneratorInterface.php b/digital_doctor/vendor/symfony/routing/Generator/UrlGeneratorInterface.php deleted file mode 100644 index c6d5005..0000000 --- a/digital_doctor/vendor/symfony/routing/Generator/UrlGeneratorInterface.php +++ /dev/null @@ -1,82 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Generator; - -use Symfony\Component\Routing\Exception\InvalidParameterException; -use Symfony\Component\Routing\Exception\MissingMandatoryParametersException; -use Symfony\Component\Routing\Exception\RouteNotFoundException; -use Symfony\Component\Routing\RequestContextAwareInterface; - -/** - * UrlGeneratorInterface is the interface that all URL generator classes must implement. - * - * The constants in this interface define the different types of resource references that - * are declared in RFC 3986: http://tools.ietf.org/html/rfc3986 - * We are using the term "URL" instead of "URI" as this is more common in web applications - * and we do not need to distinguish them as the difference is mostly semantical and - * less technical. Generating URIs, i.e. representation-independent resource identifiers, - * is also possible. - * - * @author Fabien Potencier - * @author Tobias Schultze - */ -interface UrlGeneratorInterface extends RequestContextAwareInterface -{ - /** - * Generates an absolute URL, e.g. "http://example.com/dir/file". - */ - public const ABSOLUTE_URL = 0; - - /** - * Generates an absolute path, e.g. "/dir/file". - */ - public const ABSOLUTE_PATH = 1; - - /** - * Generates a relative path based on the current request path, e.g. "../parent-file". - * - * @see UrlGenerator::getRelativePath() - */ - public const RELATIVE_PATH = 2; - - /** - * Generates a network path, e.g. "//example.com/dir/file". - * Such reference reuses the current scheme but specifies the host. - */ - public const NETWORK_PATH = 3; - - /** - * Generates a URL or path for a specific route based on the given parameters. - * - * Parameters that reference placeholders in the route pattern will substitute them in the - * path or host. Extra params are added as query string to the URL. - * - * When the passed reference type cannot be generated for the route because it requires a different - * host or scheme than the current one, the method will return a more comprehensive reference - * that includes the required params. For example, when you call this method with $referenceType = ABSOLUTE_PATH - * but the route requires the https scheme whereas the current scheme is http, it will instead return an - * ABSOLUTE_URL with the https scheme and the current host. This makes sure the generated URL matches - * the route in any case. - * - * If there is no route with the given name, the generator must throw the RouteNotFoundException. - * - * The special parameter _fragment will be used as the document fragment suffixed to the final URL. - * - * @return string - * - * @throws RouteNotFoundException If the named route doesn't exist - * @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route - * @throws InvalidParameterException When a parameter value for a placeholder is not correct because - * it does not match the requirement - */ - public function generate(string $name, array $parameters = [], int $referenceType = self::ABSOLUTE_PATH); -} diff --git a/digital_doctor/vendor/symfony/routing/LICENSE b/digital_doctor/vendor/symfony/routing/LICENSE deleted file mode 100644 index 0138f8f..0000000 --- a/digital_doctor/vendor/symfony/routing/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2004-present Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/digital_doctor/vendor/symfony/routing/Loader/AnnotationClassLoader.php b/digital_doctor/vendor/symfony/routing/Loader/AnnotationClassLoader.php deleted file mode 100644 index c0bcb47..0000000 --- a/digital_doctor/vendor/symfony/routing/Loader/AnnotationClassLoader.php +++ /dev/null @@ -1,394 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Doctrine\Common\Annotations\Reader; -use Symfony\Component\Config\Loader\LoaderInterface; -use Symfony\Component\Config\Loader\LoaderResolverInterface; -use Symfony\Component\Config\Resource\FileResource; -use Symfony\Component\Routing\Annotation\Route as RouteAnnotation; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -/** - * AnnotationClassLoader loads routing information from a PHP class and its methods. - * - * You need to define an implementation for the configureRoute() method. Most of the - * time, this method should define some PHP callable to be called for the route - * (a controller in MVC speak). - * - * The @Route annotation can be set on the class (for global parameters), - * and on each method. - * - * The @Route annotation main value is the route path. The annotation also - * recognizes several parameters: requirements, options, defaults, schemes, - * methods, host, and name. The name parameter is mandatory. - * Here is an example of how you should be able to use it: - * /** - * * @Route("/Blog") - * * / - * class Blog - * { - * /** - * * @Route("/", name="blog_index") - * * / - * public function index() - * { - * } - * /** - * * @Route("/{id}", name="blog_post", requirements = {"id" = "\d+"}) - * * / - * public function show() - * { - * } - * } - * - * On PHP 8, the annotation class can be used as an attribute as well: - * #[Route('/Blog')] - * class Blog - * { - * #[Route('/', name: 'blog_index')] - * public function index() - * { - * } - * #[Route('/{id}', name: 'blog_post', requirements: ["id" => '\d+'])] - * public function show() - * { - * } - * } - - * - * @author Fabien Potencier - * @author Alexander M. Turek - */ -abstract class AnnotationClassLoader implements LoaderInterface -{ - protected $reader; - protected $env; - - /** - * @var string - */ - protected $routeAnnotationClass = RouteAnnotation::class; - - /** - * @var int - */ - protected $defaultRouteIndex = 0; - - public function __construct(?Reader $reader = null, ?string $env = null) - { - $this->reader = $reader; - $this->env = $env; - } - - /** - * Sets the annotation class to read route properties from. - */ - public function setRouteAnnotationClass(string $class) - { - $this->routeAnnotationClass = $class; - } - - /** - * Loads from annotations from a class. - * - * @param string $class A class name - * - * @return RouteCollection - * - * @throws \InvalidArgumentException When route can't be parsed - */ - public function load($class, ?string $type = null) - { - if (!class_exists($class)) { - throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class)); - } - - $class = new \ReflectionClass($class); - if ($class->isAbstract()) { - throw new \InvalidArgumentException(sprintf('Annotations from class "%s" cannot be read as it is abstract.', $class->getName())); - } - - $globals = $this->getGlobals($class); - - $collection = new RouteCollection(); - $collection->addResource(new FileResource($class->getFileName())); - - if ($globals['env'] && $this->env !== $globals['env']) { - return $collection; - } - - foreach ($class->getMethods() as $method) { - $this->defaultRouteIndex = 0; - foreach ($this->getAnnotations($method) as $annot) { - $this->addRoute($collection, $annot, $globals, $class, $method); - } - } - - if (0 === $collection->count() && $class->hasMethod('__invoke')) { - $globals = $this->resetGlobals(); - foreach ($this->getAnnotations($class) as $annot) { - $this->addRoute($collection, $annot, $globals, $class, $class->getMethod('__invoke')); - } - } - - return $collection; - } - - /** - * @param RouteAnnotation $annot or an object that exposes a similar interface - */ - protected function addRoute(RouteCollection $collection, object $annot, array $globals, \ReflectionClass $class, \ReflectionMethod $method) - { - if ($annot->getEnv() && $annot->getEnv() !== $this->env) { - return; - } - - $name = $annot->getName(); - if (null === $name) { - $name = $this->getDefaultRouteName($class, $method); - } - $name = $globals['name'].$name; - - $requirements = $annot->getRequirements(); - - foreach ($requirements as $placeholder => $requirement) { - if (\is_int($placeholder)) { - throw new \InvalidArgumentException(sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" of route "%s" in "%s::%s()"?', $placeholder, $requirement, $name, $class->getName(), $method->getName())); - } - } - - $defaults = array_replace($globals['defaults'], $annot->getDefaults()); - $requirements = array_replace($globals['requirements'], $requirements); - $options = array_replace($globals['options'], $annot->getOptions()); - $schemes = array_merge($globals['schemes'], $annot->getSchemes()); - $methods = array_merge($globals['methods'], $annot->getMethods()); - - $host = $annot->getHost(); - if (null === $host) { - $host = $globals['host']; - } - - $condition = $annot->getCondition() ?? $globals['condition']; - $priority = $annot->getPriority() ?? $globals['priority']; - - $path = $annot->getLocalizedPaths() ?: $annot->getPath(); - $prefix = $globals['localized_paths'] ?: $globals['path']; - $paths = []; - - if (\is_array($path)) { - if (!\is_array($prefix)) { - foreach ($path as $locale => $localePath) { - $paths[$locale] = $prefix.$localePath; - } - } elseif ($missing = array_diff_key($prefix, $path)) { - throw new \LogicException(sprintf('Route to "%s" is missing paths for locale(s) "%s".', $class->name.'::'.$method->name, implode('", "', array_keys($missing)))); - } else { - foreach ($path as $locale => $localePath) { - if (!isset($prefix[$locale])) { - throw new \LogicException(sprintf('Route to "%s" with locale "%s" is missing a corresponding prefix in class "%s".', $method->name, $locale, $class->name)); - } - - $paths[$locale] = $prefix[$locale].$localePath; - } - } - } elseif (\is_array($prefix)) { - foreach ($prefix as $locale => $localePrefix) { - $paths[$locale] = $localePrefix.$path; - } - } else { - $paths[] = $prefix.$path; - } - - foreach ($method->getParameters() as $param) { - if (isset($defaults[$param->name]) || !$param->isDefaultValueAvailable()) { - continue; - } - foreach ($paths as $locale => $path) { - if (preg_match(sprintf('/\{%s(?:<.*?>)?\}/', preg_quote($param->name)), $path)) { - $defaults[$param->name] = $param->getDefaultValue(); - break; - } - } - } - - foreach ($paths as $locale => $path) { - $route = $this->createRoute($path, $defaults, $requirements, $options, $host, $schemes, $methods, $condition); - $this->configureRoute($route, $class, $method, $annot); - if (0 !== $locale) { - $route->setDefault('_locale', $locale); - $route->setRequirement('_locale', preg_quote($locale)); - $route->setDefault('_canonical_route', $name); - $collection->add($name.'.'.$locale, $route, $priority); - } else { - $collection->add($name, $route, $priority); - } - } - } - - /** - * {@inheritdoc} - */ - public function supports($resource, ?string $type = null) - { - return \is_string($resource) && preg_match('/^(?:\\\\?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)+$/', $resource) && (!$type || 'annotation' === $type); - } - - /** - * {@inheritdoc} - */ - public function setResolver(LoaderResolverInterface $resolver) - { - } - - /** - * {@inheritdoc} - */ - public function getResolver() - { - } - - /** - * Gets the default route name for a class method. - * - * @return string - */ - protected function getDefaultRouteName(\ReflectionClass $class, \ReflectionMethod $method) - { - $name = str_replace('\\', '_', $class->name).'_'.$method->name; - $name = \function_exists('mb_strtolower') && preg_match('//u', $name) ? mb_strtolower($name, 'UTF-8') : strtolower($name); - if ($this->defaultRouteIndex > 0) { - $name .= '_'.$this->defaultRouteIndex; - } - ++$this->defaultRouteIndex; - - return $name; - } - - protected function getGlobals(\ReflectionClass $class) - { - $globals = $this->resetGlobals(); - - $annot = null; - if (\PHP_VERSION_ID >= 80000 && ($attribute = $class->getAttributes($this->routeAnnotationClass, \ReflectionAttribute::IS_INSTANCEOF)[0] ?? null)) { - $annot = $attribute->newInstance(); - } - if (!$annot && $this->reader) { - $annot = $this->reader->getClassAnnotation($class, $this->routeAnnotationClass); - } - - if ($annot) { - if (null !== $annot->getName()) { - $globals['name'] = $annot->getName(); - } - - if (null !== $annot->getPath()) { - $globals['path'] = $annot->getPath(); - } - - $globals['localized_paths'] = $annot->getLocalizedPaths(); - - if (null !== $annot->getRequirements()) { - $globals['requirements'] = $annot->getRequirements(); - } - - if (null !== $annot->getOptions()) { - $globals['options'] = $annot->getOptions(); - } - - if (null !== $annot->getDefaults()) { - $globals['defaults'] = $annot->getDefaults(); - } - - if (null !== $annot->getSchemes()) { - $globals['schemes'] = $annot->getSchemes(); - } - - if (null !== $annot->getMethods()) { - $globals['methods'] = $annot->getMethods(); - } - - if (null !== $annot->getHost()) { - $globals['host'] = $annot->getHost(); - } - - if (null !== $annot->getCondition()) { - $globals['condition'] = $annot->getCondition(); - } - - $globals['priority'] = $annot->getPriority() ?? 0; - $globals['env'] = $annot->getEnv(); - - foreach ($globals['requirements'] as $placeholder => $requirement) { - if (\is_int($placeholder)) { - throw new \InvalidArgumentException(sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" in "%s"?', $placeholder, $requirement, $class->getName())); - } - } - } - - return $globals; - } - - private function resetGlobals(): array - { - return [ - 'path' => null, - 'localized_paths' => [], - 'requirements' => [], - 'options' => [], - 'defaults' => [], - 'schemes' => [], - 'methods' => [], - 'host' => '', - 'condition' => '', - 'name' => '', - 'priority' => 0, - 'env' => null, - ]; - } - - protected function createRoute(string $path, array $defaults, array $requirements, array $options, ?string $host, array $schemes, array $methods, ?string $condition) - { - return new Route($path, $defaults, $requirements, $options, $host, $schemes, $methods, $condition); - } - - abstract protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, object $annot); - - /** - * @param \ReflectionClass|\ReflectionMethod $reflection - * - * @return iterable - */ - private function getAnnotations(object $reflection): iterable - { - if (\PHP_VERSION_ID >= 80000) { - foreach ($reflection->getAttributes($this->routeAnnotationClass, \ReflectionAttribute::IS_INSTANCEOF) as $attribute) { - yield $attribute->newInstance(); - } - } - - if (!$this->reader) { - return; - } - - $anntotations = $reflection instanceof \ReflectionClass - ? $this->reader->getClassAnnotations($reflection) - : $this->reader->getMethodAnnotations($reflection); - - foreach ($anntotations as $annotation) { - if ($annotation instanceof $this->routeAnnotationClass) { - yield $annotation; - } - } - } -} diff --git a/digital_doctor/vendor/symfony/routing/Loader/AnnotationDirectoryLoader.php b/digital_doctor/vendor/symfony/routing/Loader/AnnotationDirectoryLoader.php deleted file mode 100644 index 8cd60f8..0000000 --- a/digital_doctor/vendor/symfony/routing/Loader/AnnotationDirectoryLoader.php +++ /dev/null @@ -1,93 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Symfony\Component\Config\Resource\DirectoryResource; -use Symfony\Component\Routing\RouteCollection; - -/** - * AnnotationDirectoryLoader loads routing information from annotations set - * on PHP classes and methods. - * - * @author Fabien Potencier - */ -class AnnotationDirectoryLoader extends AnnotationFileLoader -{ - /** - * Loads from annotations from a directory. - * - * @param string $path A directory path - * @param string|null $type The resource type - * - * @return RouteCollection - * - * @throws \InvalidArgumentException When the directory does not exist or its routes cannot be parsed - */ - public function load($path, ?string $type = null) - { - if (!is_dir($dir = $this->locator->locate($path))) { - return parent::supports($path, $type) ? parent::load($path, $type) : new RouteCollection(); - } - - $collection = new RouteCollection(); - $collection->addResource(new DirectoryResource($dir, '/\.php$/')); - $files = iterator_to_array(new \RecursiveIteratorIterator( - new \RecursiveCallbackFilterIterator( - new \RecursiveDirectoryIterator($dir, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS), - function (\SplFileInfo $current) { - return '.' !== substr($current->getBasename(), 0, 1); - } - ), - \RecursiveIteratorIterator::LEAVES_ONLY - )); - usort($files, function (\SplFileInfo $a, \SplFileInfo $b) { - return (string) $a > (string) $b ? 1 : -1; - }); - - foreach ($files as $file) { - if (!$file->isFile() || !str_ends_with($file->getFilename(), '.php')) { - continue; - } - - if ($class = $this->findClass($file)) { - $refl = new \ReflectionClass($class); - if ($refl->isAbstract()) { - continue; - } - - $collection->addCollection($this->loader->load($class, $type)); - } - } - - return $collection; - } - - /** - * {@inheritdoc} - */ - public function supports($resource, ?string $type = null) - { - if ('annotation' === $type) { - return true; - } - - if ($type || !\is_string($resource)) { - return false; - } - - try { - return is_dir($this->locator->locate($resource)); - } catch (\Exception $e) { - return false; - } - } -} diff --git a/digital_doctor/vendor/symfony/routing/Loader/AnnotationFileLoader.php b/digital_doctor/vendor/symfony/routing/Loader/AnnotationFileLoader.php deleted file mode 100644 index a1d70c0..0000000 --- a/digital_doctor/vendor/symfony/routing/Loader/AnnotationFileLoader.php +++ /dev/null @@ -1,146 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Symfony\Component\Config\FileLocatorInterface; -use Symfony\Component\Config\Loader\FileLoader; -use Symfony\Component\Config\Resource\FileResource; -use Symfony\Component\Routing\RouteCollection; - -/** - * AnnotationFileLoader loads routing information from annotations set - * on a PHP class and its methods. - * - * @author Fabien Potencier - */ -class AnnotationFileLoader extends FileLoader -{ - protected $loader; - - public function __construct(FileLocatorInterface $locator, AnnotationClassLoader $loader) - { - if (!\function_exists('token_get_all')) { - throw new \LogicException('The Tokenizer extension is required for the routing annotation loaders.'); - } - - parent::__construct($locator); - - $this->loader = $loader; - } - - /** - * Loads from annotations from a file. - * - * @param string $file A PHP file path - * @param string|null $type The resource type - * - * @return RouteCollection|null - * - * @throws \InvalidArgumentException When the file does not exist or its routes cannot be parsed - */ - public function load($file, ?string $type = null) - { - $path = $this->locator->locate($file); - - $collection = new RouteCollection(); - if ($class = $this->findClass($path)) { - $refl = new \ReflectionClass($class); - if ($refl->isAbstract()) { - return null; - } - - $collection->addResource(new FileResource($path)); - $collection->addCollection($this->loader->load($class, $type)); - } - - gc_mem_caches(); - - return $collection; - } - - /** - * {@inheritdoc} - */ - public function supports($resource, ?string $type = null) - { - return \is_string($resource) && 'php' === pathinfo($resource, \PATHINFO_EXTENSION) && (!$type || 'annotation' === $type); - } - - /** - * Returns the full class name for the first class in the file. - * - * @return string|false - */ - protected function findClass(string $file) - { - $class = false; - $namespace = false; - $tokens = token_get_all(file_get_contents($file)); - - if (1 === \count($tokens) && \T_INLINE_HTML === $tokens[0][0]) { - throw new \InvalidArgumentException(sprintf('The file "%s" does not contain PHP code. Did you forgot to add the " true, \T_STRING => true]; - if (\defined('T_NAME_QUALIFIED')) { - $nsTokens[\T_NAME_QUALIFIED] = true; - } - for ($i = 0; isset($tokens[$i]); ++$i) { - $token = $tokens[$i]; - if (!isset($token[1])) { - continue; - } - - if (true === $class && \T_STRING === $token[0]) { - return $namespace.'\\'.$token[1]; - } - - if (true === $namespace && isset($nsTokens[$token[0]])) { - $namespace = $token[1]; - while (isset($tokens[++$i][1], $nsTokens[$tokens[$i][0]])) { - $namespace .= $tokens[$i][1]; - } - $token = $tokens[$i]; - } - - if (\T_CLASS === $token[0]) { - // Skip usage of ::class constant and anonymous classes - $skipClassToken = false; - for ($j = $i - 1; $j > 0; --$j) { - if (!isset($tokens[$j][1])) { - if ('(' === $tokens[$j] || ',' === $tokens[$j]) { - $skipClassToken = true; - } - break; - } - - if (\T_DOUBLE_COLON === $tokens[$j][0] || \T_NEW === $tokens[$j][0]) { - $skipClassToken = true; - break; - } elseif (!\in_array($tokens[$j][0], [\T_WHITESPACE, \T_DOC_COMMENT, \T_COMMENT])) { - break; - } - } - - if (!$skipClassToken) { - $class = true; - } - } - - if (\T_NAMESPACE === $token[0]) { - $namespace = true; - } - } - - return false; - } -} diff --git a/digital_doctor/vendor/symfony/routing/Loader/ClosureLoader.php b/digital_doctor/vendor/symfony/routing/Loader/ClosureLoader.php deleted file mode 100644 index a5081ca..0000000 --- a/digital_doctor/vendor/symfony/routing/Loader/ClosureLoader.php +++ /dev/null @@ -1,46 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Symfony\Component\Config\Loader\Loader; -use Symfony\Component\Routing\RouteCollection; - -/** - * ClosureLoader loads routes from a PHP closure. - * - * The Closure must return a RouteCollection instance. - * - * @author Fabien Potencier - */ -class ClosureLoader extends Loader -{ - /** - * Loads a Closure. - * - * @param \Closure $closure A Closure - * @param string|null $type The resource type - * - * @return RouteCollection - */ - public function load($closure, ?string $type = null) - { - return $closure($this->env); - } - - /** - * {@inheritdoc} - */ - public function supports($resource, ?string $type = null) - { - return $resource instanceof \Closure && (!$type || 'closure' === $type); - } -} diff --git a/digital_doctor/vendor/symfony/routing/Loader/Configurator/AliasConfigurator.php b/digital_doctor/vendor/symfony/routing/Loader/Configurator/AliasConfigurator.php deleted file mode 100644 index 4b2206e..0000000 --- a/digital_doctor/vendor/symfony/routing/Loader/Configurator/AliasConfigurator.php +++ /dev/null @@ -1,43 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader\Configurator; - -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\Routing\Alias; - -class AliasConfigurator -{ - private $alias; - - public function __construct(Alias $alias) - { - $this->alias = $alias; - } - - /** - * Whether this alias is deprecated, that means it should not be called anymore. - * - * @param string $package The name of the composer package that is triggering the deprecation - * @param string $version The version of the package that introduced the deprecation - * @param string $message The deprecation message to use - * - * @return $this - * - * @throws InvalidArgumentException when the message template is invalid - */ - public function deprecate(string $package, string $version, string $message): self - { - $this->alias->setDeprecated($package, $version, $message); - - return $this; - } -} diff --git a/digital_doctor/vendor/symfony/routing/Loader/Configurator/CollectionConfigurator.php b/digital_doctor/vendor/symfony/routing/Loader/Configurator/CollectionConfigurator.php deleted file mode 100644 index ec59f7e..0000000 --- a/digital_doctor/vendor/symfony/routing/Loader/Configurator/CollectionConfigurator.php +++ /dev/null @@ -1,125 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader\Configurator; - -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -/** - * @author Nicolas Grekas - */ -class CollectionConfigurator -{ - use Traits\AddTrait; - use Traits\HostTrait; - use Traits\RouteTrait; - - private $parent; - private $parentConfigurator; - private $parentPrefixes; - private $host; - - public function __construct(RouteCollection $parent, string $name, ?self $parentConfigurator = null, ?array $parentPrefixes = null) - { - $this->parent = $parent; - $this->name = $name; - $this->collection = new RouteCollection(); - $this->route = new Route(''); - $this->parentConfigurator = $parentConfigurator; // for GC control - $this->parentPrefixes = $parentPrefixes; - } - - /** - * @return array - */ - public function __sleep() - { - throw new \BadMethodCallException('Cannot serialize '.__CLASS__); - } - - public function __wakeup() - { - throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); - } - - public function __destruct() - { - if (null === $this->prefixes) { - $this->collection->addPrefix($this->route->getPath()); - } - if (null !== $this->host) { - $this->addHost($this->collection, $this->host); - } - - $this->parent->addCollection($this->collection); - } - - /** - * Creates a sub-collection. - */ - final public function collection(string $name = ''): self - { - return new self($this->collection, $this->name.$name, $this, $this->prefixes); - } - - /** - * Sets the prefix to add to the path of all child routes. - * - * @param string|array $prefix the prefix, or the localized prefixes - * - * @return $this - */ - final public function prefix($prefix): self - { - if (\is_array($prefix)) { - if (null === $this->parentPrefixes) { - // no-op - } elseif ($missing = array_diff_key($this->parentPrefixes, $prefix)) { - throw new \LogicException(sprintf('Collection "%s" is missing prefixes for locale(s) "%s".', $this->name, implode('", "', array_keys($missing)))); - } else { - foreach ($prefix as $locale => $localePrefix) { - if (!isset($this->parentPrefixes[$locale])) { - throw new \LogicException(sprintf('Collection "%s" with locale "%s" is missing a corresponding prefix in its parent collection.', $this->name, $locale)); - } - - $prefix[$locale] = $this->parentPrefixes[$locale].$localePrefix; - } - } - $this->prefixes = $prefix; - $this->route->setPath('/'); - } else { - $this->prefixes = null; - $this->route->setPath($prefix); - } - - return $this; - } - - /** - * Sets the host to use for all child routes. - * - * @param string|array $host the host, or the localized hosts - * - * @return $this - */ - final public function host($host): self - { - $this->host = $host; - - return $this; - } - - private function createRoute(string $path): Route - { - return (clone $this->route)->setPath($path); - } -} diff --git a/digital_doctor/vendor/symfony/routing/Loader/Configurator/ImportConfigurator.php b/digital_doctor/vendor/symfony/routing/Loader/Configurator/ImportConfigurator.php deleted file mode 100644 index 32f3efe..0000000 --- a/digital_doctor/vendor/symfony/routing/Loader/Configurator/ImportConfigurator.php +++ /dev/null @@ -1,90 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader\Configurator; - -use Symfony\Component\Routing\RouteCollection; - -/** - * @author Nicolas Grekas - */ -class ImportConfigurator -{ - use Traits\HostTrait; - use Traits\PrefixTrait; - use Traits\RouteTrait; - - private $parent; - - public function __construct(RouteCollection $parent, RouteCollection $route) - { - $this->parent = $parent; - $this->route = $route; - } - - /** - * @return array - */ - public function __sleep() - { - throw new \BadMethodCallException('Cannot serialize '.__CLASS__); - } - - public function __wakeup() - { - throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); - } - - public function __destruct() - { - $this->parent->addCollection($this->route); - } - - /** - * Sets the prefix to add to the path of all child routes. - * - * @param string|array $prefix the prefix, or the localized prefixes - * - * @return $this - */ - final public function prefix($prefix, bool $trailingSlashOnRoot = true): self - { - $this->addPrefix($this->route, $prefix, $trailingSlashOnRoot); - - return $this; - } - - /** - * Sets the prefix to add to the name of all child routes. - * - * @return $this - */ - final public function namePrefix(string $namePrefix): self - { - $this->route->addNamePrefix($namePrefix); - - return $this; - } - - /** - * Sets the host to use for all child routes. - * - * @param string|array $host the host, or the localized hosts - * - * @return $this - */ - final public function host($host): self - { - $this->addHost($this->route, $host); - - return $this; - } -} diff --git a/digital_doctor/vendor/symfony/routing/Loader/Configurator/RouteConfigurator.php b/digital_doctor/vendor/symfony/routing/Loader/Configurator/RouteConfigurator.php deleted file mode 100644 index fcd1c21..0000000 --- a/digital_doctor/vendor/symfony/routing/Loader/Configurator/RouteConfigurator.php +++ /dev/null @@ -1,49 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader\Configurator; - -use Symfony\Component\Routing\RouteCollection; - -/** - * @author Nicolas Grekas - */ -class RouteConfigurator -{ - use Traits\AddTrait; - use Traits\HostTrait; - use Traits\RouteTrait; - - protected $parentConfigurator; - - public function __construct(RouteCollection $collection, RouteCollection $route, string $name = '', ?CollectionConfigurator $parentConfigurator = null, ?array $prefixes = null) - { - $this->collection = $collection; - $this->route = $route; - $this->name = $name; - $this->parentConfigurator = $parentConfigurator; // for GC control - $this->prefixes = $prefixes; - } - - /** - * Sets the host to use for all child routes. - * - * @param string|array $host the host, or the localized hosts - * - * @return $this - */ - final public function host($host): self - { - $this->addHost($this->route, $host); - - return $this; - } -} diff --git a/digital_doctor/vendor/symfony/routing/Loader/Configurator/RoutingConfigurator.php b/digital_doctor/vendor/symfony/routing/Loader/Configurator/RoutingConfigurator.php deleted file mode 100644 index 620b2d5..0000000 --- a/digital_doctor/vendor/symfony/routing/Loader/Configurator/RoutingConfigurator.php +++ /dev/null @@ -1,81 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader\Configurator; - -use Symfony\Component\Routing\Loader\PhpFileLoader; -use Symfony\Component\Routing\RouteCollection; - -/** - * @author Nicolas Grekas - */ -class RoutingConfigurator -{ - use Traits\AddTrait; - - private $loader; - private $path; - private $file; - private $env; - - public function __construct(RouteCollection $collection, PhpFileLoader $loader, string $path, string $file, ?string $env = null) - { - $this->collection = $collection; - $this->loader = $loader; - $this->path = $path; - $this->file = $file; - $this->env = $env; - } - - /** - * @param string|string[]|null $exclude Glob patterns to exclude from the import - */ - final public function import($resource, ?string $type = null, bool $ignoreErrors = false, $exclude = null): ImportConfigurator - { - $this->loader->setCurrentDir(\dirname($this->path)); - - $imported = $this->loader->import($resource, $type, $ignoreErrors, $this->file, $exclude) ?: []; - if (!\is_array($imported)) { - return new ImportConfigurator($this->collection, $imported); - } - - $mergedCollection = new RouteCollection(); - foreach ($imported as $subCollection) { - $mergedCollection->addCollection($subCollection); - } - - return new ImportConfigurator($this->collection, $mergedCollection); - } - - final public function collection(string $name = ''): CollectionConfigurator - { - return new CollectionConfigurator($this->collection, $name); - } - - /** - * Get the current environment to be able to write conditional configuration. - */ - final public function env(): ?string - { - return $this->env; - } - - /** - * @return static - */ - final public function withPath(string $path): self - { - $clone = clone $this; - $clone->path = $clone->file = $path; - - return $clone; - } -} diff --git a/digital_doctor/vendor/symfony/routing/Loader/Configurator/Traits/AddTrait.php b/digital_doctor/vendor/symfony/routing/Loader/Configurator/Traits/AddTrait.php deleted file mode 100644 index 92b1bd0..0000000 --- a/digital_doctor/vendor/symfony/routing/Loader/Configurator/Traits/AddTrait.php +++ /dev/null @@ -1,60 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader\Configurator\Traits; - -use Symfony\Component\Routing\Loader\Configurator\AliasConfigurator; -use Symfony\Component\Routing\Loader\Configurator\CollectionConfigurator; -use Symfony\Component\Routing\Loader\Configurator\RouteConfigurator; -use Symfony\Component\Routing\RouteCollection; - -/** - * @author Nicolas Grekas - */ -trait AddTrait -{ - use LocalizedRouteTrait; - - /** - * @var RouteCollection - */ - protected $collection; - protected $name = ''; - protected $prefixes; - - /** - * Adds a route. - * - * @param string|array $path the path, or the localized paths of the route - */ - public function add(string $name, $path): RouteConfigurator - { - $parentConfigurator = $this instanceof CollectionConfigurator ? $this : ($this instanceof RouteConfigurator ? $this->parentConfigurator : null); - $route = $this->createLocalizedRoute($this->collection, $name, $path, $this->name, $this->prefixes); - - return new RouteConfigurator($this->collection, $route, $this->name, $parentConfigurator, $this->prefixes); - } - - public function alias(string $name, string $alias): AliasConfigurator - { - return new AliasConfigurator($this->collection->addAlias($name, $alias)); - } - - /** - * Adds a route. - * - * @param string|array $path the path, or the localized paths of the route - */ - public function __invoke(string $name, $path): RouteConfigurator - { - return $this->add($name, $path); - } -} diff --git a/digital_doctor/vendor/symfony/routing/Loader/Configurator/Traits/HostTrait.php b/digital_doctor/vendor/symfony/routing/Loader/Configurator/Traits/HostTrait.php deleted file mode 100644 index 54ae656..0000000 --- a/digital_doctor/vendor/symfony/routing/Loader/Configurator/Traits/HostTrait.php +++ /dev/null @@ -1,49 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader\Configurator\Traits; - -use Symfony\Component\Routing\RouteCollection; - -/** - * @internal - */ -trait HostTrait -{ - final protected function addHost(RouteCollection $routes, $hosts) - { - if (!$hosts || !\is_array($hosts)) { - $routes->setHost($hosts ?: ''); - - return; - } - - foreach ($routes->all() as $name => $route) { - if (null === $locale = $route->getDefault('_locale')) { - $routes->remove($name); - foreach ($hosts as $locale => $host) { - $localizedRoute = clone $route; - $localizedRoute->setDefault('_locale', $locale); - $localizedRoute->setRequirement('_locale', preg_quote($locale)); - $localizedRoute->setDefault('_canonical_route', $name); - $localizedRoute->setHost($host); - $routes->add($name.'.'.$locale, $localizedRoute); - } - } elseif (!isset($hosts[$locale])) { - throw new \InvalidArgumentException(sprintf('Route "%s" with locale "%s" is missing a corresponding host in its parent collection.', $name, $locale)); - } else { - $route->setHost($hosts[$locale]); - $route->setRequirement('_locale', preg_quote($locale)); - $routes->add($name, $route); - } - } - } -} diff --git a/digital_doctor/vendor/symfony/routing/Loader/Configurator/Traits/LocalizedRouteTrait.php b/digital_doctor/vendor/symfony/routing/Loader/Configurator/Traits/LocalizedRouteTrait.php deleted file mode 100644 index 44fb047..0000000 --- a/digital_doctor/vendor/symfony/routing/Loader/Configurator/Traits/LocalizedRouteTrait.php +++ /dev/null @@ -1,76 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader\Configurator\Traits; - -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -/** - * @internal - * - * @author Nicolas Grekas - * @author Jules Pietri - */ -trait LocalizedRouteTrait -{ - /** - * Creates one or many routes. - * - * @param string|array $path the path, or the localized paths of the route - */ - final protected function createLocalizedRoute(RouteCollection $collection, string $name, $path, string $namePrefix = '', ?array $prefixes = null): RouteCollection - { - $paths = []; - - $routes = new RouteCollection(); - - if (\is_array($path)) { - if (null === $prefixes) { - $paths = $path; - } elseif ($missing = array_diff_key($prefixes, $path)) { - throw new \LogicException(sprintf('Route "%s" is missing routes for locale(s) "%s".', $name, implode('", "', array_keys($missing)))); - } else { - foreach ($path as $locale => $localePath) { - if (!isset($prefixes[$locale])) { - throw new \LogicException(sprintf('Route "%s" with locale "%s" is missing a corresponding prefix in its parent collection.', $name, $locale)); - } - - $paths[$locale] = $prefixes[$locale].$localePath; - } - } - } elseif (null !== $prefixes) { - foreach ($prefixes as $locale => $prefix) { - $paths[$locale] = $prefix.$path; - } - } else { - $routes->add($namePrefix.$name, $route = $this->createRoute($path)); - $collection->add($namePrefix.$name, $route); - - return $routes; - } - - foreach ($paths as $locale => $path) { - $routes->add($name.'.'.$locale, $route = $this->createRoute($path)); - $collection->add($namePrefix.$name.'.'.$locale, $route); - $route->setDefault('_locale', $locale); - $route->setRequirement('_locale', preg_quote($locale)); - $route->setDefault('_canonical_route', $namePrefix.$name); - } - - return $routes; - } - - private function createRoute(string $path): Route - { - return new Route($path); - } -} diff --git a/digital_doctor/vendor/symfony/routing/Loader/Configurator/Traits/PrefixTrait.php b/digital_doctor/vendor/symfony/routing/Loader/Configurator/Traits/PrefixTrait.php deleted file mode 100644 index 0b19573..0000000 --- a/digital_doctor/vendor/symfony/routing/Loader/Configurator/Traits/PrefixTrait.php +++ /dev/null @@ -1,63 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader\Configurator\Traits; - -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -/** - * @internal - * - * @author Nicolas Grekas - */ -trait PrefixTrait -{ - final protected function addPrefix(RouteCollection $routes, $prefix, bool $trailingSlashOnRoot) - { - if (\is_array($prefix)) { - foreach ($prefix as $locale => $localePrefix) { - $prefix[$locale] = trim(trim($localePrefix), '/'); - } - foreach ($routes->all() as $name => $route) { - if (null === $locale = $route->getDefault('_locale')) { - $priority = $routes->getPriority($name) ?? 0; - $routes->remove($name); - foreach ($prefix as $locale => $localePrefix) { - $localizedRoute = clone $route; - $localizedRoute->setDefault('_locale', $locale); - $localizedRoute->setRequirement('_locale', preg_quote($locale)); - $localizedRoute->setDefault('_canonical_route', $name); - $localizedRoute->setPath($localePrefix.(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath())); - $routes->add($name.'.'.$locale, $localizedRoute, $priority); - } - } elseif (!isset($prefix[$locale])) { - throw new \InvalidArgumentException(sprintf('Route "%s" with locale "%s" is missing a corresponding prefix in its parent collection.', $name, $locale)); - } else { - $route->setPath($prefix[$locale].(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath())); - $routes->add($name, $route, $routes->getPriority($name) ?? 0); - } - } - - return; - } - - $routes->addPrefix($prefix); - if (!$trailingSlashOnRoot) { - $rootPath = (new Route(trim(trim($prefix), '/').'/'))->getPath(); - foreach ($routes->all() as $route) { - if ($route->getPath() === $rootPath) { - $route->setPath(rtrim($rootPath, '/')); - } - } - } - } -} diff --git a/digital_doctor/vendor/symfony/routing/Loader/Configurator/Traits/RouteTrait.php b/digital_doctor/vendor/symfony/routing/Loader/Configurator/Traits/RouteTrait.php deleted file mode 100644 index ac05d10..0000000 --- a/digital_doctor/vendor/symfony/routing/Loader/Configurator/Traits/RouteTrait.php +++ /dev/null @@ -1,175 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader\Configurator\Traits; - -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -trait RouteTrait -{ - /** - * @var RouteCollection|Route - */ - protected $route; - - /** - * Adds defaults. - * - * @return $this - */ - final public function defaults(array $defaults): self - { - $this->route->addDefaults($defaults); - - return $this; - } - - /** - * Adds requirements. - * - * @return $this - */ - final public function requirements(array $requirements): self - { - $this->route->addRequirements($requirements); - - return $this; - } - - /** - * Adds options. - * - * @return $this - */ - final public function options(array $options): self - { - $this->route->addOptions($options); - - return $this; - } - - /** - * Whether paths should accept utf8 encoding. - * - * @return $this - */ - final public function utf8(bool $utf8 = true): self - { - $this->route->addOptions(['utf8' => $utf8]); - - return $this; - } - - /** - * Sets the condition. - * - * @return $this - */ - final public function condition(string $condition): self - { - $this->route->setCondition($condition); - - return $this; - } - - /** - * Sets the pattern for the host. - * - * @return $this - */ - final public function host(string $pattern): self - { - $this->route->setHost($pattern); - - return $this; - } - - /** - * Sets the schemes (e.g. 'https') this route is restricted to. - * So an empty array means that any scheme is allowed. - * - * @param string[] $schemes - * - * @return $this - */ - final public function schemes(array $schemes): self - { - $this->route->setSchemes($schemes); - - return $this; - } - - /** - * Sets the HTTP methods (e.g. 'POST') this route is restricted to. - * So an empty array means that any method is allowed. - * - * @param string[] $methods - * - * @return $this - */ - final public function methods(array $methods): self - { - $this->route->setMethods($methods); - - return $this; - } - - /** - * Adds the "_controller" entry to defaults. - * - * @param callable|string|array $controller a callable or parseable pseudo-callable - * - * @return $this - */ - final public function controller($controller): self - { - $this->route->addDefaults(['_controller' => $controller]); - - return $this; - } - - /** - * Adds the "_locale" entry to defaults. - * - * @return $this - */ - final public function locale(string $locale): self - { - $this->route->addDefaults(['_locale' => $locale]); - - return $this; - } - - /** - * Adds the "_format" entry to defaults. - * - * @return $this - */ - final public function format(string $format): self - { - $this->route->addDefaults(['_format' => $format]); - - return $this; - } - - /** - * Adds the "_stateless" entry to defaults. - * - * @return $this - */ - final public function stateless(bool $stateless = true): self - { - $this->route->addDefaults(['_stateless' => $stateless]); - - return $this; - } -} diff --git a/digital_doctor/vendor/symfony/routing/Loader/ContainerLoader.php b/digital_doctor/vendor/symfony/routing/Loader/ContainerLoader.php deleted file mode 100644 index a03d465..0000000 --- a/digital_doctor/vendor/symfony/routing/Loader/ContainerLoader.php +++ /dev/null @@ -1,46 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Psr\Container\ContainerInterface; - -/** - * A route loader that executes a service from a PSR-11 container to load the routes. - * - * @author Ryan Weaver - */ -class ContainerLoader extends ObjectLoader -{ - private $container; - - public function __construct(ContainerInterface $container, ?string $env = null) - { - $this->container = $container; - parent::__construct($env); - } - - /** - * {@inheritdoc} - */ - public function supports($resource, ?string $type = null) - { - return 'service' === $type && \is_string($resource); - } - - /** - * {@inheritdoc} - */ - protected function getObject(string $id) - { - return $this->container->get($id); - } -} diff --git a/digital_doctor/vendor/symfony/routing/Loader/DirectoryLoader.php b/digital_doctor/vendor/symfony/routing/Loader/DirectoryLoader.php deleted file mode 100644 index 24cf185..0000000 --- a/digital_doctor/vendor/symfony/routing/Loader/DirectoryLoader.php +++ /dev/null @@ -1,58 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Symfony\Component\Config\Loader\FileLoader; -use Symfony\Component\Config\Resource\DirectoryResource; -use Symfony\Component\Routing\RouteCollection; - -class DirectoryLoader extends FileLoader -{ - /** - * {@inheritdoc} - */ - public function load($file, ?string $type = null) - { - $path = $this->locator->locate($file); - - $collection = new RouteCollection(); - $collection->addResource(new DirectoryResource($path)); - - foreach (scandir($path) as $dir) { - if ('.' !== $dir[0]) { - $this->setCurrentDir($path); - $subPath = $path.'/'.$dir; - $subType = null; - - if (is_dir($subPath)) { - $subPath .= '/'; - $subType = 'directory'; - } - - $subCollection = $this->import($subPath, $subType, false, $path); - $collection->addCollection($subCollection); - } - } - - return $collection; - } - - /** - * {@inheritdoc} - */ - public function supports($resource, ?string $type = null) - { - // only when type is forced to directory, not to conflict with AnnotationLoader - - return 'directory' === $type; - } -} diff --git a/digital_doctor/vendor/symfony/routing/Loader/GlobFileLoader.php b/digital_doctor/vendor/symfony/routing/Loader/GlobFileLoader.php deleted file mode 100644 index 9c2f4ed..0000000 --- a/digital_doctor/vendor/symfony/routing/Loader/GlobFileLoader.php +++ /dev/null @@ -1,47 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Symfony\Component\Config\Loader\FileLoader; -use Symfony\Component\Routing\RouteCollection; - -/** - * GlobFileLoader loads files from a glob pattern. - * - * @author Nicolas Grekas - */ -class GlobFileLoader extends FileLoader -{ - /** - * {@inheritdoc} - */ - public function load($resource, ?string $type = null) - { - $collection = new RouteCollection(); - - foreach ($this->glob($resource, false, $globResource) as $path => $info) { - $collection->addCollection($this->import($path)); - } - - $collection->addResource($globResource); - - return $collection; - } - - /** - * {@inheritdoc} - */ - public function supports($resource, ?string $type = null) - { - return 'glob' === $type; - } -} diff --git a/digital_doctor/vendor/symfony/routing/Loader/ObjectLoader.php b/digital_doctor/vendor/symfony/routing/Loader/ObjectLoader.php deleted file mode 100644 index d212f8e..0000000 --- a/digital_doctor/vendor/symfony/routing/Loader/ObjectLoader.php +++ /dev/null @@ -1,84 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Symfony\Component\Config\Loader\Loader; -use Symfony\Component\Config\Resource\FileResource; -use Symfony\Component\Routing\RouteCollection; - -/** - * A route loader that calls a method on an object to load the routes. - * - * @author Ryan Weaver - */ -abstract class ObjectLoader extends Loader -{ - /** - * Returns the object that the method will be called on to load routes. - * - * For example, if your application uses a service container, - * the $id may be a service id. - * - * @return object - */ - abstract protected function getObject(string $id); - - /** - * Calls the object method that will load the routes. - * - * @param string $resource object_id::method - * @param string|null $type The resource type - * - * @return RouteCollection - */ - public function load($resource, ?string $type = null) - { - if (!preg_match('/^[^\:]+(?:::(?:[^\:]+))?$/', $resource)) { - throw new \InvalidArgumentException(sprintf('Invalid resource "%s" passed to the %s route loader: use the format "object_id::method" or "object_id" if your object class has an "__invoke" method.', $resource, \is_string($type) ? '"'.$type.'"' : 'object')); - } - - $parts = explode('::', $resource); - $method = $parts[1] ?? '__invoke'; - - $loaderObject = $this->getObject($parts[0]); - - if (!\is_object($loaderObject)) { - throw new \TypeError(sprintf('"%s:getObject()" must return an object: "%s" returned.', static::class, get_debug_type($loaderObject))); - } - - if (!\is_callable([$loaderObject, $method])) { - throw new \BadMethodCallException(sprintf('Method "%s" not found on "%s" when importing routing resource "%s".', $method, get_debug_type($loaderObject), $resource)); - } - - $routeCollection = $loaderObject->$method($this, $this->env); - - if (!$routeCollection instanceof RouteCollection) { - $type = get_debug_type($routeCollection); - - throw new \LogicException(sprintf('The "%s::%s()" method must return a RouteCollection: "%s" returned.', get_debug_type($loaderObject), $method, $type)); - } - - // make the object file tracked so that if it changes, the cache rebuilds - $this->addClassResource(new \ReflectionClass($loaderObject), $routeCollection); - - return $routeCollection; - } - - private function addClassResource(\ReflectionClass $class, RouteCollection $collection) - { - do { - if (is_file($class->getFileName())) { - $collection->addResource(new FileResource($class->getFileName())); - } - } while ($class = $class->getParentClass()); - } -} diff --git a/digital_doctor/vendor/symfony/routing/Loader/PhpFileLoader.php b/digital_doctor/vendor/symfony/routing/Loader/PhpFileLoader.php deleted file mode 100644 index 3f1cf9c..0000000 --- a/digital_doctor/vendor/symfony/routing/Loader/PhpFileLoader.php +++ /dev/null @@ -1,85 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Symfony\Component\Config\Loader\FileLoader; -use Symfony\Component\Config\Resource\FileResource; -use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator; -use Symfony\Component\Routing\RouteCollection; - -/** - * PhpFileLoader loads routes from a PHP file. - * - * The file must return a RouteCollection instance. - * - * @author Fabien Potencier - * @author Nicolas grekas - * @author Jules Pietri - */ -class PhpFileLoader extends FileLoader -{ - /** - * Loads a PHP file. - * - * @param string $file A PHP file path - * @param string|null $type The resource type - * - * @return RouteCollection - */ - public function load($file, ?string $type = null) - { - $path = $this->locator->locate($file); - $this->setCurrentDir(\dirname($path)); - - // the closure forbids access to the private scope in the included file - $loader = $this; - $load = \Closure::bind(static function ($file) use ($loader) { - return include $file; - }, null, ProtectedPhpFileLoader::class); - - $result = $load($path); - - if (\is_object($result) && \is_callable($result)) { - $collection = $this->callConfigurator($result, $path, $file); - } else { - $collection = $result; - } - - $collection->addResource(new FileResource($path)); - - return $collection; - } - - /** - * {@inheritdoc} - */ - public function supports($resource, ?string $type = null) - { - return \is_string($resource) && 'php' === pathinfo($resource, \PATHINFO_EXTENSION) && (!$type || 'php' === $type); - } - - protected function callConfigurator(callable $result, string $path, string $file): RouteCollection - { - $collection = new RouteCollection(); - - $result(new RoutingConfigurator($collection, $this, $path, $file, $this->env)); - - return $collection; - } -} - -/** - * @internal - */ -final class ProtectedPhpFileLoader extends PhpFileLoader -{ -} diff --git a/digital_doctor/vendor/symfony/routing/Loader/XmlFileLoader.php b/digital_doctor/vendor/symfony/routing/Loader/XmlFileLoader.php deleted file mode 100644 index 85bb0ee..0000000 --- a/digital_doctor/vendor/symfony/routing/Loader/XmlFileLoader.php +++ /dev/null @@ -1,469 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Symfony\Component\Config\Loader\FileLoader; -use Symfony\Component\Config\Resource\FileResource; -use Symfony\Component\Config\Util\XmlUtils; -use Symfony\Component\Routing\Loader\Configurator\Traits\HostTrait; -use Symfony\Component\Routing\Loader\Configurator\Traits\LocalizedRouteTrait; -use Symfony\Component\Routing\Loader\Configurator\Traits\PrefixTrait; -use Symfony\Component\Routing\RouteCollection; - -/** - * XmlFileLoader loads XML routing files. - * - * @author Fabien Potencier - * @author Tobias Schultze - */ -class XmlFileLoader extends FileLoader -{ - use HostTrait; - use LocalizedRouteTrait; - use PrefixTrait; - - public const NAMESPACE_URI = 'http://symfony.com/schema/routing'; - public const SCHEME_PATH = '/schema/routing/routing-1.0.xsd'; - - /** - * Loads an XML file. - * - * @param string $file An XML file path - * @param string|null $type The resource type - * - * @return RouteCollection - * - * @throws \InvalidArgumentException when the file cannot be loaded or when the XML cannot be - * parsed because it does not validate against the scheme - */ - public function load($file, ?string $type = null) - { - $path = $this->locator->locate($file); - - $xml = $this->loadFile($path); - - $collection = new RouteCollection(); - $collection->addResource(new FileResource($path)); - - // process routes and imports - foreach ($xml->documentElement->childNodes as $node) { - if (!$node instanceof \DOMElement) { - continue; - } - - $this->parseNode($collection, $node, $path, $file); - } - - return $collection; - } - - /** - * Parses a node from a loaded XML file. - * - * @throws \InvalidArgumentException When the XML is invalid - */ - protected function parseNode(RouteCollection $collection, \DOMElement $node, string $path, string $file) - { - if (self::NAMESPACE_URI !== $node->namespaceURI) { - return; - } - - switch ($node->localName) { - case 'route': - $this->parseRoute($collection, $node, $path); - break; - case 'import': - $this->parseImport($collection, $node, $path, $file); - break; - case 'when': - if (!$this->env || $node->getAttribute('env') !== $this->env) { - break; - } - foreach ($node->childNodes as $node) { - if ($node instanceof \DOMElement) { - $this->parseNode($collection, $node, $path, $file); - } - } - break; - default: - throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "route" or "import".', $node->localName, $path)); - } - } - - /** - * {@inheritdoc} - */ - public function supports($resource, ?string $type = null) - { - return \is_string($resource) && 'xml' === pathinfo($resource, \PATHINFO_EXTENSION) && (!$type || 'xml' === $type); - } - - /** - * Parses a route and adds it to the RouteCollection. - * - * @throws \InvalidArgumentException When the XML is invalid - */ - protected function parseRoute(RouteCollection $collection, \DOMElement $node, string $path) - { - if ('' === $id = $node->getAttribute('id')) { - throw new \InvalidArgumentException(sprintf('The element in file "%s" must have an "id" attribute.', $path)); - } - - if ('' !== $alias = $node->getAttribute('alias')) { - $alias = $collection->addAlias($id, $alias); - - if ($deprecationInfo = $this->parseDeprecation($node, $path)) { - $alias->setDeprecated($deprecationInfo['package'], $deprecationInfo['version'], $deprecationInfo['message']); - } - - return; - } - - $schemes = preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, \PREG_SPLIT_NO_EMPTY); - $methods = preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, \PREG_SPLIT_NO_EMPTY); - - [$defaults, $requirements, $options, $condition, $paths, /* $prefixes */, $hosts] = $this->parseConfigs($node, $path); - - if (!$paths && '' === $node->getAttribute('path')) { - throw new \InvalidArgumentException(sprintf('The element in file "%s" must have a "path" attribute or child nodes.', $path)); - } - - if ($paths && '' !== $node->getAttribute('path')) { - throw new \InvalidArgumentException(sprintf('The element in file "%s" must not have both a "path" attribute and child nodes.', $path)); - } - - $routes = $this->createLocalizedRoute($collection, $id, $paths ?: $node->getAttribute('path')); - $routes->addDefaults($defaults); - $routes->addRequirements($requirements); - $routes->addOptions($options); - $routes->setSchemes($schemes); - $routes->setMethods($methods); - $routes->setCondition($condition); - - if (null !== $hosts) { - $this->addHost($routes, $hosts); - } - } - - /** - * Parses an import and adds the routes in the resource to the RouteCollection. - * - * @throws \InvalidArgumentException When the XML is invalid - */ - protected function parseImport(RouteCollection $collection, \DOMElement $node, string $path, string $file) - { - if ('' === $resource = $node->getAttribute('resource')) { - throw new \InvalidArgumentException(sprintf('The element in file "%s" must have a "resource" attribute.', $path)); - } - - $type = $node->getAttribute('type'); - $prefix = $node->getAttribute('prefix'); - $schemes = $node->hasAttribute('schemes') ? preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, \PREG_SPLIT_NO_EMPTY) : null; - $methods = $node->hasAttribute('methods') ? preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, \PREG_SPLIT_NO_EMPTY) : null; - $trailingSlashOnRoot = $node->hasAttribute('trailing-slash-on-root') ? XmlUtils::phpize($node->getAttribute('trailing-slash-on-root')) : true; - $namePrefix = $node->getAttribute('name-prefix') ?: null; - - [$defaults, $requirements, $options, $condition, /* $paths */, $prefixes, $hosts] = $this->parseConfigs($node, $path); - - if ('' !== $prefix && $prefixes) { - throw new \InvalidArgumentException(sprintf('The element in file "%s" must not have both a "prefix" attribute and child nodes.', $path)); - } - - $exclude = []; - foreach ($node->childNodes as $child) { - if ($child instanceof \DOMElement && $child->localName === $exclude && self::NAMESPACE_URI === $child->namespaceURI) { - $exclude[] = $child->nodeValue; - } - } - - if ($node->hasAttribute('exclude')) { - if ($exclude) { - throw new \InvalidArgumentException('You cannot use both the attribute "exclude" and tags at the same time.'); - } - $exclude = [$node->getAttribute('exclude')]; - } - - $this->setCurrentDir(\dirname($path)); - - /** @var RouteCollection[] $imported */ - $imported = $this->import($resource, '' !== $type ? $type : null, false, $file, $exclude) ?: []; - - if (!\is_array($imported)) { - $imported = [$imported]; - } - - foreach ($imported as $subCollection) { - $this->addPrefix($subCollection, $prefixes ?: $prefix, $trailingSlashOnRoot); - - if (null !== $hosts) { - $this->addHost($subCollection, $hosts); - } - - if (null !== $condition) { - $subCollection->setCondition($condition); - } - if (null !== $schemes) { - $subCollection->setSchemes($schemes); - } - if (null !== $methods) { - $subCollection->setMethods($methods); - } - if (null !== $namePrefix) { - $subCollection->addNamePrefix($namePrefix); - } - $subCollection->addDefaults($defaults); - $subCollection->addRequirements($requirements); - $subCollection->addOptions($options); - - $collection->addCollection($subCollection); - } - } - - /** - * @return \DOMDocument - * - * @throws \InvalidArgumentException When loading of XML file fails because of syntax errors - * or when the XML structure is not as expected by the scheme - - * see validate() - */ - protected function loadFile(string $file) - { - return XmlUtils::loadFile($file, __DIR__.static::SCHEME_PATH); - } - - /** - * Parses the config elements (default, requirement, option). - * - * @throws \InvalidArgumentException When the XML is invalid - */ - private function parseConfigs(\DOMElement $node, string $path): array - { - $defaults = []; - $requirements = []; - $options = []; - $condition = null; - $prefixes = []; - $paths = []; - $hosts = []; - - /** @var \DOMElement $n */ - foreach ($node->getElementsByTagNameNS(self::NAMESPACE_URI, '*') as $n) { - if ($node !== $n->parentNode) { - continue; - } - - switch ($n->localName) { - case 'path': - $paths[$n->getAttribute('locale')] = trim($n->textContent); - break; - case 'host': - $hosts[$n->getAttribute('locale')] = trim($n->textContent); - break; - case 'prefix': - $prefixes[$n->getAttribute('locale')] = trim($n->textContent); - break; - case 'default': - if ($this->isElementValueNull($n)) { - $defaults[$n->getAttribute('key')] = null; - } else { - $defaults[$n->getAttribute('key')] = $this->parseDefaultsConfig($n, $path); - } - - break; - case 'requirement': - $requirements[$n->getAttribute('key')] = trim($n->textContent); - break; - case 'option': - $options[$n->getAttribute('key')] = XmlUtils::phpize(trim($n->textContent)); - break; - case 'condition': - $condition = trim($n->textContent); - break; - default: - throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "default", "requirement", "option" or "condition".', $n->localName, $path)); - } - } - - if ($controller = $node->getAttribute('controller')) { - if (isset($defaults['_controller'])) { - $name = $node->hasAttribute('id') ? sprintf('"%s".', $node->getAttribute('id')) : sprintf('the "%s" tag.', $node->tagName); - - throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "controller" attribute and the defaults key "_controller" for ', $path).$name); - } - - $defaults['_controller'] = $controller; - } - if ($node->hasAttribute('locale')) { - $defaults['_locale'] = $node->getAttribute('locale'); - } - if ($node->hasAttribute('format')) { - $defaults['_format'] = $node->getAttribute('format'); - } - if ($node->hasAttribute('utf8')) { - $options['utf8'] = XmlUtils::phpize($node->getAttribute('utf8')); - } - if ($stateless = $node->getAttribute('stateless')) { - if (isset($defaults['_stateless'])) { - $name = $node->hasAttribute('id') ? sprintf('"%s".', $node->getAttribute('id')) : sprintf('the "%s" tag.', $node->tagName); - - throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "stateless" attribute and the defaults key "_stateless" for ', $path).$name); - } - - $defaults['_stateless'] = XmlUtils::phpize($stateless); - } - - if (!$hosts) { - $hosts = $node->hasAttribute('host') ? $node->getAttribute('host') : null; - } - - return [$defaults, $requirements, $options, $condition, $paths, $prefixes, $hosts]; - } - - /** - * Parses the "default" elements. - * - * @return array|bool|float|int|string|null - */ - private function parseDefaultsConfig(\DOMElement $element, string $path) - { - if ($this->isElementValueNull($element)) { - return null; - } - - // Check for existing element nodes in the default element. There can - // only be a single element inside a default element. So this element - // (if one was found) can safely be returned. - foreach ($element->childNodes as $child) { - if (!$child instanceof \DOMElement) { - continue; - } - - if (self::NAMESPACE_URI !== $child->namespaceURI) { - continue; - } - - return $this->parseDefaultNode($child, $path); - } - - // If the default element doesn't contain a nested "bool", "int", "float", - // "string", "list", or "map" element, the element contents will be treated - // as the string value of the associated default option. - return trim($element->textContent); - } - - /** - * Recursively parses the value of a "default" element. - * - * @return array|bool|float|int|string|null - * - * @throws \InvalidArgumentException when the XML is invalid - */ - private function parseDefaultNode(\DOMElement $node, string $path) - { - if ($this->isElementValueNull($node)) { - return null; - } - - switch ($node->localName) { - case 'bool': - return 'true' === trim($node->nodeValue) || '1' === trim($node->nodeValue); - case 'int': - return (int) trim($node->nodeValue); - case 'float': - return (float) trim($node->nodeValue); - case 'string': - return trim($node->nodeValue); - case 'list': - $list = []; - - foreach ($node->childNodes as $element) { - if (!$element instanceof \DOMElement) { - continue; - } - - if (self::NAMESPACE_URI !== $element->namespaceURI) { - continue; - } - - $list[] = $this->parseDefaultNode($element, $path); - } - - return $list; - case 'map': - $map = []; - - foreach ($node->childNodes as $element) { - if (!$element instanceof \DOMElement) { - continue; - } - - if (self::NAMESPACE_URI !== $element->namespaceURI) { - continue; - } - - $map[$element->getAttribute('key')] = $this->parseDefaultNode($element, $path); - } - - return $map; - default: - throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "bool", "int", "float", "string", "list", or "map".', $node->localName, $path)); - } - } - - private function isElementValueNull(\DOMElement $element): bool - { - $namespaceUri = 'http://www.w3.org/2001/XMLSchema-instance'; - - if (!$element->hasAttributeNS($namespaceUri, 'nil')) { - return false; - } - - return 'true' === $element->getAttributeNS($namespaceUri, 'nil') || '1' === $element->getAttributeNS($namespaceUri, 'nil'); - } - - /** - * Parses the deprecation elements. - * - * @throws \InvalidArgumentException When the XML is invalid - */ - private function parseDeprecation(\DOMElement $node, string $path): array - { - $deprecatedNode = null; - foreach ($node->childNodes as $child) { - if (!$child instanceof \DOMElement || self::NAMESPACE_URI !== $child->namespaceURI) { - continue; - } - if ('deprecated' !== $child->localName) { - throw new \InvalidArgumentException(sprintf('Invalid child element "%s" defined for alias "%s" in "%s".', $child->localName, $node->getAttribute('id'), $path)); - } - - $deprecatedNode = $child; - } - - if (null === $deprecatedNode) { - return []; - } - - if (!$deprecatedNode->hasAttribute('package')) { - throw new \InvalidArgumentException(sprintf('The element in file "%s" must have a "package" attribute.', $path)); - } - if (!$deprecatedNode->hasAttribute('version')) { - throw new \InvalidArgumentException(sprintf('The element in file "%s" must have a "version" attribute.', $path)); - } - - return [ - 'package' => $deprecatedNode->getAttribute('package'), - 'version' => $deprecatedNode->getAttribute('version'), - 'message' => trim($deprecatedNode->nodeValue), - ]; - } -} diff --git a/digital_doctor/vendor/symfony/routing/Loader/YamlFileLoader.php b/digital_doctor/vendor/symfony/routing/Loader/YamlFileLoader.php deleted file mode 100644 index 1087817..0000000 --- a/digital_doctor/vendor/symfony/routing/Loader/YamlFileLoader.php +++ /dev/null @@ -1,314 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Symfony\Component\Config\Loader\FileLoader; -use Symfony\Component\Config\Resource\FileResource; -use Symfony\Component\Routing\Loader\Configurator\Traits\HostTrait; -use Symfony\Component\Routing\Loader\Configurator\Traits\LocalizedRouteTrait; -use Symfony\Component\Routing\Loader\Configurator\Traits\PrefixTrait; -use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\Yaml\Exception\ParseException; -use Symfony\Component\Yaml\Parser as YamlParser; -use Symfony\Component\Yaml\Yaml; - -/** - * YamlFileLoader loads Yaml routing files. - * - * @author Fabien Potencier - * @author Tobias Schultze - */ -class YamlFileLoader extends FileLoader -{ - use HostTrait; - use LocalizedRouteTrait; - use PrefixTrait; - - private const AVAILABLE_KEYS = [ - 'resource', 'type', 'prefix', 'path', 'host', 'schemes', 'methods', 'defaults', 'requirements', 'options', 'condition', 'controller', 'name_prefix', 'trailing_slash_on_root', 'locale', 'format', 'utf8', 'exclude', 'stateless', - ]; - private $yamlParser; - - /** - * Loads a Yaml file. - * - * @param string $file A Yaml file path - * @param string|null $type The resource type - * - * @return RouteCollection - * - * @throws \InvalidArgumentException When a route can't be parsed because YAML is invalid - */ - public function load($file, ?string $type = null) - { - $path = $this->locator->locate($file); - - if (!stream_is_local($path)) { - throw new \InvalidArgumentException(sprintf('This is not a local file "%s".', $path)); - } - - if (!file_exists($path)) { - throw new \InvalidArgumentException(sprintf('File "%s" not found.', $path)); - } - - if (null === $this->yamlParser) { - $this->yamlParser = new YamlParser(); - } - - try { - $parsedConfig = $this->yamlParser->parseFile($path, Yaml::PARSE_CONSTANT); - } catch (ParseException $e) { - throw new \InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML: ', $path).$e->getMessage(), 0, $e); - } - - $collection = new RouteCollection(); - $collection->addResource(new FileResource($path)); - - // empty file - if (null === $parsedConfig) { - return $collection; - } - - // not an array - if (!\is_array($parsedConfig)) { - throw new \InvalidArgumentException(sprintf('The file "%s" must contain a YAML array.', $path)); - } - - foreach ($parsedConfig as $name => $config) { - if (0 === strpos($name, 'when@')) { - if (!$this->env || 'when@'.$this->env !== $name) { - continue; - } - - foreach ($config as $name => $config) { - $this->validate($config, $name.'" when "@'.$this->env, $path); - - if (isset($config['resource'])) { - $this->parseImport($collection, $config, $path, $file); - } else { - $this->parseRoute($collection, $name, $config, $path); - } - } - - continue; - } - - $this->validate($config, $name, $path); - - if (isset($config['resource'])) { - $this->parseImport($collection, $config, $path, $file); - } else { - $this->parseRoute($collection, $name, $config, $path); - } - } - - return $collection; - } - - /** - * {@inheritdoc} - */ - public function supports($resource, ?string $type = null) - { - return \is_string($resource) && \in_array(pathinfo($resource, \PATHINFO_EXTENSION), ['yml', 'yaml'], true) && (!$type || 'yaml' === $type); - } - - /** - * Parses a route and adds it to the RouteCollection. - */ - protected function parseRoute(RouteCollection $collection, string $name, array $config, string $path) - { - if (isset($config['alias'])) { - $alias = $collection->addAlias($name, $config['alias']); - $deprecation = $config['deprecated'] ?? null; - if (null !== $deprecation) { - $alias->setDeprecated( - $deprecation['package'], - $deprecation['version'], - $deprecation['message'] ?? '' - ); - } - - return; - } - - $defaults = $config['defaults'] ?? []; - $requirements = $config['requirements'] ?? []; - $options = $config['options'] ?? []; - - foreach ($requirements as $placeholder => $requirement) { - if (\is_int($placeholder)) { - throw new \InvalidArgumentException(sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" of route "%s" in "%s"?', $placeholder, $requirement, $name, $path)); - } - } - - if (isset($config['controller'])) { - $defaults['_controller'] = $config['controller']; - } - if (isset($config['locale'])) { - $defaults['_locale'] = $config['locale']; - } - if (isset($config['format'])) { - $defaults['_format'] = $config['format']; - } - if (isset($config['utf8'])) { - $options['utf8'] = $config['utf8']; - } - if (isset($config['stateless'])) { - $defaults['_stateless'] = $config['stateless']; - } - - $routes = $this->createLocalizedRoute($collection, $name, $config['path']); - $routes->addDefaults($defaults); - $routes->addRequirements($requirements); - $routes->addOptions($options); - $routes->setSchemes($config['schemes'] ?? []); - $routes->setMethods($config['methods'] ?? []); - $routes->setCondition($config['condition'] ?? null); - - if (isset($config['host'])) { - $this->addHost($routes, $config['host']); - } - } - - /** - * Parses an import and adds the routes in the resource to the RouteCollection. - */ - protected function parseImport(RouteCollection $collection, array $config, string $path, string $file) - { - $type = $config['type'] ?? null; - $prefix = $config['prefix'] ?? ''; - $defaults = $config['defaults'] ?? []; - $requirements = $config['requirements'] ?? []; - $options = $config['options'] ?? []; - $host = $config['host'] ?? null; - $condition = $config['condition'] ?? null; - $schemes = $config['schemes'] ?? null; - $methods = $config['methods'] ?? null; - $trailingSlashOnRoot = $config['trailing_slash_on_root'] ?? true; - $namePrefix = $config['name_prefix'] ?? null; - $exclude = $config['exclude'] ?? null; - - if (isset($config['controller'])) { - $defaults['_controller'] = $config['controller']; - } - if (isset($config['locale'])) { - $defaults['_locale'] = $config['locale']; - } - if (isset($config['format'])) { - $defaults['_format'] = $config['format']; - } - if (isset($config['utf8'])) { - $options['utf8'] = $config['utf8']; - } - if (isset($config['stateless'])) { - $defaults['_stateless'] = $config['stateless']; - } - - $this->setCurrentDir(\dirname($path)); - - /** @var RouteCollection[] $imported */ - $imported = $this->import($config['resource'], $type, false, $file, $exclude) ?: []; - - if (!\is_array($imported)) { - $imported = [$imported]; - } - - foreach ($imported as $subCollection) { - $this->addPrefix($subCollection, $prefix, $trailingSlashOnRoot); - - if (null !== $host) { - $this->addHost($subCollection, $host); - } - if (null !== $condition) { - $subCollection->setCondition($condition); - } - if (null !== $schemes) { - $subCollection->setSchemes($schemes); - } - if (null !== $methods) { - $subCollection->setMethods($methods); - } - if (null !== $namePrefix) { - $subCollection->addNamePrefix($namePrefix); - } - $subCollection->addDefaults($defaults); - $subCollection->addRequirements($requirements); - $subCollection->addOptions($options); - - $collection->addCollection($subCollection); - } - } - - /** - * Validates the route configuration. - * - * @param array $config A resource config - * @param string $name The config key - * @param string $path The loaded file path - * - * @throws \InvalidArgumentException If one of the provided config keys is not supported, - * something is missing or the combination is nonsense - */ - protected function validate($config, string $name, string $path) - { - if (!\is_array($config)) { - throw new \InvalidArgumentException(sprintf('The definition of "%s" in "%s" must be a YAML array.', $name, $path)); - } - if (isset($config['alias'])) { - $this->validateAlias($config, $name, $path); - - return; - } - if ($extraKeys = array_diff(array_keys($config), self::AVAILABLE_KEYS)) { - throw new \InvalidArgumentException(sprintf('The routing file "%s" contains unsupported keys for "%s": "%s". Expected one of: "%s".', $path, $name, implode('", "', $extraKeys), implode('", "', self::AVAILABLE_KEYS))); - } - if (isset($config['resource']) && isset($config['path'])) { - throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "resource" key and the "path" key for "%s". Choose between an import and a route definition.', $path, $name)); - } - if (!isset($config['resource']) && isset($config['type'])) { - throw new \InvalidArgumentException(sprintf('The "type" key for the route definition "%s" in "%s" is unsupported. It is only available for imports in combination with the "resource" key.', $name, $path)); - } - if (!isset($config['resource']) && !isset($config['path'])) { - throw new \InvalidArgumentException(sprintf('You must define a "path" for the route "%s" in file "%s".', $name, $path)); - } - if (isset($config['controller']) && isset($config['defaults']['_controller'])) { - throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "controller" key and the defaults key "_controller" for "%s".', $path, $name)); - } - if (isset($config['stateless']) && isset($config['defaults']['_stateless'])) { - throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "stateless" key and the defaults key "_stateless" for "%s".', $path, $name)); - } - } - - /** - * @throws \InvalidArgumentException If one of the provided config keys is not supported, - * something is missing or the combination is nonsense - */ - private function validateAlias(array $config, string $name, string $path): void - { - foreach ($config as $key => $value) { - if (!\in_array($key, ['alias', 'deprecated'], true)) { - throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify other keys than "alias" and "deprecated" for "%s".', $path, $name)); - } - - if ('deprecated' === $key) { - if (!isset($value['package'])) { - throw new \InvalidArgumentException(sprintf('The routing file "%s" must specify the attribute "package" of the "deprecated" option for "%s".', $path, $name)); - } - - if (!isset($value['version'])) { - throw new \InvalidArgumentException(sprintf('The routing file "%s" must specify the attribute "version" of the "deprecated" option for "%s".', $path, $name)); - } - } - } - } -} diff --git a/digital_doctor/vendor/symfony/routing/Loader/schema/routing/routing-1.0.xsd b/digital_doctor/vendor/symfony/routing/Loader/schema/routing/routing-1.0.xsd deleted file mode 100644 index 66c40a0..0000000 --- a/digital_doctor/vendor/symfony/routing/Loader/schema/routing/routing-1.0.xsd +++ /dev/null @@ -1,194 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/digital_doctor/vendor/symfony/routing/Matcher/CompiledUrlMatcher.php b/digital_doctor/vendor/symfony/routing/Matcher/CompiledUrlMatcher.php deleted file mode 100644 index ae13fd7..0000000 --- a/digital_doctor/vendor/symfony/routing/Matcher/CompiledUrlMatcher.php +++ /dev/null @@ -1,31 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher; - -use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherTrait; -use Symfony\Component\Routing\RequestContext; - -/** - * Matches URLs based on rules dumped by CompiledUrlMatcherDumper. - * - * @author Nicolas Grekas - */ -class CompiledUrlMatcher extends UrlMatcher -{ - use CompiledUrlMatcherTrait; - - public function __construct(array $compiledRoutes, RequestContext $context) - { - $this->context = $context; - [$this->matchHost, $this->staticRoutes, $this->regexpList, $this->dynamicRoutes, $this->checkCondition] = $compiledRoutes; - } -} diff --git a/digital_doctor/vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherDumper.php b/digital_doctor/vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherDumper.php deleted file mode 100644 index ddf231f..0000000 --- a/digital_doctor/vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherDumper.php +++ /dev/null @@ -1,501 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher\Dumper; - -use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; -use Symfony\Component\ExpressionLanguage\ExpressionLanguage; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -/** - * CompiledUrlMatcherDumper creates PHP arrays to be used with CompiledUrlMatcher. - * - * @author Fabien Potencier - * @author Tobias Schultze - * @author Arnaud Le Blanc - * @author Nicolas Grekas - */ -class CompiledUrlMatcherDumper extends MatcherDumper -{ - private $expressionLanguage; - private $signalingException; - - /** - * @var ExpressionFunctionProviderInterface[] - */ - private $expressionLanguageProviders = []; - - /** - * {@inheritdoc} - */ - public function dump(array $options = []) - { - return <<generateCompiledRoutes()}]; - -EOF; - } - - public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider) - { - $this->expressionLanguageProviders[] = $provider; - } - - /** - * Generates the arrays for CompiledUrlMatcher's constructor. - */ - public function getCompiledRoutes(bool $forDump = false): array - { - // Group hosts by same-suffix, re-order when possible - $matchHost = false; - $routes = new StaticPrefixCollection(); - foreach ($this->getRoutes()->all() as $name => $route) { - if ($host = $route->getHost()) { - $matchHost = true; - $host = '/'.strtr(strrev($host), '}.{', '(/)'); - } - - $routes->addRoute($host ?: '/(.*)', [$name, $route]); - } - - if ($matchHost) { - $compiledRoutes = [true]; - $routes = $routes->populateCollection(new RouteCollection()); - } else { - $compiledRoutes = [false]; - $routes = $this->getRoutes(); - } - - [$staticRoutes, $dynamicRoutes] = $this->groupStaticRoutes($routes); - - $conditions = [null]; - $compiledRoutes[] = $this->compileStaticRoutes($staticRoutes, $conditions); - $chunkLimit = \count($dynamicRoutes); - - while (true) { - try { - $this->signalingException = new \RuntimeException('Compilation failed: regular expression is too large'); - $compiledRoutes = array_merge($compiledRoutes, $this->compileDynamicRoutes($dynamicRoutes, $matchHost, $chunkLimit, $conditions)); - - break; - } catch (\Exception $e) { - if (1 < $chunkLimit && $this->signalingException === $e) { - $chunkLimit = 1 + ($chunkLimit >> 1); - continue; - } - throw $e; - } - } - - if ($forDump) { - $compiledRoutes[2] = $compiledRoutes[4]; - } - unset($conditions[0]); - - if ($conditions) { - foreach ($conditions as $expression => $condition) { - $conditions[$expression] = "case {$condition}: return {$expression};"; - } - - $checkConditionCode = <<indent(implode("\n", $conditions), 3)} - } - } -EOF; - $compiledRoutes[4] = $forDump ? $checkConditionCode.",\n" : eval('return '.$checkConditionCode.';'); - } else { - $compiledRoutes[4] = $forDump ? " null, // \$checkCondition\n" : null; - } - - return $compiledRoutes; - } - - private function generateCompiledRoutes(): string - { - [$matchHost, $staticRoutes, $regexpCode, $dynamicRoutes, $checkConditionCode] = $this->getCompiledRoutes(true); - - $code = self::export($matchHost).', // $matchHost'."\n"; - - $code .= '[ // $staticRoutes'."\n"; - foreach ($staticRoutes as $path => $routes) { - $code .= sprintf(" %s => [\n", self::export($path)); - foreach ($routes as $route) { - $code .= vsprintf(" [%s, %s, %s, %s, %s, %s, %s],\n", array_map([__CLASS__, 'export'], $route)); - } - $code .= " ],\n"; - } - $code .= "],\n"; - - $code .= sprintf("[ // \$regexpList%s\n],\n", $regexpCode); - - $code .= '[ // $dynamicRoutes'."\n"; - foreach ($dynamicRoutes as $path => $routes) { - $code .= sprintf(" %s => [\n", self::export($path)); - foreach ($routes as $route) { - $code .= vsprintf(" [%s, %s, %s, %s, %s, %s, %s],\n", array_map([__CLASS__, 'export'], $route)); - } - $code .= " ],\n"; - } - $code .= "],\n"; - $code = preg_replace('/ => \[\n (\[.+?),\n \],/', ' => [$1],', $code); - - return $this->indent($code, 1).$checkConditionCode; - } - - /** - * Splits static routes from dynamic routes, so that they can be matched first, using a simple switch. - */ - private function groupStaticRoutes(RouteCollection $collection): array - { - $staticRoutes = $dynamicRegex = []; - $dynamicRoutes = new RouteCollection(); - - foreach ($collection->all() as $name => $route) { - $compiledRoute = $route->compile(); - $staticPrefix = rtrim($compiledRoute->getStaticPrefix(), '/'); - $hostRegex = $compiledRoute->getHostRegex(); - $regex = $compiledRoute->getRegex(); - if ($hasTrailingSlash = '/' !== $route->getPath()) { - $pos = strrpos($regex, '$'); - $hasTrailingSlash = '/' === $regex[$pos - 1]; - $regex = substr_replace($regex, '/?$', $pos - $hasTrailingSlash, 1 + $hasTrailingSlash); - } - - if (!$compiledRoute->getPathVariables()) { - $host = !$compiledRoute->getHostVariables() ? $route->getHost() : ''; - $url = $route->getPath(); - if ($hasTrailingSlash) { - $url = substr($url, 0, -1); - } - foreach ($dynamicRegex as [$hostRx, $rx, $prefix]) { - if (('' === $prefix || str_starts_with($url, $prefix)) && (preg_match($rx, $url) || preg_match($rx, $url.'/')) && (!$host || !$hostRx || preg_match($hostRx, $host))) { - $dynamicRegex[] = [$hostRegex, $regex, $staticPrefix]; - $dynamicRoutes->add($name, $route); - continue 2; - } - } - - $staticRoutes[$url][$name] = [$route, $hasTrailingSlash]; - } else { - $dynamicRegex[] = [$hostRegex, $regex, $staticPrefix]; - $dynamicRoutes->add($name, $route); - } - } - - return [$staticRoutes, $dynamicRoutes]; - } - - /** - * Compiles static routes in a switch statement. - * - * Condition-less paths are put in a static array in the switch's default, with generic matching logic. - * Paths that can match two or more routes, or have user-specified conditions are put in separate switch's cases. - * - * @throws \LogicException - */ - private function compileStaticRoutes(array $staticRoutes, array &$conditions): array - { - if (!$staticRoutes) { - return []; - } - $compiledRoutes = []; - - foreach ($staticRoutes as $url => $routes) { - $compiledRoutes[$url] = []; - foreach ($routes as $name => [$route, $hasTrailingSlash]) { - $compiledRoutes[$url][] = $this->compileRoute($route, $name, (!$route->compile()->getHostVariables() ? $route->getHost() : $route->compile()->getHostRegex()) ?: null, $hasTrailingSlash, false, $conditions); - } - } - - return $compiledRoutes; - } - - /** - * Compiles a regular expression followed by a switch statement to match dynamic routes. - * - * The regular expression matches both the host and the pathinfo at the same time. For stellar performance, - * it is built as a tree of patterns, with re-ordering logic to group same-prefix routes together when possible. - * - * Patterns are named so that we know which one matched (https://pcre.org/current/doc/html/pcre2syntax.html#SEC23). - * This name is used to "switch" to the additional logic required to match the final route. - * - * Condition-less paths are put in a static array in the switch's default, with generic matching logic. - * Paths that can match two or more routes, or have user-specified conditions are put in separate switch's cases. - * - * Last but not least: - * - Because it is not possible to mix unicode/non-unicode patterns in a single regexp, several of them can be generated. - * - The same regexp can be used several times when the logic in the switch rejects the match. When this happens, the - * matching-but-failing subpattern is excluded by replacing its name by "(*F)", which forces a failure-to-match. - * To ease this backlisting operation, the name of subpatterns is also the string offset where the replacement should occur. - */ - private function compileDynamicRoutes(RouteCollection $collection, bool $matchHost, int $chunkLimit, array &$conditions): array - { - if (!$collection->all()) { - return [[], [], '']; - } - $regexpList = []; - $code = ''; - $state = (object) [ - 'regexMark' => 0, - 'regex' => [], - 'routes' => [], - 'mark' => 0, - 'markTail' => 0, - 'hostVars' => [], - 'vars' => [], - ]; - $state->getVars = static function ($m) use ($state) { - if ('_route' === $m[1]) { - return '?:'; - } - - $state->vars[] = $m[1]; - - return ''; - }; - - $chunkSize = 0; - $prev = null; - $perModifiers = []; - foreach ($collection->all() as $name => $route) { - preg_match('#[a-zA-Z]*$#', $route->compile()->getRegex(), $rx); - if ($chunkLimit < ++$chunkSize || $prev !== $rx[0] && $route->compile()->getPathVariables()) { - $chunkSize = 1; - $routes = new RouteCollection(); - $perModifiers[] = [$rx[0], $routes]; - $prev = $rx[0]; - } - $routes->add($name, $route); - } - - foreach ($perModifiers as [$modifiers, $routes]) { - $prev = false; - $perHost = []; - foreach ($routes->all() as $name => $route) { - $regex = $route->compile()->getHostRegex(); - if ($prev !== $regex) { - $routes = new RouteCollection(); - $perHost[] = [$regex, $routes]; - $prev = $regex; - } - $routes->add($name, $route); - } - $prev = false; - $rx = '{^(?'; - $code .= "\n {$state->mark} => ".self::export($rx); - $startingMark = $state->mark; - $state->mark += \strlen($rx); - $state->regex = $rx; - - foreach ($perHost as [$hostRegex, $routes]) { - if ($matchHost) { - if ($hostRegex) { - preg_match('#^.\^(.*)\$.[a-zA-Z]*$#', $hostRegex, $rx); - $state->vars = []; - $hostRegex = '(?i:'.preg_replace_callback('#\?P<([^>]++)>#', $state->getVars, $rx[1]).')\.'; - $state->hostVars = $state->vars; - } else { - $hostRegex = '(?:(?:[^./]*+\.)++)'; - $state->hostVars = []; - } - $state->mark += \strlen($rx = ($prev ? ')' : '')."|{$hostRegex}(?"); - $code .= "\n .".self::export($rx); - $state->regex .= $rx; - $prev = true; - } - - $tree = new StaticPrefixCollection(); - foreach ($routes->all() as $name => $route) { - preg_match('#^.\^(.*)\$.[a-zA-Z]*$#', $route->compile()->getRegex(), $rx); - - $state->vars = []; - $regex = preg_replace_callback('#\?P<([^>]++)>#', $state->getVars, $rx[1]); - if ($hasTrailingSlash = '/' !== $regex && '/' === $regex[-1]) { - $regex = substr($regex, 0, -1); - } - $hasTrailingVar = (bool) preg_match('#\{\w+\}/?$#', $route->getPath()); - - $tree->addRoute($regex, [$name, $regex, $state->vars, $route, $hasTrailingSlash, $hasTrailingVar]); - } - - $code .= $this->compileStaticPrefixCollection($tree, $state, 0, $conditions); - } - if ($matchHost) { - $code .= "\n .')'"; - $state->regex .= ')'; - } - $rx = ")/?$}{$modifiers}"; - $code .= "\n .'{$rx}',"; - $state->regex .= $rx; - $state->markTail = 0; - - // if the regex is too large, throw a signaling exception to recompute with smaller chunk size - set_error_handler(function ($type, $message) { throw str_contains($message, $this->signalingException->getMessage()) ? $this->signalingException : new \ErrorException($message); }); - try { - preg_match($state->regex, ''); - } finally { - restore_error_handler(); - } - - $regexpList[$startingMark] = $state->regex; - } - - $state->routes[$state->mark][] = [null, null, null, null, false, false, 0]; - unset($state->getVars); - - return [$regexpList, $state->routes, $code]; - } - - /** - * Compiles a regexp tree of subpatterns that matches nested same-prefix routes. - * - * @param \stdClass $state A simple state object that keeps track of the progress of the compilation, - * and gathers the generated switch's "case" and "default" statements - */ - private function compileStaticPrefixCollection(StaticPrefixCollection $tree, \stdClass $state, int $prefixLen, array &$conditions): string - { - $code = ''; - $prevRegex = null; - $routes = $tree->getRoutes(); - - foreach ($routes as $i => $route) { - if ($route instanceof StaticPrefixCollection) { - $prevRegex = null; - $prefix = substr($route->getPrefix(), $prefixLen); - $state->mark += \strlen($rx = "|{$prefix}(?"); - $code .= "\n .".self::export($rx); - $state->regex .= $rx; - $code .= $this->indent($this->compileStaticPrefixCollection($route, $state, $prefixLen + \strlen($prefix), $conditions)); - $code .= "\n .')'"; - $state->regex .= ')'; - ++$state->markTail; - continue; - } - - [$name, $regex, $vars, $route, $hasTrailingSlash, $hasTrailingVar] = $route; - $compiledRoute = $route->compile(); - $vars = array_merge($state->hostVars, $vars); - - if ($compiledRoute->getRegex() === $prevRegex) { - $state->routes[$state->mark][] = $this->compileRoute($route, $name, $vars, $hasTrailingSlash, $hasTrailingVar, $conditions); - continue; - } - - $state->mark += 3 + $state->markTail + \strlen($regex) - $prefixLen; - $state->markTail = 2 + \strlen($state->mark); - $rx = sprintf('|%s(*:%s)', substr($regex, $prefixLen), $state->mark); - $code .= "\n .".self::export($rx); - $state->regex .= $rx; - - $prevRegex = $compiledRoute->getRegex(); - $state->routes[$state->mark] = [$this->compileRoute($route, $name, $vars, $hasTrailingSlash, $hasTrailingVar, $conditions)]; - } - - return $code; - } - - /** - * Compiles a single Route to PHP code used to match it against the path info. - */ - private function compileRoute(Route $route, string $name, $vars, bool $hasTrailingSlash, bool $hasTrailingVar, array &$conditions): array - { - $defaults = $route->getDefaults(); - - if (isset($defaults['_canonical_route'])) { - $name = $defaults['_canonical_route']; - unset($defaults['_canonical_route']); - } - - if ($condition = $route->getCondition()) { - $condition = $this->getExpressionLanguage()->compile($condition, ['context', 'request']); - $condition = $conditions[$condition] ?? $conditions[$condition] = (str_contains($condition, '$request') ? 1 : -1) * \count($conditions); - } else { - $condition = null; - } - - return [ - ['_route' => $name] + $defaults, - $vars, - array_flip($route->getMethods()) ?: null, - array_flip($route->getSchemes()) ?: null, - $hasTrailingSlash, - $hasTrailingVar, - $condition, - ]; - } - - private function getExpressionLanguage(): ExpressionLanguage - { - if (null === $this->expressionLanguage) { - if (!class_exists(ExpressionLanguage::class)) { - throw new \LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); - } - $this->expressionLanguage = new ExpressionLanguage(null, $this->expressionLanguageProviders); - } - - return $this->expressionLanguage; - } - - private function indent(string $code, int $level = 1): string - { - return preg_replace('/^./m', str_repeat(' ', $level).'$0', $code); - } - - /** - * @internal - */ - public static function export($value): string - { - if (null === $value) { - return 'null'; - } - if (!\is_array($value)) { - if (\is_object($value)) { - throw new \InvalidArgumentException('Symfony\Component\Routing\Route cannot contain objects.'); - } - - return str_replace("\n", '\'."\n".\'', var_export($value, true)); - } - if (!$value) { - return '[]'; - } - - $i = 0; - $export = '['; - - foreach ($value as $k => $v) { - if ($i === $k) { - ++$i; - } else { - $export .= self::export($k).' => '; - - if (\is_int($k) && $i < $k) { - $i = 1 + $k; - } - } - - $export .= self::export($v).', '; - } - - return substr_replace($export, ']', -2); - } -} diff --git a/digital_doctor/vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php b/digital_doctor/vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php deleted file mode 100644 index bdb7ba3..0000000 --- a/digital_doctor/vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php +++ /dev/null @@ -1,191 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher\Dumper; - -use Symfony\Component\Routing\Exception\MethodNotAllowedException; -use Symfony\Component\Routing\Exception\NoConfigurationException; -use Symfony\Component\Routing\Exception\ResourceNotFoundException; -use Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface; -use Symfony\Component\Routing\RequestContext; - -/** - * @author Nicolas Grekas - * - * @internal - * - * @property RequestContext $context - */ -trait CompiledUrlMatcherTrait -{ - private $matchHost = false; - private $staticRoutes = []; - private $regexpList = []; - private $dynamicRoutes = []; - - /** - * @var callable|null - */ - private $checkCondition; - - public function match(string $pathinfo): array - { - $allow = $allowSchemes = []; - if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) { - return $ret; - } - if ($allow) { - throw new MethodNotAllowedException(array_keys($allow)); - } - if (!$this instanceof RedirectableUrlMatcherInterface) { - throw new ResourceNotFoundException(sprintf('No routes found for "%s".', $pathinfo)); - } - if (!\in_array($this->context->getMethod(), ['HEAD', 'GET'], true)) { - // no-op - } elseif ($allowSchemes) { - redirect_scheme: - $scheme = $this->context->getScheme(); - $this->context->setScheme(key($allowSchemes)); - try { - if ($ret = $this->doMatch($pathinfo)) { - return $this->redirect($pathinfo, $ret['_route'], $this->context->getScheme()) + $ret; - } - } finally { - $this->context->setScheme($scheme); - } - } elseif ('/' !== $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/') { - $pathinfo = $trimmedPathinfo === $pathinfo ? $pathinfo.'/' : $trimmedPathinfo; - if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) { - return $this->redirect($pathinfo, $ret['_route']) + $ret; - } - if ($allowSchemes) { - goto redirect_scheme; - } - } - - throw new ResourceNotFoundException(sprintf('No routes found for "%s".', $pathinfo)); - } - - private function doMatch(string $pathinfo, array &$allow = [], array &$allowSchemes = []): array - { - $allow = $allowSchemes = []; - $pathinfo = rawurldecode($pathinfo) ?: '/'; - $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/'; - $context = $this->context; - $requestMethod = $canonicalMethod = $context->getMethod(); - - if ($this->matchHost) { - $host = strtolower($context->getHost()); - } - - if ('HEAD' === $requestMethod) { - $canonicalMethod = 'GET'; - } - $supportsRedirections = 'GET' === $canonicalMethod && $this instanceof RedirectableUrlMatcherInterface; - - foreach ($this->staticRoutes[$trimmedPathinfo] ?? [] as [$ret, $requiredHost, $requiredMethods, $requiredSchemes, $hasTrailingSlash, , $condition]) { - if ($condition && !($this->checkCondition)($condition, $context, 0 < $condition ? $request ?? $request = $this->request ?: $this->createRequest($pathinfo) : null)) { - continue; - } - - if ($requiredHost) { - if ('{' !== $requiredHost[0] ? $requiredHost !== $host : !preg_match($requiredHost, $host, $hostMatches)) { - continue; - } - if ('{' === $requiredHost[0] && $hostMatches) { - $hostMatches['_route'] = $ret['_route']; - $ret = $this->mergeDefaults($hostMatches, $ret); - } - } - - if ('/' !== $pathinfo && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) { - if ($supportsRedirections && (!$requiredMethods || isset($requiredMethods['GET']))) { - return $allow = $allowSchemes = []; - } - continue; - } - - $hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]); - if ($hasRequiredScheme && $requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) { - $allow += $requiredMethods; - continue; - } - - if (!$hasRequiredScheme) { - $allowSchemes += $requiredSchemes; - continue; - } - - return $ret; - } - - $matchedPathinfo = $this->matchHost ? $host.'.'.$pathinfo : $pathinfo; - - foreach ($this->regexpList as $offset => $regex) { - while (preg_match($regex, $matchedPathinfo, $matches)) { - foreach ($this->dynamicRoutes[$m = (int) $matches['MARK']] as [$ret, $vars, $requiredMethods, $requiredSchemes, $hasTrailingSlash, $hasTrailingVar, $condition]) { - if (null !== $condition) { - if (0 === $condition) { // marks the last route in the regexp - continue 3; - } - if (!($this->checkCondition)($condition, $context, 0 < $condition ? $request ?? $request = $this->request ?: $this->createRequest($pathinfo) : null)) { - continue; - } - } - - $hasTrailingVar = $trimmedPathinfo !== $pathinfo && $hasTrailingVar; - - if ($hasTrailingVar && ($hasTrailingSlash || (null === $n = $matches[\count($vars)] ?? null) || '/' !== ($n[-1] ?? '/')) && preg_match($regex, $this->matchHost ? $host.'.'.$trimmedPathinfo : $trimmedPathinfo, $n) && $m === (int) $n['MARK']) { - if ($hasTrailingSlash) { - $matches = $n; - } else { - $hasTrailingVar = false; - } - } - - if ('/' !== $pathinfo && !$hasTrailingVar && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) { - if ($supportsRedirections && (!$requiredMethods || isset($requiredMethods['GET']))) { - return $allow = $allowSchemes = []; - } - continue; - } - - foreach ($vars as $i => $v) { - if (isset($matches[1 + $i])) { - $ret[$v] = $matches[1 + $i]; - } - } - - if ($requiredSchemes && !isset($requiredSchemes[$context->getScheme()])) { - $allowSchemes += $requiredSchemes; - continue; - } - - if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) { - $allow += $requiredMethods; - continue; - } - - return $ret; - } - - $regex = substr_replace($regex, 'F', $m - $offset, 1 + \strlen($m)); - $offset += \strlen($m); - } - } - - if ('/' === $pathinfo && !$allow && !$allowSchemes) { - throw new NoConfigurationException(); - } - - return []; - } -} diff --git a/digital_doctor/vendor/symfony/routing/Matcher/Dumper/MatcherDumper.php b/digital_doctor/vendor/symfony/routing/Matcher/Dumper/MatcherDumper.php deleted file mode 100644 index ea51ab4..0000000 --- a/digital_doctor/vendor/symfony/routing/Matcher/Dumper/MatcherDumper.php +++ /dev/null @@ -1,37 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher\Dumper; - -use Symfony\Component\Routing\RouteCollection; - -/** - * MatcherDumper is the abstract class for all built-in matcher dumpers. - * - * @author Fabien Potencier - */ -abstract class MatcherDumper implements MatcherDumperInterface -{ - private $routes; - - public function __construct(RouteCollection $routes) - { - $this->routes = $routes; - } - - /** - * {@inheritdoc} - */ - public function getRoutes() - { - return $this->routes; - } -} diff --git a/digital_doctor/vendor/symfony/routing/Matcher/Dumper/MatcherDumperInterface.php b/digital_doctor/vendor/symfony/routing/Matcher/Dumper/MatcherDumperInterface.php deleted file mode 100644 index 8e33802..0000000 --- a/digital_doctor/vendor/symfony/routing/Matcher/Dumper/MatcherDumperInterface.php +++ /dev/null @@ -1,37 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher\Dumper; - -use Symfony\Component\Routing\RouteCollection; - -/** - * MatcherDumperInterface is the interface that all matcher dumper classes must implement. - * - * @author Fabien Potencier - */ -interface MatcherDumperInterface -{ - /** - * Dumps a set of routes to a string representation of executable code - * that can then be used to match a request against these routes. - * - * @return string - */ - public function dump(array $options = []); - - /** - * Gets the routes to dump. - * - * @return RouteCollection - */ - public function getRoutes(); -} diff --git a/digital_doctor/vendor/symfony/routing/Matcher/Dumper/StaticPrefixCollection.php b/digital_doctor/vendor/symfony/routing/Matcher/Dumper/StaticPrefixCollection.php deleted file mode 100644 index 47d923c..0000000 --- a/digital_doctor/vendor/symfony/routing/Matcher/Dumper/StaticPrefixCollection.php +++ /dev/null @@ -1,206 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher\Dumper; - -use Symfony\Component\Routing\RouteCollection; - -/** - * Prefix tree of routes preserving routes order. - * - * @author Frank de Jonge - * @author Nicolas Grekas - * - * @internal - */ -class StaticPrefixCollection -{ - private $prefix; - - /** - * @var string[] - */ - private $staticPrefixes = []; - - /** - * @var string[] - */ - private $prefixes = []; - - /** - * @var array[]|self[] - */ - private $items = []; - - public function __construct(string $prefix = '/') - { - $this->prefix = $prefix; - } - - public function getPrefix(): string - { - return $this->prefix; - } - - /** - * @return array[]|self[] - */ - public function getRoutes(): array - { - return $this->items; - } - - /** - * Adds a route to a group. - * - * @param array|self $route - */ - public function addRoute(string $prefix, $route) - { - [$prefix, $staticPrefix] = $this->getCommonPrefix($prefix, $prefix); - - for ($i = \count($this->items) - 1; 0 <= $i; --$i) { - $item = $this->items[$i]; - - [$commonPrefix, $commonStaticPrefix] = $this->getCommonPrefix($prefix, $this->prefixes[$i]); - - if ($this->prefix === $commonPrefix) { - // the new route and a previous one have no common prefix, let's see if they are exclusive to each others - - if ($this->prefix !== $staticPrefix && $this->prefix !== $this->staticPrefixes[$i]) { - // the new route and the previous one have exclusive static prefixes - continue; - } - - if ($this->prefix === $staticPrefix && $this->prefix === $this->staticPrefixes[$i]) { - // the new route and the previous one have no static prefix - break; - } - - if ($this->prefixes[$i] !== $this->staticPrefixes[$i] && $this->prefix === $this->staticPrefixes[$i]) { - // the previous route is non-static and has no static prefix - break; - } - - if ($prefix !== $staticPrefix && $this->prefix === $staticPrefix) { - // the new route is non-static and has no static prefix - break; - } - - continue; - } - - if ($item instanceof self && $this->prefixes[$i] === $commonPrefix) { - // the new route is a child of a previous one, let's nest it - $item->addRoute($prefix, $route); - } else { - // the new route and a previous one have a common prefix, let's merge them - $child = new self($commonPrefix); - [$child->prefixes[0], $child->staticPrefixes[0]] = $child->getCommonPrefix($this->prefixes[$i], $this->prefixes[$i]); - [$child->prefixes[1], $child->staticPrefixes[1]] = $child->getCommonPrefix($prefix, $prefix); - $child->items = [$this->items[$i], $route]; - - $this->staticPrefixes[$i] = $commonStaticPrefix; - $this->prefixes[$i] = $commonPrefix; - $this->items[$i] = $child; - } - - return; - } - - // No optimised case was found, in this case we simple add the route for possible - // grouping when new routes are added. - $this->staticPrefixes[] = $staticPrefix; - $this->prefixes[] = $prefix; - $this->items[] = $route; - } - - /** - * Linearizes back a set of nested routes into a collection. - */ - public function populateCollection(RouteCollection $routes): RouteCollection - { - foreach ($this->items as $route) { - if ($route instanceof self) { - $route->populateCollection($routes); - } else { - $routes->add(...$route); - } - } - - return $routes; - } - - /** - * Gets the full and static common prefixes between two route patterns. - * - * The static prefix stops at last at the first opening bracket. - */ - private function getCommonPrefix(string $prefix, string $anotherPrefix): array - { - $baseLength = \strlen($this->prefix); - $end = min(\strlen($prefix), \strlen($anotherPrefix)); - $staticLength = null; - set_error_handler([__CLASS__, 'handleError']); - - try { - for ($i = $baseLength; $i < $end && $prefix[$i] === $anotherPrefix[$i]; ++$i) { - if ('(' === $prefix[$i]) { - $staticLength = $staticLength ?? $i; - for ($j = 1 + $i, $n = 1; $j < $end && 0 < $n; ++$j) { - if ($prefix[$j] !== $anotherPrefix[$j]) { - break 2; - } - if ('(' === $prefix[$j]) { - ++$n; - } elseif (')' === $prefix[$j]) { - --$n; - } elseif ('\\' === $prefix[$j] && (++$j === $end || $prefix[$j] !== $anotherPrefix[$j])) { - --$j; - break; - } - } - if (0 < $n) { - break; - } - if (('?' === ($prefix[$j] ?? '') || '?' === ($anotherPrefix[$j] ?? '')) && ($prefix[$j] ?? '') !== ($anotherPrefix[$j] ?? '')) { - break; - } - $subPattern = substr($prefix, $i, $j - $i); - if ($prefix !== $anotherPrefix && !preg_match('/^\(\[[^\]]++\]\+\+\)$/', $subPattern) && !preg_match('{(?> 6) && preg_match('//u', $prefix.' '.$anotherPrefix)) { - do { - // Prevent cutting in the middle of an UTF-8 characters - --$i; - } while (0b10 === (\ord($prefix[$i]) >> 6)); - } - - return [substr($prefix, 0, $i), substr($prefix, 0, $staticLength ?? $i)]; - } - - public static function handleError(int $type, string $msg) - { - return str_contains($msg, 'Compilation failed: lookbehind assertion is not fixed length') - || str_contains($msg, 'Compilation failed: length of lookbehind assertion is not limited'); - } -} diff --git a/digital_doctor/vendor/symfony/routing/Matcher/ExpressionLanguageProvider.php b/digital_doctor/vendor/symfony/routing/Matcher/ExpressionLanguageProvider.php deleted file mode 100644 index 96bb7ba..0000000 --- a/digital_doctor/vendor/symfony/routing/Matcher/ExpressionLanguageProvider.php +++ /dev/null @@ -1,58 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher; - -use Symfony\Component\ExpressionLanguage\ExpressionFunction; -use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; -use Symfony\Contracts\Service\ServiceProviderInterface; - -/** - * Exposes functions defined in the request context to route conditions. - * - * @author Ahmed TAILOULOUTE - */ -class ExpressionLanguageProvider implements ExpressionFunctionProviderInterface -{ - private $functions; - - public function __construct(ServiceProviderInterface $functions) - { - $this->functions = $functions; - } - - /** - * {@inheritdoc} - */ - public function getFunctions() - { - $functions = []; - - foreach ($this->functions->getProvidedServices() as $function => $type) { - $functions[] = new ExpressionFunction( - $function, - static function (...$args) use ($function) { - return sprintf('($context->getParameter(\'_functions\')->get(%s)(%s))', var_export($function, true), implode(', ', $args)); - }, - function ($values, ...$args) use ($function) { - return $values['context']->getParameter('_functions')->get($function)(...$args); - } - ); - } - - return $functions; - } - - public function get(string $function): callable - { - return $this->functions->get($function); - } -} diff --git a/digital_doctor/vendor/symfony/routing/Matcher/RedirectableUrlMatcher.php b/digital_doctor/vendor/symfony/routing/Matcher/RedirectableUrlMatcher.php deleted file mode 100644 index 3cd7c81..0000000 --- a/digital_doctor/vendor/symfony/routing/Matcher/RedirectableUrlMatcher.php +++ /dev/null @@ -1,64 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher; - -use Symfony\Component\Routing\Exception\ExceptionInterface; -use Symfony\Component\Routing\Exception\ResourceNotFoundException; - -/** - * @author Fabien Potencier - */ -abstract class RedirectableUrlMatcher extends UrlMatcher implements RedirectableUrlMatcherInterface -{ - /** - * {@inheritdoc} - */ - public function match(string $pathinfo) - { - try { - return parent::match($pathinfo); - } catch (ResourceNotFoundException $e) { - if (!\in_array($this->context->getMethod(), ['HEAD', 'GET'], true)) { - throw $e; - } - - if ($this->allowSchemes) { - redirect_scheme: - $scheme = $this->context->getScheme(); - $this->context->setScheme(current($this->allowSchemes)); - try { - $ret = parent::match($pathinfo); - - return $this->redirect($pathinfo, $ret['_route'] ?? null, $this->context->getScheme()) + $ret; - } catch (ExceptionInterface $e2) { - throw $e; - } finally { - $this->context->setScheme($scheme); - } - } elseif ('/' === $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/') { - throw $e; - } else { - try { - $pathinfo = $trimmedPathinfo === $pathinfo ? $pathinfo.'/' : $trimmedPathinfo; - $ret = parent::match($pathinfo); - - return $this->redirect($pathinfo, $ret['_route'] ?? null) + $ret; - } catch (ExceptionInterface $e2) { - if ($this->allowSchemes) { - goto redirect_scheme; - } - throw $e; - } - } - } - } -} diff --git a/digital_doctor/vendor/symfony/routing/Matcher/RedirectableUrlMatcherInterface.php b/digital_doctor/vendor/symfony/routing/Matcher/RedirectableUrlMatcherInterface.php deleted file mode 100644 index a43888b..0000000 --- a/digital_doctor/vendor/symfony/routing/Matcher/RedirectableUrlMatcherInterface.php +++ /dev/null @@ -1,31 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher; - -/** - * RedirectableUrlMatcherInterface knows how to redirect the user. - * - * @author Fabien Potencier - */ -interface RedirectableUrlMatcherInterface -{ - /** - * Redirects the user to another URL and returns the parameters for the redirection. - * - * @param string $path The path info to redirect to - * @param string $route The route name that matched - * @param string|null $scheme The URL scheme (null to keep the current one) - * - * @return array - */ - public function redirect(string $path, string $route, ?string $scheme = null); -} diff --git a/digital_doctor/vendor/symfony/routing/Matcher/RequestMatcherInterface.php b/digital_doctor/vendor/symfony/routing/Matcher/RequestMatcherInterface.php deleted file mode 100644 index c05016e..0000000 --- a/digital_doctor/vendor/symfony/routing/Matcher/RequestMatcherInterface.php +++ /dev/null @@ -1,39 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Routing\Exception\MethodNotAllowedException; -use Symfony\Component\Routing\Exception\NoConfigurationException; -use Symfony\Component\Routing\Exception\ResourceNotFoundException; - -/** - * RequestMatcherInterface is the interface that all request matcher classes must implement. - * - * @author Fabien Potencier - */ -interface RequestMatcherInterface -{ - /** - * Tries to match a request with a set of routes. - * - * If the matcher cannot find information, it must throw one of the exceptions documented - * below. - * - * @return array - * - * @throws NoConfigurationException If no routing configuration could be found - * @throws ResourceNotFoundException If no matching resource could be found - * @throws MethodNotAllowedException If a matching resource was found but the request method is not allowed - */ - public function matchRequest(Request $request); -} diff --git a/digital_doctor/vendor/symfony/routing/Matcher/TraceableUrlMatcher.php b/digital_doctor/vendor/symfony/routing/Matcher/TraceableUrlMatcher.php deleted file mode 100644 index cddfe02..0000000 --- a/digital_doctor/vendor/symfony/routing/Matcher/TraceableUrlMatcher.php +++ /dev/null @@ -1,164 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Routing\Exception\ExceptionInterface; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -/** - * TraceableUrlMatcher helps debug path info matching by tracing the match. - * - * @author Fabien Potencier - */ -class TraceableUrlMatcher extends UrlMatcher -{ - public const ROUTE_DOES_NOT_MATCH = 0; - public const ROUTE_ALMOST_MATCHES = 1; - public const ROUTE_MATCHES = 2; - - protected $traces; - - public function getTraces(string $pathinfo) - { - $this->traces = []; - - try { - $this->match($pathinfo); - } catch (ExceptionInterface $e) { - } - - return $this->traces; - } - - public function getTracesForRequest(Request $request) - { - $this->request = $request; - $traces = $this->getTraces($request->getPathInfo()); - $this->request = null; - - return $traces; - } - - protected function matchCollection(string $pathinfo, RouteCollection $routes) - { - // HEAD and GET are equivalent as per RFC - if ('HEAD' === $method = $this->context->getMethod()) { - $method = 'GET'; - } - $supportsTrailingSlash = 'GET' === $method && $this instanceof RedirectableUrlMatcherInterface; - $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/'; - - foreach ($routes as $name => $route) { - $compiledRoute = $route->compile(); - $staticPrefix = rtrim($compiledRoute->getStaticPrefix(), '/'); - $requiredMethods = $route->getMethods(); - - // check the static prefix of the URL first. Only use the more expensive preg_match when it matches - if ('' !== $staticPrefix && !str_starts_with($trimmedPathinfo, $staticPrefix)) { - $this->addTrace(sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route); - continue; - } - $regex = $compiledRoute->getRegex(); - - $pos = strrpos($regex, '$'); - $hasTrailingSlash = '/' === $regex[$pos - 1]; - $regex = substr_replace($regex, '/?$', $pos - $hasTrailingSlash, 1 + $hasTrailingSlash); - - if (!preg_match($regex, $pathinfo, $matches)) { - // does it match without any requirements? - $r = new Route($route->getPath(), $route->getDefaults(), [], $route->getOptions()); - $cr = $r->compile(); - if (!preg_match($cr->getRegex(), $pathinfo)) { - $this->addTrace(sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route); - - continue; - } - - foreach ($route->getRequirements() as $n => $regex) { - $r = new Route($route->getPath(), $route->getDefaults(), [$n => $regex], $route->getOptions()); - $cr = $r->compile(); - - if (\in_array($n, $cr->getVariables()) && !preg_match($cr->getRegex(), $pathinfo)) { - $this->addTrace(sprintf('Requirement for "%s" does not match (%s)', $n, $regex), self::ROUTE_ALMOST_MATCHES, $name, $route); - - continue 2; - } - } - - continue; - } - - $hasTrailingVar = $trimmedPathinfo !== $pathinfo && preg_match('#\{\w+\}/?$#', $route->getPath()); - - if ($hasTrailingVar && ($hasTrailingSlash || (null === $m = $matches[\count($compiledRoute->getPathVariables())] ?? null) || '/' !== ($m[-1] ?? '/')) && preg_match($regex, $trimmedPathinfo, $m)) { - if ($hasTrailingSlash) { - $matches = $m; - } else { - $hasTrailingVar = false; - } - } - - $hostMatches = []; - if ($compiledRoute->getHostRegex() && !preg_match($compiledRoute->getHostRegex(), $this->context->getHost(), $hostMatches)) { - $this->addTrace(sprintf('Host "%s" does not match the requirement ("%s")', $this->context->getHost(), $route->getHost()), self::ROUTE_ALMOST_MATCHES, $name, $route); - continue; - } - - $status = $this->handleRouteRequirements($pathinfo, $name, $route); - - if (self::REQUIREMENT_MISMATCH === $status[0]) { - $this->addTrace(sprintf('Condition "%s" does not evaluate to "true"', $route->getCondition()), self::ROUTE_ALMOST_MATCHES, $name, $route); - continue; - } - - if ('/' !== $pathinfo && !$hasTrailingVar && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) { - if ($supportsTrailingSlash && (!$requiredMethods || \in_array('GET', $requiredMethods))) { - $this->addTrace('Route matches!', self::ROUTE_MATCHES, $name, $route); - - return $this->allow = $this->allowSchemes = []; - } - $this->addTrace(sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route); - continue; - } - - if ($route->getSchemes() && !$route->hasScheme($this->context->getScheme())) { - $this->allowSchemes = array_merge($this->allowSchemes, $route->getSchemes()); - $this->addTrace(sprintf('Scheme "%s" does not match any of the required schemes (%s)', $this->context->getScheme(), implode(', ', $route->getSchemes())), self::ROUTE_ALMOST_MATCHES, $name, $route); - continue; - } - - if ($requiredMethods && !\in_array($method, $requiredMethods)) { - $this->allow = array_merge($this->allow, $requiredMethods); - $this->addTrace(sprintf('Method "%s" does not match any of the required methods (%s)', $this->context->getMethod(), implode(', ', $requiredMethods)), self::ROUTE_ALMOST_MATCHES, $name, $route); - continue; - } - - $this->addTrace('Route matches!', self::ROUTE_MATCHES, $name, $route); - - return $this->getAttributes($route, $name, array_replace($matches, $hostMatches, $status[1] ?? [])); - } - - return []; - } - - private function addTrace(string $log, int $level = self::ROUTE_DOES_NOT_MATCH, ?string $name = null, ?Route $route = null) - { - $this->traces[] = [ - 'log' => $log, - 'name' => $name, - 'level' => $level, - 'path' => null !== $route ? $route->getPath() : null, - ]; - } -} diff --git a/digital_doctor/vendor/symfony/routing/Matcher/UrlMatcher.php b/digital_doctor/vendor/symfony/routing/Matcher/UrlMatcher.php deleted file mode 100644 index f076a2f..0000000 --- a/digital_doctor/vendor/symfony/routing/Matcher/UrlMatcher.php +++ /dev/null @@ -1,279 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher; - -use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; -use Symfony\Component\ExpressionLanguage\ExpressionLanguage; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Routing\Exception\MethodNotAllowedException; -use Symfony\Component\Routing\Exception\NoConfigurationException; -use Symfony\Component\Routing\Exception\ResourceNotFoundException; -use Symfony\Component\Routing\RequestContext; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -/** - * UrlMatcher matches URL based on a set of routes. - * - * @author Fabien Potencier - */ -class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface -{ - public const REQUIREMENT_MATCH = 0; - public const REQUIREMENT_MISMATCH = 1; - public const ROUTE_MATCH = 2; - - /** @var RequestContext */ - protected $context; - - /** - * Collects HTTP methods that would be allowed for the request. - */ - protected $allow = []; - - /** - * Collects URI schemes that would be allowed for the request. - * - * @internal - */ - protected $allowSchemes = []; - - protected $routes; - protected $request; - protected $expressionLanguage; - - /** - * @var ExpressionFunctionProviderInterface[] - */ - protected $expressionLanguageProviders = []; - - public function __construct(RouteCollection $routes, RequestContext $context) - { - $this->routes = $routes; - $this->context = $context; - } - - /** - * {@inheritdoc} - */ - public function setContext(RequestContext $context) - { - $this->context = $context; - } - - /** - * {@inheritdoc} - */ - public function getContext() - { - return $this->context; - } - - /** - * {@inheritdoc} - */ - public function match(string $pathinfo) - { - $this->allow = $this->allowSchemes = []; - - if ($ret = $this->matchCollection(rawurldecode($pathinfo) ?: '/', $this->routes)) { - return $ret; - } - - if ('/' === $pathinfo && !$this->allow && !$this->allowSchemes) { - throw new NoConfigurationException(); - } - - throw 0 < \count($this->allow) ? new MethodNotAllowedException(array_unique($this->allow)) : new ResourceNotFoundException(sprintf('No routes found for "%s".', $pathinfo)); - } - - /** - * {@inheritdoc} - */ - public function matchRequest(Request $request) - { - $this->request = $request; - - $ret = $this->match($request->getPathInfo()); - - $this->request = null; - - return $ret; - } - - public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider) - { - $this->expressionLanguageProviders[] = $provider; - } - - /** - * Tries to match a URL with a set of routes. - * - * @param string $pathinfo The path info to be parsed - * - * @return array - * - * @throws NoConfigurationException If no routing configuration could be found - * @throws ResourceNotFoundException If the resource could not be found - * @throws MethodNotAllowedException If the resource was found but the request method is not allowed - */ - protected function matchCollection(string $pathinfo, RouteCollection $routes) - { - // HEAD and GET are equivalent as per RFC - if ('HEAD' === $method = $this->context->getMethod()) { - $method = 'GET'; - } - $supportsTrailingSlash = 'GET' === $method && $this instanceof RedirectableUrlMatcherInterface; - $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/'; - - foreach ($routes as $name => $route) { - $compiledRoute = $route->compile(); - $staticPrefix = rtrim($compiledRoute->getStaticPrefix(), '/'); - $requiredMethods = $route->getMethods(); - - // check the static prefix of the URL first. Only use the more expensive preg_match when it matches - if ('' !== $staticPrefix && !str_starts_with($trimmedPathinfo, $staticPrefix)) { - continue; - } - $regex = $compiledRoute->getRegex(); - - $pos = strrpos($regex, '$'); - $hasTrailingSlash = '/' === $regex[$pos - 1]; - $regex = substr_replace($regex, '/?$', $pos - $hasTrailingSlash, 1 + $hasTrailingSlash); - - if (!preg_match($regex, $pathinfo, $matches)) { - continue; - } - - $hasTrailingVar = $trimmedPathinfo !== $pathinfo && preg_match('#\{\w+\}/?$#', $route->getPath()); - - if ($hasTrailingVar && ($hasTrailingSlash || (null === $m = $matches[\count($compiledRoute->getPathVariables())] ?? null) || '/' !== ($m[-1] ?? '/')) && preg_match($regex, $trimmedPathinfo, $m)) { - if ($hasTrailingSlash) { - $matches = $m; - } else { - $hasTrailingVar = false; - } - } - - $hostMatches = []; - if ($compiledRoute->getHostRegex() && !preg_match($compiledRoute->getHostRegex(), $this->context->getHost(), $hostMatches)) { - continue; - } - - $status = $this->handleRouteRequirements($pathinfo, $name, $route); - - if (self::REQUIREMENT_MISMATCH === $status[0]) { - continue; - } - - if ('/' !== $pathinfo && !$hasTrailingVar && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) { - if ($supportsTrailingSlash && (!$requiredMethods || \in_array('GET', $requiredMethods))) { - return $this->allow = $this->allowSchemes = []; - } - continue; - } - - if ($route->getSchemes() && !$route->hasScheme($this->context->getScheme())) { - $this->allowSchemes = array_merge($this->allowSchemes, $route->getSchemes()); - continue; - } - - if ($requiredMethods && !\in_array($method, $requiredMethods)) { - $this->allow = array_merge($this->allow, $requiredMethods); - continue; - } - - return $this->getAttributes($route, $name, array_replace($matches, $hostMatches, $status[1] ?? [])); - } - - return []; - } - - /** - * Returns an array of values to use as request attributes. - * - * As this method requires the Route object, it is not available - * in matchers that do not have access to the matched Route instance - * (like the PHP and Apache matcher dumpers). - * - * @return array - */ - protected function getAttributes(Route $route, string $name, array $attributes) - { - $defaults = $route->getDefaults(); - if (isset($defaults['_canonical_route'])) { - $name = $defaults['_canonical_route']; - unset($defaults['_canonical_route']); - } - $attributes['_route'] = $name; - - return $this->mergeDefaults($attributes, $defaults); - } - - /** - * Handles specific route requirements. - * - * @return array The first element represents the status, the second contains additional information - */ - protected function handleRouteRequirements(string $pathinfo, string $name, Route $route) - { - // expression condition - if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), ['context' => $this->context, 'request' => $this->request ?: $this->createRequest($pathinfo)])) { - return [self::REQUIREMENT_MISMATCH, null]; - } - - return [self::REQUIREMENT_MATCH, null]; - } - - /** - * Get merged default parameters. - * - * @return array - */ - protected function mergeDefaults(array $params, array $defaults) - { - foreach ($params as $key => $value) { - if (!\is_int($key) && null !== $value) { - $defaults[$key] = $value; - } - } - - return $defaults; - } - - protected function getExpressionLanguage() - { - if (null === $this->expressionLanguage) { - if (!class_exists(ExpressionLanguage::class)) { - throw new \LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); - } - $this->expressionLanguage = new ExpressionLanguage(null, $this->expressionLanguageProviders); - } - - return $this->expressionLanguage; - } - - /** - * @internal - */ - protected function createRequest(string $pathinfo): ?Request - { - if (!class_exists(Request::class)) { - return null; - } - - return Request::create($this->context->getScheme().'://'.$this->context->getHost().$this->context->getBaseUrl().$pathinfo, $this->context->getMethod(), $this->context->getParameters(), [], [], [ - 'SCRIPT_FILENAME' => $this->context->getBaseUrl(), - 'SCRIPT_NAME' => $this->context->getBaseUrl(), - ]); - } -} diff --git a/digital_doctor/vendor/symfony/routing/Matcher/UrlMatcherInterface.php b/digital_doctor/vendor/symfony/routing/Matcher/UrlMatcherInterface.php deleted file mode 100644 index 0a5be97..0000000 --- a/digital_doctor/vendor/symfony/routing/Matcher/UrlMatcherInterface.php +++ /dev/null @@ -1,41 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher; - -use Symfony\Component\Routing\Exception\MethodNotAllowedException; -use Symfony\Component\Routing\Exception\NoConfigurationException; -use Symfony\Component\Routing\Exception\ResourceNotFoundException; -use Symfony\Component\Routing\RequestContextAwareInterface; - -/** - * UrlMatcherInterface is the interface that all URL matcher classes must implement. - * - * @author Fabien Potencier - */ -interface UrlMatcherInterface extends RequestContextAwareInterface -{ - /** - * Tries to match a URL path with a set of routes. - * - * If the matcher cannot find information, it must throw one of the exceptions documented - * below. - * - * @param string $pathinfo The path info to be parsed (raw format, i.e. not urldecoded) - * - * @return array - * - * @throws NoConfigurationException If no routing configuration could be found - * @throws ResourceNotFoundException If the resource could not be found - * @throws MethodNotAllowedException If the resource was found but the request method is not allowed - */ - public function match(string $pathinfo); -} diff --git a/digital_doctor/vendor/symfony/routing/README.md b/digital_doctor/vendor/symfony/routing/README.md deleted file mode 100644 index ae8284f..0000000 --- a/digital_doctor/vendor/symfony/routing/README.md +++ /dev/null @@ -1,51 +0,0 @@ -Routing Component -================= - -The Routing component maps an HTTP request to a set of configuration variables. - -Getting Started ---------------- - -``` -$ composer require symfony/routing -``` - -```php -use App\Controller\BlogController; -use Symfony\Component\Routing\Generator\UrlGenerator; -use Symfony\Component\Routing\Matcher\UrlMatcher; -use Symfony\Component\Routing\RequestContext; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -$route = new Route('/blog/{slug}', ['_controller' => BlogController::class]); -$routes = new RouteCollection(); -$routes->add('blog_show', $route); - -$context = new RequestContext(); - -// Routing can match routes with incoming requests -$matcher = new UrlMatcher($routes, $context); -$parameters = $matcher->match('/blog/lorem-ipsum'); -// $parameters = [ -// '_controller' => 'App\Controller\BlogController', -// 'slug' => 'lorem-ipsum', -// '_route' => 'blog_show' -// ] - -// Routing can also generate URLs for a given route -$generator = new UrlGenerator($routes, $context); -$url = $generator->generate('blog_show', [ - 'slug' => 'my-blog-post', -]); -// $url = '/blog/my-blog-post' -``` - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/routing.html) - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/digital_doctor/vendor/symfony/routing/RequestContext.php b/digital_doctor/vendor/symfony/routing/RequestContext.php deleted file mode 100644 index f54c430..0000000 --- a/digital_doctor/vendor/symfony/routing/RequestContext.php +++ /dev/null @@ -1,327 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing; - -use Symfony\Component\HttpFoundation\Request; - -/** - * Holds information about the current request. - * - * This class implements a fluent interface. - * - * @author Fabien Potencier - * @author Tobias Schultze - */ -class RequestContext -{ - private $baseUrl; - private $pathInfo; - private $method; - private $host; - private $scheme; - private $httpPort; - private $httpsPort; - private $queryString; - private $parameters = []; - - public function __construct(string $baseUrl = '', string $method = 'GET', string $host = 'localhost', string $scheme = 'http', int $httpPort = 80, int $httpsPort = 443, string $path = '/', string $queryString = '') - { - $this->setBaseUrl($baseUrl); - $this->setMethod($method); - $this->setHost($host); - $this->setScheme($scheme); - $this->setHttpPort($httpPort); - $this->setHttpsPort($httpsPort); - $this->setPathInfo($path); - $this->setQueryString($queryString); - } - - public static function fromUri(string $uri, string $host = 'localhost', string $scheme = 'http', int $httpPort = 80, int $httpsPort = 443): self - { - $uri = parse_url($uri); - $scheme = $uri['scheme'] ?? $scheme; - $host = $uri['host'] ?? $host; - - if (isset($uri['port'])) { - if ('http' === $scheme) { - $httpPort = $uri['port']; - } elseif ('https' === $scheme) { - $httpsPort = $uri['port']; - } - } - - return new self($uri['path'] ?? '', 'GET', $host, $scheme, $httpPort, $httpsPort); - } - - /** - * Updates the RequestContext information based on a HttpFoundation Request. - * - * @return $this - */ - public function fromRequest(Request $request) - { - $this->setBaseUrl($request->getBaseUrl()); - $this->setPathInfo($request->getPathInfo()); - $this->setMethod($request->getMethod()); - $this->setHost($request->getHost()); - $this->setScheme($request->getScheme()); - $this->setHttpPort($request->isSecure() || null === $request->getPort() ? $this->httpPort : $request->getPort()); - $this->setHttpsPort($request->isSecure() && null !== $request->getPort() ? $request->getPort() : $this->httpsPort); - $this->setQueryString($request->server->get('QUERY_STRING', '')); - - return $this; - } - - /** - * Gets the base URL. - * - * @return string - */ - public function getBaseUrl() - { - return $this->baseUrl; - } - - /** - * Sets the base URL. - * - * @return $this - */ - public function setBaseUrl(string $baseUrl) - { - $this->baseUrl = rtrim($baseUrl, '/'); - - return $this; - } - - /** - * Gets the path info. - * - * @return string - */ - public function getPathInfo() - { - return $this->pathInfo; - } - - /** - * Sets the path info. - * - * @return $this - */ - public function setPathInfo(string $pathInfo) - { - $this->pathInfo = $pathInfo; - - return $this; - } - - /** - * Gets the HTTP method. - * - * The method is always an uppercased string. - * - * @return string - */ - public function getMethod() - { - return $this->method; - } - - /** - * Sets the HTTP method. - * - * @return $this - */ - public function setMethod(string $method) - { - $this->method = strtoupper($method); - - return $this; - } - - /** - * Gets the HTTP host. - * - * The host is always lowercased because it must be treated case-insensitive. - * - * @return string - */ - public function getHost() - { - return $this->host; - } - - /** - * Sets the HTTP host. - * - * @return $this - */ - public function setHost(string $host) - { - $this->host = strtolower($host); - - return $this; - } - - /** - * Gets the HTTP scheme. - * - * @return string - */ - public function getScheme() - { - return $this->scheme; - } - - /** - * Sets the HTTP scheme. - * - * @return $this - */ - public function setScheme(string $scheme) - { - $this->scheme = strtolower($scheme); - - return $this; - } - - /** - * Gets the HTTP port. - * - * @return int - */ - public function getHttpPort() - { - return $this->httpPort; - } - - /** - * Sets the HTTP port. - * - * @return $this - */ - public function setHttpPort(int $httpPort) - { - $this->httpPort = $httpPort; - - return $this; - } - - /** - * Gets the HTTPS port. - * - * @return int - */ - public function getHttpsPort() - { - return $this->httpsPort; - } - - /** - * Sets the HTTPS port. - * - * @return $this - */ - public function setHttpsPort(int $httpsPort) - { - $this->httpsPort = $httpsPort; - - return $this; - } - - /** - * Gets the query string without the "?". - * - * @return string - */ - public function getQueryString() - { - return $this->queryString; - } - - /** - * Sets the query string. - * - * @return $this - */ - public function setQueryString(?string $queryString) - { - // string cast to be fault-tolerant, accepting null - $this->queryString = (string) $queryString; - - return $this; - } - - /** - * Returns the parameters. - * - * @return array - */ - public function getParameters() - { - return $this->parameters; - } - - /** - * Sets the parameters. - * - * @param array $parameters The parameters - * - * @return $this - */ - public function setParameters(array $parameters) - { - $this->parameters = $parameters; - - return $this; - } - - /** - * Gets a parameter value. - * - * @return mixed - */ - public function getParameter(string $name) - { - return $this->parameters[$name] ?? null; - } - - /** - * Checks if a parameter value is set for the given parameter. - * - * @return bool - */ - public function hasParameter(string $name) - { - return \array_key_exists($name, $this->parameters); - } - - /** - * Sets a parameter value. - * - * @param mixed $parameter The parameter value - * - * @return $this - */ - public function setParameter(string $name, $parameter) - { - $this->parameters[$name] = $parameter; - - return $this; - } - - public function isSecure(): bool - { - return 'https' === $this->scheme; - } -} diff --git a/digital_doctor/vendor/symfony/routing/RequestContextAwareInterface.php b/digital_doctor/vendor/symfony/routing/RequestContextAwareInterface.php deleted file mode 100644 index 270a2b0..0000000 --- a/digital_doctor/vendor/symfony/routing/RequestContextAwareInterface.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing; - -interface RequestContextAwareInterface -{ - /** - * Sets the request context. - */ - public function setContext(RequestContext $context); - - /** - * Gets the request context. - * - * @return RequestContext - */ - public function getContext(); -} diff --git a/digital_doctor/vendor/symfony/routing/Route.php b/digital_doctor/vendor/symfony/routing/Route.php deleted file mode 100644 index c67bd2d..0000000 --- a/digital_doctor/vendor/symfony/routing/Route.php +++ /dev/null @@ -1,507 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing; - -/** - * A Route describes a route and its parameters. - * - * @author Fabien Potencier - * @author Tobias Schultze - */ -class Route implements \Serializable -{ - private $path = '/'; - private $host = ''; - private $schemes = []; - private $methods = []; - private $defaults = []; - private $requirements = []; - private $options = []; - private $condition = ''; - - /** - * @var CompiledRoute|null - */ - private $compiled; - - /** - * Constructor. - * - * Available options: - * - * * compiler_class: A class name able to compile this route instance (RouteCompiler by default) - * * utf8: Whether UTF-8 matching is enforced ot not - * - * @param string $path The path pattern to match - * @param array $defaults An array of default parameter values - * @param array $requirements An array of requirements for parameters (regexes) - * @param array $options An array of options - * @param string|null $host The host pattern to match - * @param string|string[] $schemes A required URI scheme or an array of restricted schemes - * @param string|string[] $methods A required HTTP method or an array of restricted methods - * @param string|null $condition A condition that should evaluate to true for the route to match - */ - public function __construct(string $path, array $defaults = [], array $requirements = [], array $options = [], ?string $host = '', $schemes = [], $methods = [], ?string $condition = '') - { - $this->setPath($path); - $this->addDefaults($defaults); - $this->addRequirements($requirements); - $this->setOptions($options); - $this->setHost($host); - $this->setSchemes($schemes); - $this->setMethods($methods); - $this->setCondition($condition); - } - - public function __serialize(): array - { - return [ - 'path' => $this->path, - 'host' => $this->host, - 'defaults' => $this->defaults, - 'requirements' => $this->requirements, - 'options' => $this->options, - 'schemes' => $this->schemes, - 'methods' => $this->methods, - 'condition' => $this->condition, - 'compiled' => $this->compiled, - ]; - } - - /** - * @internal - */ - final public function serialize(): string - { - return serialize($this->__serialize()); - } - - public function __unserialize(array $data): void - { - $this->path = $data['path']; - $this->host = $data['host']; - $this->defaults = $data['defaults']; - $this->requirements = $data['requirements']; - $this->options = $data['options']; - $this->schemes = $data['schemes']; - $this->methods = $data['methods']; - - if (isset($data['condition'])) { - $this->condition = $data['condition']; - } - if (isset($data['compiled'])) { - $this->compiled = $data['compiled']; - } - } - - /** - * @internal - */ - final public function unserialize($serialized) - { - $this->__unserialize(unserialize($serialized)); - } - - /** - * @return string - */ - public function getPath() - { - return $this->path; - } - - /** - * @return $this - */ - public function setPath(string $pattern) - { - $pattern = $this->extractInlineDefaultsAndRequirements($pattern); - - // A pattern must start with a slash and must not have multiple slashes at the beginning because the - // generated path for this route would be confused with a network path, e.g. '//domain.com/path'. - $this->path = '/'.ltrim(trim($pattern), '/'); - $this->compiled = null; - - return $this; - } - - /** - * @return string - */ - public function getHost() - { - return $this->host; - } - - /** - * @return $this - */ - public function setHost(?string $pattern) - { - $this->host = $this->extractInlineDefaultsAndRequirements((string) $pattern); - $this->compiled = null; - - return $this; - } - - /** - * Returns the lowercased schemes this route is restricted to. - * So an empty array means that any scheme is allowed. - * - * @return string[] - */ - public function getSchemes() - { - return $this->schemes; - } - - /** - * Sets the schemes (e.g. 'https') this route is restricted to. - * So an empty array means that any scheme is allowed. - * - * @param string|string[] $schemes The scheme or an array of schemes - * - * @return $this - */ - public function setSchemes($schemes) - { - $this->schemes = array_map('strtolower', (array) $schemes); - $this->compiled = null; - - return $this; - } - - /** - * Checks if a scheme requirement has been set. - * - * @return bool - */ - public function hasScheme(string $scheme) - { - return \in_array(strtolower($scheme), $this->schemes, true); - } - - /** - * Returns the uppercased HTTP methods this route is restricted to. - * So an empty array means that any method is allowed. - * - * @return string[] - */ - public function getMethods() - { - return $this->methods; - } - - /** - * Sets the HTTP methods (e.g. 'POST') this route is restricted to. - * So an empty array means that any method is allowed. - * - * @param string|string[] $methods The method or an array of methods - * - * @return $this - */ - public function setMethods($methods) - { - $this->methods = array_map('strtoupper', (array) $methods); - $this->compiled = null; - - return $this; - } - - /** - * @return array - */ - public function getOptions() - { - return $this->options; - } - - /** - * @return $this - */ - public function setOptions(array $options) - { - $this->options = [ - 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler', - ]; - - return $this->addOptions($options); - } - - /** - * @return $this - */ - public function addOptions(array $options) - { - foreach ($options as $name => $option) { - $this->options[$name] = $option; - } - $this->compiled = null; - - return $this; - } - - /** - * Sets an option value. - * - * @param mixed $value The option value - * - * @return $this - */ - public function setOption(string $name, $value) - { - $this->options[$name] = $value; - $this->compiled = null; - - return $this; - } - - /** - * Returns the option value or null when not found. - * - * @return mixed - */ - public function getOption(string $name) - { - return $this->options[$name] ?? null; - } - - /** - * @return bool - */ - public function hasOption(string $name) - { - return \array_key_exists($name, $this->options); - } - - /** - * @return array - */ - public function getDefaults() - { - return $this->defaults; - } - - /** - * @return $this - */ - public function setDefaults(array $defaults) - { - $this->defaults = []; - - return $this->addDefaults($defaults); - } - - /** - * @return $this - */ - public function addDefaults(array $defaults) - { - if (isset($defaults['_locale']) && $this->isLocalized()) { - unset($defaults['_locale']); - } - - foreach ($defaults as $name => $default) { - $this->defaults[$name] = $default; - } - $this->compiled = null; - - return $this; - } - - /** - * @return mixed - */ - public function getDefault(string $name) - { - return $this->defaults[$name] ?? null; - } - - /** - * @return bool - */ - public function hasDefault(string $name) - { - return \array_key_exists($name, $this->defaults); - } - - /** - * Sets a default value. - * - * @param mixed $default The default value - * - * @return $this - */ - public function setDefault(string $name, $default) - { - if ('_locale' === $name && $this->isLocalized()) { - return $this; - } - - $this->defaults[$name] = $default; - $this->compiled = null; - - return $this; - } - - /** - * @return array - */ - public function getRequirements() - { - return $this->requirements; - } - - /** - * @return $this - */ - public function setRequirements(array $requirements) - { - $this->requirements = []; - - return $this->addRequirements($requirements); - } - - /** - * @return $this - */ - public function addRequirements(array $requirements) - { - if (isset($requirements['_locale']) && $this->isLocalized()) { - unset($requirements['_locale']); - } - - foreach ($requirements as $key => $regex) { - $this->requirements[$key] = $this->sanitizeRequirement($key, $regex); - } - $this->compiled = null; - - return $this; - } - - /** - * @return string|null - */ - public function getRequirement(string $key) - { - return $this->requirements[$key] ?? null; - } - - /** - * @return bool - */ - public function hasRequirement(string $key) - { - return \array_key_exists($key, $this->requirements); - } - - /** - * @return $this - */ - public function setRequirement(string $key, string $regex) - { - if ('_locale' === $key && $this->isLocalized()) { - return $this; - } - - $this->requirements[$key] = $this->sanitizeRequirement($key, $regex); - $this->compiled = null; - - return $this; - } - - /** - * @return string - */ - public function getCondition() - { - return $this->condition; - } - - /** - * @return $this - */ - public function setCondition(?string $condition) - { - $this->condition = (string) $condition; - $this->compiled = null; - - return $this; - } - - /** - * Compiles the route. - * - * @return CompiledRoute - * - * @throws \LogicException If the Route cannot be compiled because the - * path or host pattern is invalid - * - * @see RouteCompiler which is responsible for the compilation process - */ - public function compile() - { - if (null !== $this->compiled) { - return $this->compiled; - } - - $class = $this->getOption('compiler_class'); - - return $this->compiled = $class::compile($this); - } - - private function extractInlineDefaultsAndRequirements(string $pattern): string - { - if (false === strpbrk($pattern, '?<')) { - return $pattern; - } - - return preg_replace_callback('#\{(!?)(\w++)(<.*?>)?(\?[^\}]*+)?\}#', function ($m) { - if (isset($m[4][0])) { - $this->setDefault($m[2], '?' !== $m[4] ? substr($m[4], 1) : null); - } - if (isset($m[3][0])) { - $this->setRequirement($m[2], substr($m[3], 1, -1)); - } - - return '{'.$m[1].$m[2].'}'; - }, $pattern); - } - - private function sanitizeRequirement(string $key, string $regex) - { - if ('' !== $regex) { - if ('^' === $regex[0]) { - $regex = substr($regex, 1); - } elseif (0 === strpos($regex, '\\A')) { - $regex = substr($regex, 2); - } - } - - if (str_ends_with($regex, '$')) { - $regex = substr($regex, 0, -1); - } elseif (\strlen($regex) - 2 === strpos($regex, '\\z')) { - $regex = substr($regex, 0, -2); - } - - if ('' === $regex) { - throw new \InvalidArgumentException(sprintf('Routing requirement for "%s" cannot be empty.', $key)); - } - - return $regex; - } - - private function isLocalized(): bool - { - return isset($this->defaults['_locale']) && isset($this->defaults['_canonical_route']) && ($this->requirements['_locale'] ?? null) === preg_quote($this->defaults['_locale']); - } -} diff --git a/digital_doctor/vendor/symfony/routing/RouteCollection.php b/digital_doctor/vendor/symfony/routing/RouteCollection.php deleted file mode 100644 index 95faead..0000000 --- a/digital_doctor/vendor/symfony/routing/RouteCollection.php +++ /dev/null @@ -1,403 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing; - -use Symfony\Component\Config\Resource\ResourceInterface; -use Symfony\Component\Routing\Exception\InvalidArgumentException; -use Symfony\Component\Routing\Exception\RouteCircularReferenceException; - -/** - * A RouteCollection represents a set of Route instances. - * - * When adding a route at the end of the collection, an existing route - * with the same name is removed first. So there can only be one route - * with a given name. - * - * @author Fabien Potencier - * @author Tobias Schultze - * - * @implements \IteratorAggregate - */ -class RouteCollection implements \IteratorAggregate, \Countable -{ - /** - * @var array - */ - private $routes = []; - - /** - * @var array - */ - private $aliases = []; - - /** - * @var array - */ - private $resources = []; - - /** - * @var array - */ - private $priorities = []; - - public function __clone() - { - foreach ($this->routes as $name => $route) { - $this->routes[$name] = clone $route; - } - - foreach ($this->aliases as $name => $alias) { - $this->aliases[$name] = clone $alias; - } - } - - /** - * Gets the current RouteCollection as an Iterator that includes all routes. - * - * It implements \IteratorAggregate. - * - * @see all() - * - * @return \ArrayIterator - */ - #[\ReturnTypeWillChange] - public function getIterator() - { - return new \ArrayIterator($this->all()); - } - - /** - * Gets the number of Routes in this collection. - * - * @return int - */ - #[\ReturnTypeWillChange] - public function count() - { - return \count($this->routes); - } - - /** - * @param int $priority - */ - public function add(string $name, Route $route/* , int $priority = 0 */) - { - if (\func_num_args() < 3 && __CLASS__ !== static::class && __CLASS__ !== (new \ReflectionMethod($this, __FUNCTION__))->getDeclaringClass()->getName() && !$this instanceof \PHPUnit\Framework\MockObject\MockObject && !$this instanceof \Prophecy\Prophecy\ProphecySubjectInterface && !$this instanceof \Mockery\MockInterface) { - trigger_deprecation('symfony/routing', '5.1', 'The "%s()" method will have a new "int $priority = 0" argument in version 6.0, not defining it is deprecated.', __METHOD__); - } - - unset($this->routes[$name], $this->priorities[$name], $this->aliases[$name]); - - $this->routes[$name] = $route; - - if ($priority = 3 <= \func_num_args() ? func_get_arg(2) : 0) { - $this->priorities[$name] = $priority; - } - } - - /** - * Returns all routes in this collection. - * - * @return array - */ - public function all() - { - if ($this->priorities) { - $priorities = $this->priorities; - $keysOrder = array_flip(array_keys($this->routes)); - uksort($this->routes, static function ($n1, $n2) use ($priorities, $keysOrder) { - return (($priorities[$n2] ?? 0) <=> ($priorities[$n1] ?? 0)) ?: ($keysOrder[$n1] <=> $keysOrder[$n2]); - }); - } - - return $this->routes; - } - - /** - * Gets a route by name. - * - * @return Route|null - */ - public function get(string $name) - { - $visited = []; - while (null !== $alias = $this->aliases[$name] ?? null) { - if (false !== $searchKey = array_search($name, $visited)) { - $visited[] = $name; - - throw new RouteCircularReferenceException($name, \array_slice($visited, $searchKey)); - } - - if ($alias->isDeprecated()) { - $deprecation = $alias->getDeprecation($name); - - trigger_deprecation($deprecation['package'], $deprecation['version'], $deprecation['message']); - } - - $visited[] = $name; - $name = $alias->getId(); - } - - return $this->routes[$name] ?? null; - } - - /** - * Removes a route or an array of routes by name from the collection. - * - * @param string|string[] $name The route name or an array of route names - */ - public function remove($name) - { - $routes = []; - foreach ((array) $name as $n) { - if (isset($this->routes[$n])) { - $routes[] = $n; - } - - unset($this->routes[$n], $this->priorities[$n], $this->aliases[$n]); - } - - if (!$routes) { - return; - } - - foreach ($this->aliases as $k => $alias) { - if (\in_array($alias->getId(), $routes, true)) { - unset($this->aliases[$k]); - } - } - } - - /** - * Adds a route collection at the end of the current set by appending all - * routes of the added collection. - */ - public function addCollection(self $collection) - { - // we need to remove all routes with the same names first because just replacing them - // would not place the new route at the end of the merged array - foreach ($collection->all() as $name => $route) { - unset($this->routes[$name], $this->priorities[$name], $this->aliases[$name]); - $this->routes[$name] = $route; - - if (isset($collection->priorities[$name])) { - $this->priorities[$name] = $collection->priorities[$name]; - } - } - - foreach ($collection->getAliases() as $name => $alias) { - unset($this->routes[$name], $this->priorities[$name], $this->aliases[$name]); - - $this->aliases[$name] = $alias; - } - - foreach ($collection->getResources() as $resource) { - $this->addResource($resource); - } - } - - /** - * Adds a prefix to the path of all child routes. - */ - public function addPrefix(string $prefix, array $defaults = [], array $requirements = []) - { - $prefix = trim(trim($prefix), '/'); - - if ('' === $prefix) { - return; - } - - foreach ($this->routes as $route) { - $route->setPath('/'.$prefix.$route->getPath()); - $route->addDefaults($defaults); - $route->addRequirements($requirements); - } - } - - /** - * Adds a prefix to the name of all the routes within in the collection. - */ - public function addNamePrefix(string $prefix) - { - $prefixedRoutes = []; - $prefixedPriorities = []; - $prefixedAliases = []; - - foreach ($this->routes as $name => $route) { - $prefixedRoutes[$prefix.$name] = $route; - if (null !== $canonicalName = $route->getDefault('_canonical_route')) { - $route->setDefault('_canonical_route', $prefix.$canonicalName); - } - if (isset($this->priorities[$name])) { - $prefixedPriorities[$prefix.$name] = $this->priorities[$name]; - } - } - - foreach ($this->aliases as $name => $alias) { - $prefixedAliases[$prefix.$name] = $alias->withId($prefix.$alias->getId()); - } - - $this->routes = $prefixedRoutes; - $this->priorities = $prefixedPriorities; - $this->aliases = $prefixedAliases; - } - - /** - * Sets the host pattern on all routes. - */ - public function setHost(?string $pattern, array $defaults = [], array $requirements = []) - { - foreach ($this->routes as $route) { - $route->setHost($pattern); - $route->addDefaults($defaults); - $route->addRequirements($requirements); - } - } - - /** - * Sets a condition on all routes. - * - * Existing conditions will be overridden. - */ - public function setCondition(?string $condition) - { - foreach ($this->routes as $route) { - $route->setCondition($condition); - } - } - - /** - * Adds defaults to all routes. - * - * An existing default value under the same name in a route will be overridden. - */ - public function addDefaults(array $defaults) - { - if ($defaults) { - foreach ($this->routes as $route) { - $route->addDefaults($defaults); - } - } - } - - /** - * Adds requirements to all routes. - * - * An existing requirement under the same name in a route will be overridden. - */ - public function addRequirements(array $requirements) - { - if ($requirements) { - foreach ($this->routes as $route) { - $route->addRequirements($requirements); - } - } - } - - /** - * Adds options to all routes. - * - * An existing option value under the same name in a route will be overridden. - */ - public function addOptions(array $options) - { - if ($options) { - foreach ($this->routes as $route) { - $route->addOptions($options); - } - } - } - - /** - * Sets the schemes (e.g. 'https') all child routes are restricted to. - * - * @param string|string[] $schemes The scheme or an array of schemes - */ - public function setSchemes($schemes) - { - foreach ($this->routes as $route) { - $route->setSchemes($schemes); - } - } - - /** - * Sets the HTTP methods (e.g. 'POST') all child routes are restricted to. - * - * @param string|string[] $methods The method or an array of methods - */ - public function setMethods($methods) - { - foreach ($this->routes as $route) { - $route->setMethods($methods); - } - } - - /** - * Returns an array of resources loaded to build this collection. - * - * @return ResourceInterface[] - */ - public function getResources() - { - return array_values($this->resources); - } - - /** - * Adds a resource for this collection. If the resource already exists - * it is not added. - */ - public function addResource(ResourceInterface $resource) - { - $key = (string) $resource; - - if (!isset($this->resources[$key])) { - $this->resources[$key] = $resource; - } - } - - /** - * Sets an alias for an existing route. - * - * @param string $name The alias to create - * @param string $alias The route to alias - * - * @throws InvalidArgumentException if the alias is for itself - */ - public function addAlias(string $name, string $alias): Alias - { - if ($name === $alias) { - throw new InvalidArgumentException(sprintf('Route alias "%s" can not reference itself.', $name)); - } - - unset($this->routes[$name], $this->priorities[$name]); - - return $this->aliases[$name] = new Alias($alias); - } - - /** - * @return array - */ - public function getAliases(): array - { - return $this->aliases; - } - - public function getAlias(string $name): ?Alias - { - return $this->aliases[$name] ?? null; - } - - public function getPriority(string $name): ?int - { - return $this->priorities[$name] ?? null; - } -} diff --git a/digital_doctor/vendor/symfony/routing/RouteCollectionBuilder.php b/digital_doctor/vendor/symfony/routing/RouteCollectionBuilder.php deleted file mode 100644 index 04a4439..0000000 --- a/digital_doctor/vendor/symfony/routing/RouteCollectionBuilder.php +++ /dev/null @@ -1,364 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing; - -use Symfony\Component\Config\Exception\LoaderLoadException; -use Symfony\Component\Config\Loader\LoaderInterface; -use Symfony\Component\Config\Resource\ResourceInterface; -use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator; - -trigger_deprecation('symfony/routing', '5.1', 'The "%s" class is deprecated, use "%s" instead.', RouteCollectionBuilder::class, RoutingConfigurator::class); - -/** - * Helps add and import routes into a RouteCollection. - * - * @author Ryan Weaver - * - * @deprecated since Symfony 5.1, use RoutingConfigurator instead - */ -class RouteCollectionBuilder -{ - /** - * @var Route[]|RouteCollectionBuilder[] - */ - private $routes = []; - - private $loader; - private $defaults = []; - private $prefix; - private $host; - private $condition; - private $requirements = []; - private $options = []; - private $schemes; - private $methods; - private $resources = []; - - public function __construct(?LoaderInterface $loader = null) - { - $this->loader = $loader; - } - - /** - * Import an external routing resource and returns the RouteCollectionBuilder. - * - * $routes->import('blog.yml', '/blog'); - * - * @param mixed $resource - * - * @return self - * - * @throws LoaderLoadException - */ - public function import($resource, string $prefix = '/', ?string $type = null) - { - /** @var RouteCollection[] $collections */ - $collections = $this->load($resource, $type); - - // create a builder from the RouteCollection - $builder = $this->createBuilder(); - - foreach ($collections as $collection) { - if (null === $collection) { - continue; - } - - foreach ($collection->all() as $name => $route) { - $builder->addRoute($route, $name); - } - - foreach ($collection->getResources() as $resource) { - $builder->addResource($resource); - } - } - - // mount into this builder - $this->mount($prefix, $builder); - - return $builder; - } - - /** - * Adds a route and returns it for future modification. - * - * @return Route - */ - public function add(string $path, string $controller, ?string $name = null) - { - $route = new Route($path); - $route->setDefault('_controller', $controller); - $this->addRoute($route, $name); - - return $route; - } - - /** - * Returns a RouteCollectionBuilder that can be configured and then added with mount(). - * - * @return self - */ - public function createBuilder() - { - return new self($this->loader); - } - - /** - * Add a RouteCollectionBuilder. - */ - public function mount(string $prefix, self $builder) - { - $builder->prefix = trim(trim($prefix), '/'); - $this->routes[] = $builder; - } - - /** - * Adds a Route object to the builder. - * - * @return $this - */ - public function addRoute(Route $route, ?string $name = null) - { - if (null === $name) { - // used as a flag to know which routes will need a name later - $name = '_unnamed_route_'.spl_object_hash($route); - } - - $this->routes[$name] = $route; - - return $this; - } - - /** - * Sets the host on all embedded routes (unless already set). - * - * @return $this - */ - public function setHost(?string $pattern) - { - $this->host = $pattern; - - return $this; - } - - /** - * Sets a condition on all embedded routes (unless already set). - * - * @return $this - */ - public function setCondition(?string $condition) - { - $this->condition = $condition; - - return $this; - } - - /** - * Sets a default value that will be added to all embedded routes (unless that - * default value is already set). - * - * @param mixed $value - * - * @return $this - */ - public function setDefault(string $key, $value) - { - $this->defaults[$key] = $value; - - return $this; - } - - /** - * Sets a requirement that will be added to all embedded routes (unless that - * requirement is already set). - * - * @param mixed $regex - * - * @return $this - */ - public function setRequirement(string $key, $regex) - { - $this->requirements[$key] = $regex; - - return $this; - } - - /** - * Sets an option that will be added to all embedded routes (unless that - * option is already set). - * - * @param mixed $value - * - * @return $this - */ - public function setOption(string $key, $value) - { - $this->options[$key] = $value; - - return $this; - } - - /** - * Sets the schemes on all embedded routes (unless already set). - * - * @param array|string $schemes - * - * @return $this - */ - public function setSchemes($schemes) - { - $this->schemes = $schemes; - - return $this; - } - - /** - * Sets the methods on all embedded routes (unless already set). - * - * @param array|string $methods - * - * @return $this - */ - public function setMethods($methods) - { - $this->methods = $methods; - - return $this; - } - - /** - * Adds a resource for this collection. - * - * @return $this - */ - private function addResource(ResourceInterface $resource): self - { - $this->resources[] = $resource; - - return $this; - } - - /** - * Creates the final RouteCollection and returns it. - * - * @return RouteCollection - */ - public function build() - { - $routeCollection = new RouteCollection(); - - foreach ($this->routes as $name => $route) { - if ($route instanceof Route) { - $route->setDefaults(array_merge($this->defaults, $route->getDefaults())); - $route->setOptions(array_merge($this->options, $route->getOptions())); - - foreach ($this->requirements as $key => $val) { - if (!$route->hasRequirement($key)) { - $route->setRequirement($key, $val); - } - } - - if (null !== $this->prefix) { - $route->setPath('/'.$this->prefix.$route->getPath()); - } - - if (!$route->getHost()) { - $route->setHost($this->host); - } - - if (!$route->getCondition()) { - $route->setCondition($this->condition); - } - - if (!$route->getSchemes()) { - $route->setSchemes($this->schemes); - } - - if (!$route->getMethods()) { - $route->setMethods($this->methods); - } - - // auto-generate the route name if it's been marked - if ('_unnamed_route_' === substr($name, 0, 15)) { - $name = $this->generateRouteName($route); - } - - $routeCollection->add($name, $route); - } else { - /* @var self $route */ - $subCollection = $route->build(); - if (null !== $this->prefix) { - $subCollection->addPrefix($this->prefix); - } - - $routeCollection->addCollection($subCollection); - } - } - - foreach ($this->resources as $resource) { - $routeCollection->addResource($resource); - } - - return $routeCollection; - } - - /** - * Generates a route name based on details of this route. - */ - private function generateRouteName(Route $route): string - { - $methods = implode('_', $route->getMethods()).'_'; - - $routeName = $methods.$route->getPath(); - $routeName = str_replace(['/', ':', '|', '-'], '_', $routeName); - $routeName = preg_replace('/[^a-z0-9A-Z_.]+/', '', $routeName); - - // Collapse consecutive underscores down into a single underscore. - $routeName = preg_replace('/_+/', '_', $routeName); - - return $routeName; - } - - /** - * Finds a loader able to load an imported resource and loads it. - * - * @param mixed $resource A resource - * @param string|null $type The resource type or null if unknown - * - * @return RouteCollection[] - * - * @throws LoaderLoadException If no loader is found - */ - private function load($resource, ?string $type = null): array - { - if (null === $this->loader) { - throw new \BadMethodCallException('Cannot import other routing resources: you must pass a LoaderInterface when constructing RouteCollectionBuilder.'); - } - - if ($this->loader->supports($resource, $type)) { - $collections = $this->loader->load($resource, $type); - - return \is_array($collections) ? $collections : [$collections]; - } - - if (null === $resolver = $this->loader->getResolver()) { - throw new LoaderLoadException($resource, null, 0, null, $type); - } - - if (false === $loader = $resolver->resolve($resource, $type)) { - throw new LoaderLoadException($resource, null, 0, null, $type); - } - - $collections = $loader->load($resource, $type); - - return \is_array($collections) ? $collections : [$collections]; - } -} diff --git a/digital_doctor/vendor/symfony/routing/RouteCompiler.php b/digital_doctor/vendor/symfony/routing/RouteCompiler.php deleted file mode 100644 index 7e78c29..0000000 --- a/digital_doctor/vendor/symfony/routing/RouteCompiler.php +++ /dev/null @@ -1,346 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing; - -/** - * RouteCompiler compiles Route instances to CompiledRoute instances. - * - * @author Fabien Potencier - * @author Tobias Schultze - */ -class RouteCompiler implements RouteCompilerInterface -{ - /** - * @deprecated since Symfony 5.1, to be removed in 6.0 - */ - public const REGEX_DELIMITER = '#'; - - /** - * This string defines the characters that are automatically considered separators in front of - * optional placeholders (with default and no static text following). Such a single separator - * can be left out together with the optional placeholder from matching and generating URLs. - */ - public const SEPARATORS = '/,;.:-_~+*=@|'; - - /** - * The maximum supported length of a PCRE subpattern name - * http://pcre.org/current/doc/html/pcre2pattern.html#SEC16. - * - * @internal - */ - public const VARIABLE_MAXIMUM_LENGTH = 32; - - /** - * {@inheritdoc} - * - * @throws \InvalidArgumentException if a path variable is named _fragment - * @throws \LogicException if a variable is referenced more than once - * @throws \DomainException if a variable name starts with a digit or if it is too long to be successfully used as - * a PCRE subpattern - */ - public static function compile(Route $route) - { - $hostVariables = []; - $variables = []; - $hostRegex = null; - $hostTokens = []; - - if ('' !== $host = $route->getHost()) { - $result = self::compilePattern($route, $host, true); - - $hostVariables = $result['variables']; - $variables = $hostVariables; - - $hostTokens = $result['tokens']; - $hostRegex = $result['regex']; - } - - $locale = $route->getDefault('_locale'); - if (null !== $locale && null !== $route->getDefault('_canonical_route') && preg_quote($locale) === $route->getRequirement('_locale')) { - $requirements = $route->getRequirements(); - unset($requirements['_locale']); - $route->setRequirements($requirements); - $route->setPath(str_replace('{_locale}', $locale, $route->getPath())); - } - - $path = $route->getPath(); - - $result = self::compilePattern($route, $path, false); - - $staticPrefix = $result['staticPrefix']; - - $pathVariables = $result['variables']; - - foreach ($pathVariables as $pathParam) { - if ('_fragment' === $pathParam) { - throw new \InvalidArgumentException(sprintf('Route pattern "%s" cannot contain "_fragment" as a path parameter.', $route->getPath())); - } - } - - $variables = array_merge($variables, $pathVariables); - - $tokens = $result['tokens']; - $regex = $result['regex']; - - return new CompiledRoute( - $staticPrefix, - $regex, - $tokens, - $pathVariables, - $hostRegex, - $hostTokens, - $hostVariables, - array_unique($variables) - ); - } - - private static function compilePattern(Route $route, string $pattern, bool $isHost): array - { - $tokens = []; - $variables = []; - $matches = []; - $pos = 0; - $defaultSeparator = $isHost ? '.' : '/'; - $useUtf8 = preg_match('//u', $pattern); - $needsUtf8 = $route->getOption('utf8'); - - if (!$needsUtf8 && $useUtf8 && preg_match('/[\x80-\xFF]/', $pattern)) { - throw new \LogicException(sprintf('Cannot use UTF-8 route patterns without setting the "utf8" option for route "%s".', $route->getPath())); - } - if (!$useUtf8 && $needsUtf8) { - throw new \LogicException(sprintf('Cannot mix UTF-8 requirements with non-UTF-8 pattern "%s".', $pattern)); - } - - // Match all variables enclosed in "{}" and iterate over them. But we only want to match the innermost variable - // in case of nested "{}", e.g. {foo{bar}}. This in ensured because \w does not match "{" or "}" itself. - preg_match_all('#\{(!)?(\w+)\}#', $pattern, $matches, \PREG_OFFSET_CAPTURE | \PREG_SET_ORDER); - foreach ($matches as $match) { - $important = $match[1][1] >= 0; - $varName = $match[2][0]; - // get all static text preceding the current variable - $precedingText = substr($pattern, $pos, $match[0][1] - $pos); - $pos = $match[0][1] + \strlen($match[0][0]); - - if (!\strlen($precedingText)) { - $precedingChar = ''; - } elseif ($useUtf8) { - preg_match('/.$/u', $precedingText, $precedingChar); - $precedingChar = $precedingChar[0]; - } else { - $precedingChar = substr($precedingText, -1); - } - $isSeparator = '' !== $precedingChar && str_contains(static::SEPARATORS, $precedingChar); - - // A PCRE subpattern name must start with a non-digit. Also a PHP variable cannot start with a digit so the - // variable would not be usable as a Controller action argument. - if (preg_match('/^\d/', $varName)) { - throw new \DomainException(sprintf('Variable name "%s" cannot start with a digit in route pattern "%s". Please use a different name.', $varName, $pattern)); - } - if (\in_array($varName, $variables)) { - throw new \LogicException(sprintf('Route pattern "%s" cannot reference variable name "%s" more than once.', $pattern, $varName)); - } - - if (\strlen($varName) > self::VARIABLE_MAXIMUM_LENGTH) { - throw new \DomainException(sprintf('Variable name "%s" cannot be longer than %d characters in route pattern "%s". Please use a shorter name.', $varName, self::VARIABLE_MAXIMUM_LENGTH, $pattern)); - } - - if ($isSeparator && $precedingText !== $precedingChar) { - $tokens[] = ['text', substr($precedingText, 0, -\strlen($precedingChar))]; - } elseif (!$isSeparator && '' !== $precedingText) { - $tokens[] = ['text', $precedingText]; - } - - $regexp = $route->getRequirement($varName); - if (null === $regexp) { - $followingPattern = (string) substr($pattern, $pos); - // Find the next static character after the variable that functions as a separator. By default, this separator and '/' - // are disallowed for the variable. This default requirement makes sure that optional variables can be matched at all - // and that the generating-matching-combination of URLs unambiguous, i.e. the params used for generating the URL are - // the same that will be matched. Example: new Route('/{page}.{_format}', ['_format' => 'html']) - // If {page} would also match the separating dot, {_format} would never match as {page} will eagerly consume everything. - // Also even if {_format} was not optional the requirement prevents that {page} matches something that was originally - // part of {_format} when generating the URL, e.g. _format = 'mobile.html'. - $nextSeparator = self::findNextSeparator($followingPattern, $useUtf8); - $regexp = sprintf( - '[^%s%s]+', - preg_quote($defaultSeparator), - $defaultSeparator !== $nextSeparator && '' !== $nextSeparator ? preg_quote($nextSeparator) : '' - ); - if (('' !== $nextSeparator && !preg_match('#^\{\w+\}#', $followingPattern)) || '' === $followingPattern) { - // When we have a separator, which is disallowed for the variable, we can optimize the regex with a possessive - // quantifier. This prevents useless backtracking of PCRE and improves performance by 20% for matching those patterns. - // Given the above example, there is no point in backtracking into {page} (that forbids the dot) when a dot must follow - // after it. This optimization cannot be applied when the next char is no real separator or when the next variable is - // directly adjacent, e.g. '/{x}{y}'. - $regexp .= '+'; - } - } else { - if (!preg_match('//u', $regexp)) { - $useUtf8 = false; - } elseif (!$needsUtf8 && preg_match('/[\x80-\xFF]|(?= 0; --$i) { - $token = $tokens[$i]; - // variable is optional when it is not important and has a default value - if ('variable' === $token[0] && !($token[5] ?? false) && $route->hasDefault($token[3])) { - $firstOptional = $i; - } else { - break; - } - } - } - - // compute the matching regexp - $regexp = ''; - for ($i = 0, $nbToken = \count($tokens); $i < $nbToken; ++$i) { - $regexp .= self::computeRegexp($tokens, $i, $firstOptional); - } - $regexp = '{^'.$regexp.'$}sD'.($isHost ? 'i' : ''); - - // enable Utf8 matching if really required - if ($needsUtf8) { - $regexp .= 'u'; - for ($i = 0, $nbToken = \count($tokens); $i < $nbToken; ++$i) { - if ('variable' === $tokens[$i][0]) { - $tokens[$i][4] = true; - } - } - } - - return [ - 'staticPrefix' => self::determineStaticPrefix($route, $tokens), - 'regex' => $regexp, - 'tokens' => array_reverse($tokens), - 'variables' => $variables, - ]; - } - - /** - * Determines the longest static prefix possible for a route. - */ - private static function determineStaticPrefix(Route $route, array $tokens): string - { - if ('text' !== $tokens[0][0]) { - return ($route->hasDefault($tokens[0][3]) || '/' === $tokens[0][1]) ? '' : $tokens[0][1]; - } - - $prefix = $tokens[0][1]; - - if (isset($tokens[1][1]) && '/' !== $tokens[1][1] && false === $route->hasDefault($tokens[1][3])) { - $prefix .= $tokens[1][1]; - } - - return $prefix; - } - - /** - * Returns the next static character in the Route pattern that will serve as a separator (or the empty string when none available). - */ - private static function findNextSeparator(string $pattern, bool $useUtf8): string - { - if ('' == $pattern) { - // return empty string if pattern is empty or false (false which can be returned by substr) - return ''; - } - // first remove all placeholders from the pattern so we can find the next real static character - if ('' === $pattern = preg_replace('#\{\w+\}#', '', $pattern)) { - return ''; - } - if ($useUtf8) { - preg_match('/^./u', $pattern, $pattern); - } - - return str_contains(static::SEPARATORS, $pattern[0]) ? $pattern[0] : ''; - } - - /** - * Computes the regexp used to match a specific token. It can be static text or a subpattern. - * - * @param array $tokens The route tokens - * @param int $index The index of the current token - * @param int $firstOptional The index of the first optional token - */ - private static function computeRegexp(array $tokens, int $index, int $firstOptional): string - { - $token = $tokens[$index]; - if ('text' === $token[0]) { - // Text tokens - return preg_quote($token[1]); - } else { - // Variable tokens - if (0 === $index && 0 === $firstOptional) { - // When the only token is an optional variable token, the separator is required - return sprintf('%s(?P<%s>%s)?', preg_quote($token[1]), $token[3], $token[2]); - } else { - $regexp = sprintf('%s(?P<%s>%s)', preg_quote($token[1]), $token[3], $token[2]); - if ($index >= $firstOptional) { - // Enclose each optional token in a subpattern to make it optional. - // "?:" means it is non-capturing, i.e. the portion of the subject string that - // matched the optional subpattern is not passed back. - $regexp = "(?:$regexp"; - $nbTokens = \count($tokens); - if ($nbTokens - 1 == $index) { - // Close the optional subpatterns - $regexp .= str_repeat(')?', $nbTokens - $firstOptional - (0 === $firstOptional ? 1 : 0)); - } - } - - return $regexp; - } - } - } - - private static function transformCapturingGroupsToNonCapturings(string $regexp): string - { - for ($i = 0; $i < \strlen($regexp); ++$i) { - if ('\\' === $regexp[$i]) { - ++$i; - continue; - } - if ('(' !== $regexp[$i] || !isset($regexp[$i + 2])) { - continue; - } - if ('*' === $regexp[++$i] || '?' === $regexp[$i]) { - ++$i; - continue; - } - $regexp = substr_replace($regexp, '?:', $i, 0); - ++$i; - } - - return $regexp; - } -} diff --git a/digital_doctor/vendor/symfony/routing/RouteCompilerInterface.php b/digital_doctor/vendor/symfony/routing/RouteCompilerInterface.php deleted file mode 100644 index 9bae33a..0000000 --- a/digital_doctor/vendor/symfony/routing/RouteCompilerInterface.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing; - -/** - * RouteCompilerInterface is the interface that all RouteCompiler classes must implement. - * - * @author Fabien Potencier - */ -interface RouteCompilerInterface -{ - /** - * Compiles the current route instance. - * - * @return CompiledRoute - * - * @throws \LogicException If the Route cannot be compiled because the - * path or host pattern is invalid - */ - public static function compile(Route $route); -} diff --git a/digital_doctor/vendor/symfony/routing/Router.php b/digital_doctor/vendor/symfony/routing/Router.php deleted file mode 100644 index 48ec101..0000000 --- a/digital_doctor/vendor/symfony/routing/Router.php +++ /dev/null @@ -1,391 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing; - -use Psr\Log\LoggerInterface; -use Symfony\Component\Config\ConfigCacheFactory; -use Symfony\Component\Config\ConfigCacheFactoryInterface; -use Symfony\Component\Config\ConfigCacheInterface; -use Symfony\Component\Config\Loader\LoaderInterface; -use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Routing\Generator\CompiledUrlGenerator; -use Symfony\Component\Routing\Generator\ConfigurableRequirementsInterface; -use Symfony\Component\Routing\Generator\Dumper\CompiledUrlGeneratorDumper; -use Symfony\Component\Routing\Generator\Dumper\GeneratorDumperInterface; -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; -use Symfony\Component\Routing\Matcher\CompiledUrlMatcher; -use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper; -use Symfony\Component\Routing\Matcher\Dumper\MatcherDumperInterface; -use Symfony\Component\Routing\Matcher\RequestMatcherInterface; -use Symfony\Component\Routing\Matcher\UrlMatcherInterface; - -/** - * The Router class is an example of the integration of all pieces of the - * routing system for easier use. - * - * @author Fabien Potencier - */ -class Router implements RouterInterface, RequestMatcherInterface -{ - /** - * @var UrlMatcherInterface|null - */ - protected $matcher; - - /** - * @var UrlGeneratorInterface|null - */ - protected $generator; - - /** - * @var RequestContext - */ - protected $context; - - /** - * @var LoaderInterface - */ - protected $loader; - - /** - * @var RouteCollection|null - */ - protected $collection; - - /** - * @var mixed - */ - protected $resource; - - /** - * @var array - */ - protected $options = []; - - /** - * @var LoggerInterface|null - */ - protected $logger; - - /** - * @var string|null - */ - protected $defaultLocale; - - /** - * @var ConfigCacheFactoryInterface|null - */ - private $configCacheFactory; - - /** - * @var ExpressionFunctionProviderInterface[] - */ - private $expressionLanguageProviders = []; - - private static $cache = []; - - /** - * @param mixed $resource The main resource to load - */ - public function __construct(LoaderInterface $loader, $resource, array $options = [], ?RequestContext $context = null, ?LoggerInterface $logger = null, ?string $defaultLocale = null) - { - $this->loader = $loader; - $this->resource = $resource; - $this->logger = $logger; - $this->context = $context ?? new RequestContext(); - $this->setOptions($options); - $this->defaultLocale = $defaultLocale; - } - - /** - * Sets options. - * - * Available options: - * - * * cache_dir: The cache directory (or null to disable caching) - * * debug: Whether to enable debugging or not (false by default) - * * generator_class: The name of a UrlGeneratorInterface implementation - * * generator_dumper_class: The name of a GeneratorDumperInterface implementation - * * matcher_class: The name of a UrlMatcherInterface implementation - * * matcher_dumper_class: The name of a MatcherDumperInterface implementation - * * resource_type: Type hint for the main resource (optional) - * * strict_requirements: Configure strict requirement checking for generators - * implementing ConfigurableRequirementsInterface (default is true) - * - * @throws \InvalidArgumentException When unsupported option is provided - */ - public function setOptions(array $options) - { - $this->options = [ - 'cache_dir' => null, - 'debug' => false, - 'generator_class' => CompiledUrlGenerator::class, - 'generator_dumper_class' => CompiledUrlGeneratorDumper::class, - 'matcher_class' => CompiledUrlMatcher::class, - 'matcher_dumper_class' => CompiledUrlMatcherDumper::class, - 'resource_type' => null, - 'strict_requirements' => true, - ]; - - // check option names and live merge, if errors are encountered Exception will be thrown - $invalid = []; - foreach ($options as $key => $value) { - if (\array_key_exists($key, $this->options)) { - $this->options[$key] = $value; - } else { - $invalid[] = $key; - } - } - - if ($invalid) { - throw new \InvalidArgumentException(sprintf('The Router does not support the following options: "%s".', implode('", "', $invalid))); - } - } - - /** - * Sets an option. - * - * @param mixed $value The value - * - * @throws \InvalidArgumentException - */ - public function setOption(string $key, $value) - { - if (!\array_key_exists($key, $this->options)) { - throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key)); - } - - $this->options[$key] = $value; - } - - /** - * Gets an option value. - * - * @return mixed - * - * @throws \InvalidArgumentException - */ - public function getOption(string $key) - { - if (!\array_key_exists($key, $this->options)) { - throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key)); - } - - return $this->options[$key]; - } - - /** - * {@inheritdoc} - */ - public function getRouteCollection() - { - if (null === $this->collection) { - $this->collection = $this->loader->load($this->resource, $this->options['resource_type']); - } - - return $this->collection; - } - - /** - * {@inheritdoc} - */ - public function setContext(RequestContext $context) - { - $this->context = $context; - - if (null !== $this->matcher) { - $this->getMatcher()->setContext($context); - } - if (null !== $this->generator) { - $this->getGenerator()->setContext($context); - } - } - - /** - * {@inheritdoc} - */ - public function getContext() - { - return $this->context; - } - - /** - * Sets the ConfigCache factory to use. - */ - public function setConfigCacheFactory(ConfigCacheFactoryInterface $configCacheFactory) - { - $this->configCacheFactory = $configCacheFactory; - } - - /** - * {@inheritdoc} - */ - public function generate(string $name, array $parameters = [], int $referenceType = self::ABSOLUTE_PATH) - { - return $this->getGenerator()->generate($name, $parameters, $referenceType); - } - - /** - * {@inheritdoc} - */ - public function match(string $pathinfo) - { - return $this->getMatcher()->match($pathinfo); - } - - /** - * {@inheritdoc} - */ - public function matchRequest(Request $request) - { - $matcher = $this->getMatcher(); - if (!$matcher instanceof RequestMatcherInterface) { - // fallback to the default UrlMatcherInterface - return $matcher->match($request->getPathInfo()); - } - - return $matcher->matchRequest($request); - } - - /** - * Gets the UrlMatcher or RequestMatcher instance associated with this Router. - * - * @return UrlMatcherInterface|RequestMatcherInterface - */ - public function getMatcher() - { - if (null !== $this->matcher) { - return $this->matcher; - } - - if (null === $this->options['cache_dir']) { - $routes = $this->getRouteCollection(); - $compiled = is_a($this->options['matcher_class'], CompiledUrlMatcher::class, true); - if ($compiled) { - $routes = (new CompiledUrlMatcherDumper($routes))->getCompiledRoutes(); - } - $this->matcher = new $this->options['matcher_class']($routes, $this->context); - if (method_exists($this->matcher, 'addExpressionLanguageProvider')) { - foreach ($this->expressionLanguageProviders as $provider) { - $this->matcher->addExpressionLanguageProvider($provider); - } - } - - return $this->matcher; - } - - $cache = $this->getConfigCacheFactory()->cache($this->options['cache_dir'].'/url_matching_routes.php', - function (ConfigCacheInterface $cache) { - $dumper = $this->getMatcherDumperInstance(); - if (method_exists($dumper, 'addExpressionLanguageProvider')) { - foreach ($this->expressionLanguageProviders as $provider) { - $dumper->addExpressionLanguageProvider($provider); - } - } - - $cache->write($dumper->dump(), $this->getRouteCollection()->getResources()); - } - ); - - return $this->matcher = new $this->options['matcher_class'](self::getCompiledRoutes($cache->getPath()), $this->context); - } - - /** - * Gets the UrlGenerator instance associated with this Router. - * - * @return UrlGeneratorInterface - */ - public function getGenerator() - { - if (null !== $this->generator) { - return $this->generator; - } - - if (null === $this->options['cache_dir']) { - $routes = $this->getRouteCollection(); - $compiled = is_a($this->options['generator_class'], CompiledUrlGenerator::class, true); - if ($compiled) { - $generatorDumper = new CompiledUrlGeneratorDumper($routes); - $routes = array_merge($generatorDumper->getCompiledRoutes(), $generatorDumper->getCompiledAliases()); - } - $this->generator = new $this->options['generator_class']($routes, $this->context, $this->logger, $this->defaultLocale); - } else { - $cache = $this->getConfigCacheFactory()->cache($this->options['cache_dir'].'/url_generating_routes.php', - function (ConfigCacheInterface $cache) { - $dumper = $this->getGeneratorDumperInstance(); - - $cache->write($dumper->dump(), $this->getRouteCollection()->getResources()); - } - ); - - $this->generator = new $this->options['generator_class'](self::getCompiledRoutes($cache->getPath()), $this->context, $this->logger, $this->defaultLocale); - } - - if ($this->generator instanceof ConfigurableRequirementsInterface) { - $this->generator->setStrictRequirements($this->options['strict_requirements']); - } - - return $this->generator; - } - - public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider) - { - $this->expressionLanguageProviders[] = $provider; - } - - /** - * @return GeneratorDumperInterface - */ - protected function getGeneratorDumperInstance() - { - return new $this->options['generator_dumper_class']($this->getRouteCollection()); - } - - /** - * @return MatcherDumperInterface - */ - protected function getMatcherDumperInstance() - { - return new $this->options['matcher_dumper_class']($this->getRouteCollection()); - } - - /** - * Provides the ConfigCache factory implementation, falling back to a - * default implementation if necessary. - */ - private function getConfigCacheFactory(): ConfigCacheFactoryInterface - { - if (null === $this->configCacheFactory) { - $this->configCacheFactory = new ConfigCacheFactory($this->options['debug']); - } - - return $this->configCacheFactory; - } - - private static function getCompiledRoutes(string $path): array - { - if ([] === self::$cache && \function_exists('opcache_invalidate') && filter_var(\ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN) && (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) || filter_var(\ini_get('opcache.enable_cli'), \FILTER_VALIDATE_BOOLEAN))) { - self::$cache = null; - } - - if (null === self::$cache) { - return require $path; - } - - if (isset(self::$cache[$path])) { - return self::$cache[$path]; - } - - return self::$cache[$path] = require $path; - } -} diff --git a/digital_doctor/vendor/symfony/routing/RouterInterface.php b/digital_doctor/vendor/symfony/routing/RouterInterface.php deleted file mode 100644 index 6912f8a..0000000 --- a/digital_doctor/vendor/symfony/routing/RouterInterface.php +++ /dev/null @@ -1,35 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing; - -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; -use Symfony\Component\Routing\Matcher\UrlMatcherInterface; - -/** - * RouterInterface is the interface that all Router classes must implement. - * - * This interface is the concatenation of UrlMatcherInterface and UrlGeneratorInterface. - * - * @author Fabien Potencier - */ -interface RouterInterface extends UrlMatcherInterface, UrlGeneratorInterface -{ - /** - * Gets the RouteCollection instance associated with this Router. - * - * WARNING: This method should never be used at runtime as it is SLOW. - * You might use it in a cache warmer though. - * - * @return RouteCollection - */ - public function getRouteCollection(); -} diff --git a/digital_doctor/vendor/symfony/routing/composer.json b/digital_doctor/vendor/symfony/routing/composer.json deleted file mode 100644 index c32219e..0000000 --- a/digital_doctor/vendor/symfony/routing/composer.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "name": "symfony/routing", - "type": "library", - "description": "Maps an HTTP request to a set of configuration variables", - "keywords": ["routing", "router", "url", "uri"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16" - }, - "require-dev": { - "symfony/config": "^5.3|^6.0", - "symfony/http-foundation": "^4.4|^5.0|^6.0", - "symfony/yaml": "^4.4|^5.0|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "doctrine/annotations": "^1.12|^2", - "psr/log": "^1|^2|^3" - }, - "conflict": { - "doctrine/annotations": "<1.12", - "symfony/config": "<5.3", - "symfony/dependency-injection": "<4.4", - "symfony/yaml": "<4.4" - }, - "suggest": { - "symfony/http-foundation": "For using a Symfony Request object", - "symfony/config": "For using the all-in-one router or any loader", - "symfony/yaml": "For using the YAML loader", - "symfony/expression-language": "For using expression matching" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\Routing\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev" -} diff --git a/digital_doctor_admin/addons/command/.addonrc b/digital_doctor_admin/addons/command/.addonrc index fa7a8e3..3ed878f 100644 --- a/digital_doctor_admin/addons/command/.addonrc +++ b/digital_doctor_admin/addons/command/.addonrc @@ -1 +1 @@ -{"files":["application\\admin\\controller\\Command.php","application\\admin\\lang\\zh-cn\\command.php","application\\admin\\model\\Command.php","application\\admin\\validate\\Command.php","application\\admin\\view\\command\\add.html","application\\admin\\view\\command\\detail.html","application\\admin\\view\\command\\index.html","public\\assets\\js\\backend\\command.js"],"license":"regular","licenseto":"35362","licensekey":"RelQz6AtXCS4JikE ERBkje4Xykr+XiBbSpumLQ==","domains":["digitaldoctoradmin.com"],"licensecodes":[],"validations":["0cfc8a7936e1ddab07015d7067c29a6e"],"menus":["command","command\/index","command\/add","command\/detail","command\/command","command\/execute","command\/del","command\/multi"]} \ No newline at end of file +{"files":["application\\admin\\controller\\Command.php","application\\admin\\lang\\zh-cn\\command.php","application\\admin\\model\\Command.php","application\\admin\\validate\\Command.php","application\\admin\\view\\command\\add.html","application\\admin\\view\\command\\detail.html","application\\admin\\view\\command\\index.html","public\\assets\\js\\backend\\command.js"],"license":"regular","licenseto":"35362","licensekey":"1NPuoXGn2dF9zSWp BnJFi8rJ+fduZcsd5LQpmg==","domains":["digitaldoctoradmin.com"],"licensecodes":[],"validations":["0cfc8a7936e1ddab07015d7067c29a6e"],"menus":["command","command\/index","command\/add","command\/detail","command\/command","command\/execute","command\/del","command\/multi"]} \ No newline at end of file diff --git a/digital_doctor_admin/application/admin/controller/Dashboard.php b/digital_doctor_admin/application/admin/controller/Dashboard.php index 2dd2e06..9437b47 100644 --- a/digital_doctor_admin/application/admin/controller/Dashboard.php +++ b/digital_doctor_admin/application/admin/controller/Dashboard.php @@ -54,10 +54,10 @@ class Dashboard extends Backend } } $this->view->assign([ - 'totaluser' => User::count(), - 'totaladdon' => $totaladdon, - 'totaladmin' => Admin::count(), - 'totalcategory' => \app\common\model\Category::count(), + 'totaluser' => Db::table('fa_tt_userbaseinfo')->where('create_time','>=',date("Y-m-d",time()))->count('id'),//今日问诊 + 'totaladdon' => Db::table('fa_tt_userbaseinfo')->where('create_time','>=',date("Y-m-d",time()-30*86400))->count('id'),//30日问诊 + 'totaladmin' => Db::table('fa_tt_userbaseinfo')->where('create_time','>=',date("Y-m-d",time()-30*3*86400))->count('id'),//3个月问诊 + 'totalcategory' => Db::table('fa_tt_userbaseinfo')->count('id'),//总问诊 'todayusersignup' => User::whereTime('jointime', 'today')->count(), 'todayuserlogin' => User::whereTime('logintime', 'today')->count(), 'sevendau' => User::whereTime('jointime|logintime|prevtime', '-7 days')->count(), diff --git a/digital_doctor_admin/application/admin/controller/Ttmedicalreport.php b/digital_doctor_admin/application/admin/controller/Ttmedicalreport.php new file mode 100644 index 0000000..5015bc3 --- /dev/null +++ b/digital_doctor_admin/application/admin/controller/Ttmedicalreport.php @@ -0,0 +1,37 @@ +model = new \app\admin\model\Ttmedicalreport; + + } + + + + /** + * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法 + * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑 + * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改 + */ + + +} diff --git a/digital_doctor_admin/application/admin/controller/Tymedicalreport.php b/digital_doctor_admin/application/admin/controller/Tymedicalreport.php new file mode 100644 index 0000000..b2a6e40 --- /dev/null +++ b/digital_doctor_admin/application/admin/controller/Tymedicalreport.php @@ -0,0 +1,37 @@ +model = new \app\admin\model\Tymedicalreport; + + } + + + + /** + * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法 + * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑 + * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改 + */ + + +} diff --git a/digital_doctor_admin/application/admin/controller/ty/Userbaseinfo.php b/digital_doctor_admin/application/admin/controller/ty/Userbaseinfo.php new file mode 100644 index 0000000..7093bed --- /dev/null +++ b/digital_doctor_admin/application/admin/controller/ty/Userbaseinfo.php @@ -0,0 +1,37 @@ +model = new \app\admin\model\ty\Userbaseinfo; + + } + + + + /** + * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法 + * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑 + * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改 + */ + + +} diff --git a/digital_doctor_admin/application/admin/lang/zh-cn/ttmedicalreport.php b/digital_doctor_admin/application/admin/lang/zh-cn/ttmedicalreport.php new file mode 100644 index 0000000..de089ec --- /dev/null +++ b/digital_doctor_admin/application/admin/lang/zh-cn/ttmedicalreport.php @@ -0,0 +1,9 @@ + 'ID', + 'Doctor' => '所属医生', + 'Username' => '病人', + 'Report_content' => '报告内容', + 'Create_time' => '生成时间' +]; diff --git a/digital_doctor_admin/application/admin/lang/zh-cn/ty/userbaseinfo.php b/digital_doctor_admin/application/admin/lang/zh-cn/ty/userbaseinfo.php new file mode 100644 index 0000000..81c1bab --- /dev/null +++ b/digital_doctor_admin/application/admin/lang/zh-cn/ty/userbaseinfo.php @@ -0,0 +1,18 @@ + 'ID', + 'Username' => '所属医生', + 'Name' => '病人姓名', + 'Gender' => '病人性别', + 'Age' => '病人年龄', + 'Main_complaint' => '主诉', + 'Medical_history' => '病史', + 'Past_history' => '既往史', + 'Allergy_history' => '过敏史', + 'Family_history' => '家族史', + 'Personal_history' => '个人史', + 'Menstrual_marital_history' => '月经婚育史', + 'Diagnosis' => '诊断', + 'Treatment' => '医嘱' +]; diff --git a/digital_doctor_admin/application/admin/lang/zh-cn/tymedicalreport.php b/digital_doctor_admin/application/admin/lang/zh-cn/tymedicalreport.php new file mode 100644 index 0000000..de089ec --- /dev/null +++ b/digital_doctor_admin/application/admin/lang/zh-cn/tymedicalreport.php @@ -0,0 +1,9 @@ + 'ID', + 'Doctor' => '所属医生', + 'Username' => '病人', + 'Report_content' => '报告内容', + 'Create_time' => '生成时间' +]; diff --git a/digital_doctor_admin/application/admin/model/Ttmedicalreport.php b/digital_doctor_admin/application/admin/model/Ttmedicalreport.php new file mode 100644 index 0000000..8f3ddf0 --- /dev/null +++ b/digital_doctor_admin/application/admin/model/Ttmedicalreport.php @@ -0,0 +1,40 @@ + [], + 'edit' => [], + ]; + +} diff --git a/digital_doctor_admin/application/admin/validate/Tymedicalreport.php b/digital_doctor_admin/application/admin/validate/Tymedicalreport.php new file mode 100644 index 0000000..5d1a4d7 --- /dev/null +++ b/digital_doctor_admin/application/admin/validate/Tymedicalreport.php @@ -0,0 +1,27 @@ + [], + 'edit' => [], + ]; + +} diff --git a/digital_doctor_admin/application/admin/validate/ty/Userbaseinfo.php b/digital_doctor_admin/application/admin/validate/ty/Userbaseinfo.php new file mode 100644 index 0000000..999daa6 --- /dev/null +++ b/digital_doctor_admin/application/admin/validate/ty/Userbaseinfo.php @@ -0,0 +1,27 @@ + [], + 'edit' => [], + ]; + +} diff --git a/digital_doctor_admin/application/admin/view/dashboard/index.html b/digital_doctor_admin/application/admin/view/dashboard/index.html index 0c04396..843700a 100644 --- a/digital_doctor_admin/application/admin/view/dashboard/index.html +++ b/digital_doctor_admin/application/admin/view/dashboard/index.html @@ -174,10 +174,10 @@
- +
{$totaluser} - {:__('Total user')} + 今日问诊
@@ -186,7 +186,7 @@
{$totaladdon} - {:__('Total addon')} + 30日问诊
@@ -195,201 +195,204 @@
{$attachmentnums} - {:__('Total attachment')} + 90日问诊
- +
{$totaladmin} - {:__('Total admin')} + 总问诊
-
-
-
-
-
-
-
-
-
-
-
-
{$todayusersignup}
-
{:__('Today user signup')}
-
-
-
-
-
-
-
-
-
{$todayuserlogin}
-
{:__('Today user login')}
-
-
-
-
-
-
-
-
-
{$threednu}
-
{:__('Three dnu')}
-
-
-
-
-
-
-
-
-
{$sevendnu}
-
{:__('Seven dnu')}
-
-
-
-
-
-
-
-
-
{$sevendau}
-
{:__('Seven dau')}
-
-
-
-
-
-
-
-
-
{$thirtydau}
-
{:__('Thirty dau')}
-
-
-
-
-
-
-
-
-
-
+ + + + -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -
-
-
-
-
-
- {:__('Real time')} -
{:__('Working addon count')}
-
-
-
-
-

{$totalworkingaddon}

-
- {:__('Working addon count tips')} -
-
-
-
-
-
-
-
-
-
-
- {:__('Real time')} -
{:__('Database count')}
-
-
-
-
-

{$dbtablenums}

-
- {:__('Database table nums')} -
-
-
-

{$dbsize|format_bytes=###,'',0}

-
- {:__('Database size')} -
-
-
-
-
-
-
+ -
-
-
-
- {:__('Real time')} -
{:__('Attachment count')}
-
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -
-
-

{$attachmentnums}

-
- {:__('Attachment nums')} -
-
-
-

{$attachmentsize|format_bytes=###,'',0}

-
- {:__('Attachment size')} -
-
-
-
-
-
-
-
-
-
-
- {:__('Real time')} -
{:__('Picture count')}
-
-
+ + + + + + + + -
-
-

{$picturenums}

-
- {:__('Picture nums')} -
-
-
-

{$picturesize|format_bytes=###,'',0}

-
- {:__('Picture size')} -
-
-
-
-
-
-
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -401,3 +404,18 @@
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/digital_doctor_admin/application/admin/view/ttmedicalreport/add.html b/digital_doctor_admin/application/admin/view/ttmedicalreport/add.html new file mode 100644 index 0000000..71092d6 --- /dev/null +++ b/digital_doctor_admin/application/admin/view/ttmedicalreport/add.html @@ -0,0 +1,33 @@ +
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+ +
diff --git a/digital_doctor_admin/application/admin/view/ttmedicalreport/edit.html b/digital_doctor_admin/application/admin/view/ttmedicalreport/edit.html new file mode 100644 index 0000000..8587331 --- /dev/null +++ b/digital_doctor_admin/application/admin/view/ttmedicalreport/edit.html @@ -0,0 +1,33 @@ +
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+ +
diff --git a/digital_doctor_admin/application/admin/view/ttmedicalreport/index.html b/digital_doctor_admin/application/admin/view/ttmedicalreport/index.html new file mode 100644 index 0000000..de8a1c9 --- /dev/null +++ b/digital_doctor_admin/application/admin/view/ttmedicalreport/index.html @@ -0,0 +1,29 @@ +
+ {:build_heading()} + +
+
+
+ +
+ +
+
+
diff --git a/digital_doctor_admin/application/admin/view/ty/userbaseinfo/add.html b/digital_doctor_admin/application/admin/view/ty/userbaseinfo/add.html new file mode 100644 index 0000000..b9f6d9f --- /dev/null +++ b/digital_doctor_admin/application/admin/view/ty/userbaseinfo/add.html @@ -0,0 +1,87 @@ +
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+ +
diff --git a/digital_doctor_admin/application/admin/view/ty/userbaseinfo/edit.html b/digital_doctor_admin/application/admin/view/ty/userbaseinfo/edit.html new file mode 100644 index 0000000..73ce900 --- /dev/null +++ b/digital_doctor_admin/application/admin/view/ty/userbaseinfo/edit.html @@ -0,0 +1,87 @@ +
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+ +
diff --git a/digital_doctor_admin/application/admin/view/ty/userbaseinfo/index.html b/digital_doctor_admin/application/admin/view/ty/userbaseinfo/index.html new file mode 100644 index 0000000..cdb87c6 --- /dev/null +++ b/digital_doctor_admin/application/admin/view/ty/userbaseinfo/index.html @@ -0,0 +1,29 @@ +
+ {:build_heading()} + +
+
+
+ +
+ +
+
+
diff --git a/digital_doctor_admin/application/admin/view/tymedicalreport/add.html b/digital_doctor_admin/application/admin/view/tymedicalreport/add.html new file mode 100644 index 0000000..71092d6 --- /dev/null +++ b/digital_doctor_admin/application/admin/view/tymedicalreport/add.html @@ -0,0 +1,33 @@ +
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+ +
diff --git a/digital_doctor_admin/application/admin/view/tymedicalreport/edit.html b/digital_doctor_admin/application/admin/view/tymedicalreport/edit.html new file mode 100644 index 0000000..8587331 --- /dev/null +++ b/digital_doctor_admin/application/admin/view/tymedicalreport/edit.html @@ -0,0 +1,33 @@ +
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+ +
diff --git a/digital_doctor_admin/application/admin/view/tymedicalreport/index.html b/digital_doctor_admin/application/admin/view/tymedicalreport/index.html new file mode 100644 index 0000000..17a9d6e --- /dev/null +++ b/digital_doctor_admin/application/admin/view/tymedicalreport/index.html @@ -0,0 +1,29 @@ +
+ {:build_heading()} + +
+
+
+ +
+ +
+
+
diff --git a/digital_doctor_admin/public/assets/js/backend/dashboard.js b/digital_doctor_admin/public/assets/js/backend/dashboard.js index ab8409c..043ef07 100644 --- a/digital_doctor_admin/public/assets/js/backend/dashboard.js +++ b/digital_doctor_admin/public/assets/js/backend/dashboard.js @@ -3,76 +3,104 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'table', 'echarts', 'echart var Controller = { index: function () { // 基于准备好的dom,初始化echarts实例 - var myChart = Echarts.init(document.getElementById('echart'), 'walden'); - - // 指定图表的配置项和数据 - var option = { - title: { - text: '', - subtext: '' - }, - color: [ - "#18d1b1", - "#3fb1e3", - "#626c91", - "#a0a7e6", - "#c4ebad", - "#96dee8" - ], - tooltip: { - trigger: 'axis' - }, - legend: { - data: [__('Register user')] - }, - toolbox: { - show: false, - feature: { - magicType: {show: true, type: ['stack', 'tiled']}, - saveAsImage: {show: true} - } - }, - xAxis: { - type: 'category', - boundaryGap: false, - data: Config.column - }, - yAxis: {}, - grid: [{ - left: 'left', - top: 'top', - right: '10', - bottom: 30 - }], - series: [{ - name: __('Register user'), - type: 'line', - smooth: true, - areaStyle: { - normal: {} - }, - lineStyle: { - normal: { - width: 1.5 - } - }, - data: Config.userdata - }] - }; - - // 使用刚指定的配置项和数据显示图表。 - myChart.setOption(option); - - $(window).resize(function () { - myChart.resize(); + // var myChart = Echarts.init(document.getElementById('echart'), 'walden'); + // + // // 指定图表的配置项和数据 + // var option = { + // title: { + // text: '', + // subtext: '' + // }, + // color: [ + // "#18d1b1", + // "#3fb1e3", + // "#626c91", + // "#a0a7e6", + // "#c4ebad", + // "#96dee8" + // ], + // tooltip: { + // trigger: 'axis' + // }, + // legend: { + // data: [__('Register user')] + // }, + // toolbox: { + // show: false, + // feature: { + // magicType: {show: true, type: ['stack', 'tiled']}, + // saveAsImage: {show: true} + // } + // }, + // xAxis: { + // type: 'category', + // boundaryGap: false, + // data: Config.column + // }, + // yAxis: {}, + // grid: [{ + // left: 'left', + // top: 'top', + // right: '10', + // bottom: 30 + // }], + // series: [{ + // name: __('Register user'), + // type: 'line', + // smooth: true, + // areaStyle: { + // normal: {} + // }, + // lineStyle: { + // normal: { + // width: 1.5 + // } + // }, + // data: Config.userdata + // }] + // }; + // + // // 使用刚指定的配置项和数据显示图表。 + // myChart.setOption(option); + // + // $(window).resize(function () { + // myChart.resize(); + // }); + // + // $(document).on("click", ".btn-refresh", function () { + // setTimeout(function () { + // myChart.resize(); + // }, 0); + // }); + // 初始化表格参数配置 + Table.api.init({ + extend: { + index_url: 'tt/userbaseinfo/index' + location.search, + table: 'fa_tt_userbaseinfo', + } }); - $(document).on("click", ".btn-refresh", function () { - setTimeout(function () { - myChart.resize(); - }, 0); + var table = $("#table"); + + // 初始化表格 + table.bootstrapTable({ + url: $.fn.bootstrapTable.defaults.extend.index_url, + pk: 'id', + sortName: 'id', + columns: [ + [ + {checkbox: true}, + {field: 'id', title: __('Id')}, + {field: 'doctor', title: __('Doctor'), operate: 'LIKE'}, + {field: 'username', title: __('Username'), operate: 'LIKE'}, + {field: 'create_time', title: __('Create_time'), operate:'RANGE', addclass:'datetimerange', autocomplete:false, formatter: Table.api.formatter.datetime}, + {field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate} + ] + ] }); + // 为表格绑定事件 + Table.api.bindevent(table); } }; diff --git a/digital_doctor_admin/public/assets/js/backend/tt/userbaseinfo.js b/digital_doctor_admin/public/assets/js/backend/tt/userbaseinfo.js index 1e6b8bc..b13e91f 100644 --- a/digital_doctor_admin/public/assets/js/backend/tt/userbaseinfo.js +++ b/digital_doctor_admin/public/assets/js/backend/tt/userbaseinfo.js @@ -45,7 +45,53 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin {field: 'phone', title: __('Phone'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content}, {field: 'wechat_no', title: __('Wechat_no'), operate: 'LIKE'}, {field: 'create_time', title: __('Create_time'), operate:'RANGE', addclass:'datetimerange', autocomplete:false, formatter: Table.api.formatter.datetime}, - {field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate} + {field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate, + + buttons: [ + { + name: 'getReport', + text: __('查询病历报告'), + title: __('查询病历报告'), + classname: 'btn btn-xs btn-primary btn-dialog', + icon: 'fa fa-list', + url: 'Ttmedicalreport/edit', + callback: function (data) { + Layer.alert("接收到回传数据:" + JSON.stringify(data), {title: "回传数据"}); + }, + visible: function (row) { + //返回true时按钮显示,返回false隐藏 + return true; + } + }, + // { + // name: 'ajax', + // text: __('发送Ajax'), + // title: __('发送Ajax'), + // classname: 'btn btn-xs btn-success btn-magic btn-ajax', + // icon: 'fa fa-magic', + // url: 'example/bootstraptable/detail', + // confirm: '确认发送', + // success: function (data, ret) { + // Layer.alert(ret.msg + ",返回数据:" + JSON.stringify(data)); + // //如果需要阻止成功提示,则必须使用return false; + // //return false; + // }, + // error: function (data, ret) { + // console.log(data, ret); + // Layer.alert(ret.msg); + // return false; + // } + // }, + // { + // name: 'addtabs', + // text: __('新选项卡中打开'), + // title: __('新选项卡中打开'), + // classname: 'btn btn-xs btn-warning btn-addtabs', + // icon: 'fa fa-folder-o', + // url: 'example/bootstraptable/detail' + // } + ], + } ] ] }); diff --git a/digital_doctor_admin/public/assets/js/backend/ttmedicalreport.js b/digital_doctor_admin/public/assets/js/backend/ttmedicalreport.js new file mode 100644 index 0000000..f09ffe4 --- /dev/null +++ b/digital_doctor_admin/public/assets/js/backend/ttmedicalreport.js @@ -0,0 +1,53 @@ +define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) { + + var Controller = { + index: function () { + // 初始化表格参数配置 + Table.api.init({ + extend: { + index_url: 'ttmedicalreport/index' + location.search, + add_url: 'ttmedicalreport/add', + edit_url: 'ttmedicalreport/edit', + del_url: 'ttmedicalreport/del', + multi_url: 'ttmedicalreport/multi', + import_url: 'ttmedicalreport/import', + table: 'tt_medical_report', + } + }); + + var table = $("#table"); + + // 初始化表格 + table.bootstrapTable({ + url: $.fn.bootstrapTable.defaults.extend.index_url, + pk: 'id', + sortName: 'id', + columns: [ + [ + {checkbox: true}, + {field: 'id', title: __('Id')}, + {field: 'doctor', title: __('Doctor'), operate: 'LIKE'}, + {field: 'username', title: __('Username'), operate: 'LIKE'}, + {field: 'create_time', title: __('Create_time'), operate:'RANGE', addclass:'datetimerange', autocomplete:false, formatter: Table.api.formatter.datetime}, + {field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate} + ] + ] + }); + + // 为表格绑定事件 + Table.api.bindevent(table); + }, + add: function () { + Controller.api.bindevent(); + }, + edit: function () { + Controller.api.bindevent(); + }, + api: { + bindevent: function () { + Form.api.bindevent($("form[role=form]")); + } + } + }; + return Controller; +}); diff --git a/digital_doctor_admin/public/assets/js/backend/ty/userbaseinfo.js b/digital_doctor_admin/public/assets/js/backend/ty/userbaseinfo.js new file mode 100644 index 0000000..42bccbd --- /dev/null +++ b/digital_doctor_admin/public/assets/js/backend/ty/userbaseinfo.js @@ -0,0 +1,103 @@ +define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) { + + var Controller = { + index: function () { + // 初始化表格参数配置 + Table.api.init({ + extend: { + index_url: 'ty/userbaseinfo/index' + location.search, + add_url: 'ty/userbaseinfo/add', + edit_url: 'ty/userbaseinfo/edit', + del_url: 'ty/userbaseinfo/del', + multi_url: 'ty/userbaseinfo/multi', + import_url: 'ty/userbaseinfo/import', + table: 'ty_userbaseinfo', + } + }); + + var table = $("#table"); + + // 初始化表格 + table.bootstrapTable({ + url: $.fn.bootstrapTable.defaults.extend.index_url, + pk: 'id', + sortName: 'id', + fixedColumns: true, + fixedRightNumber: 1, + columns: [ + [ + {checkbox: true}, + {field: 'id', title: __('Id')}, + {field: 'username', title: __('Username'), operate: 'LIKE'}, + {field: 'name', title: __('Name'), operate: 'LIKE'}, + {field: 'gender', title: __('Gender'), operate: 'LIKE'}, + {field: 'age', title: __('Age')}, + {field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate, + + + buttons: [ + { + name: 'getReport', + text: __('查询病历报告'), + title: __('查询病历报告'), + classname: 'btn btn-xs btn-primary btn-dialog', + icon: 'fa fa-list', + url: 'Tymedicalreport/edit', + callback: function (data) { + Layer.alert("接收到回传数据:" + JSON.stringify(data), {title: "回传数据"}); + }, + visible: function (row) { + //返回true时按钮显示,返回false隐藏 + return true; + } + }, + // { + // name: 'ajax', + // text: __('发送Ajax'), + // title: __('发送Ajax'), + // classname: 'btn btn-xs btn-success btn-magic btn-ajax', + // icon: 'fa fa-magic', + // url: 'example/bootstraptable/detail', + // confirm: '确认发送', + // success: function (data, ret) { + // Layer.alert(ret.msg + ",返回数据:" + JSON.stringify(data)); + // //如果需要阻止成功提示,则必须使用return false; + // //return false; + // }, + // error: function (data, ret) { + // console.log(data, ret); + // Layer.alert(ret.msg); + // return false; + // } + // }, + // { + // name: 'addtabs', + // text: __('新选项卡中打开'), + // title: __('新选项卡中打开'), + // classname: 'btn btn-xs btn-warning btn-addtabs', + // icon: 'fa fa-folder-o', + // url: 'example/bootstraptable/detail' + // } + ], + } + ] + ] + }); + + // 为表格绑定事件 + Table.api.bindevent(table); + }, + add: function () { + Controller.api.bindevent(); + }, + edit: function () { + Controller.api.bindevent(); + }, + api: { + bindevent: function () { + Form.api.bindevent($("form[role=form]")); + } + } + }; + return Controller; +}); diff --git a/digital_doctor_admin/public/assets/js/backend/tymedicalreport.js b/digital_doctor_admin/public/assets/js/backend/tymedicalreport.js new file mode 100644 index 0000000..3d73fed --- /dev/null +++ b/digital_doctor_admin/public/assets/js/backend/tymedicalreport.js @@ -0,0 +1,53 @@ +define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) { + + var Controller = { + index: function () { + // 初始化表格参数配置 + Table.api.init({ + extend: { + index_url: 'tymedicalreport/index' + location.search, + add_url: 'tymedicalreport/add', + edit_url: 'tymedicalreport/edit', + del_url: 'tymedicalreport/del', + multi_url: 'tymedicalreport/multi', + import_url: 'tymedicalreport/import', + table: 'ty_medical_report', + } + }); + + var table = $("#table"); + + // 初始化表格 + table.bootstrapTable({ + url: $.fn.bootstrapTable.defaults.extend.index_url, + pk: 'id', + sortName: 'id', + columns: [ + [ + {checkbox: true}, + {field: 'id', title: __('Id')}, + {field: 'doctor', title: __('Doctor'), operate: 'LIKE'}, + {field: 'username', title: __('Username'), operate: 'LIKE'}, + {field: 'create_time', title: __('Create_time'), operate:'RANGE', addclass:'datetimerange', autocomplete:false, formatter: Table.api.formatter.datetime}, + {field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate} + ] + ] + }); + + // 为表格绑定事件 + Table.api.bindevent(table); + }, + add: function () { + Controller.api.bindevent(); + }, + edit: function () { + Controller.api.bindevent(); + }, + api: { + bindevent: function () { + Form.api.bindevent($("form[role=form]")); + } + } + }; + return Controller; +});