571 changed files with 34 additions and 73228 deletions
@ -1,50 +1,2 @@
@@ -1,50 +1,2 @@
|
||||
# Windows image file caches |
||||
Thumbs.db |
||||
ehthumbs.db |
||||
|
||||
# Folder config file |
||||
Desktop.ini |
||||
|
||||
# Recycle Bin used on file shares |
||||
$RECYCLE.BIN/ |
||||
|
||||
# Windows Installer files |
||||
*.cab |
||||
*.msi |
||||
*.msm |
||||
*.msp |
||||
|
||||
# Windows shortcuts |
||||
*.lnk |
||||
|
||||
# ========================= |
||||
# Operating System Files |
||||
# ========================= |
||||
|
||||
# OSX |
||||
# ========================= |
||||
|
||||
.DS_Store |
||||
.AppleDouble |
||||
.LSOverride |
||||
|
||||
# Thumbnails |
||||
._* |
||||
|
||||
# Files that might appear in the root of a volume |
||||
.DocumentRevisions-V100 |
||||
.fseventsd |
||||
.Spotlight-V100 |
||||
.TemporaryItems |
||||
.Trashes |
||||
.VolumeIcon.icns |
||||
|
||||
# Directories potentially created on remote AFP share |
||||
.AppleDB |
||||
.AppleDesktop |
||||
Network Trash Folder |
||||
Temporary Items |
||||
.apdisk |
||||
/nbproject/private/ |
||||
|
||||
Server.php |
||||
Server.php |
||||
/vendor/ |
@ -1,7 +0,0 @@
@@ -1,7 +0,0 @@
|
||||
<?php |
||||
|
||||
// autoload.php @generated by Composer |
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php'; |
||||
|
||||
return ComposerAutoloaderInita3d708ca3bb0f3f4e817238e4fb57153::getLoader(); |
@ -1,5 +0,0 @@
@@ -1,5 +0,0 @@
|
||||
phpunit.xml |
||||
reports |
||||
sandbox |
||||
vendor |
||||
composer.lock |
@ -1,12 +0,0 @@
@@ -1,12 +0,0 @@
|
||||
language: php |
||||
|
||||
php: |
||||
- 5.4 |
||||
- 5.5 |
||||
- 5.6 |
||||
- 7 |
||||
- hhvm |
||||
|
||||
before_script: |
||||
- sh -c 'if [ "$TRAVIS_PHP_VERSION" != "hhvm" ]; then echo "session.serialize_handler = php" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; fi;' |
||||
- composer install --dev --prefer-source |
@ -1,140 +0,0 @@
@@ -1,140 +0,0 @@
|
||||
CHANGELOG |
||||
========= |
||||
|
||||
###Legend |
||||
|
||||
* "BC": Backwards compatibility break (from public component APIs) |
||||
* "BF": Bug fix |
||||
|
||||
--- |
||||
|
||||
* 0.4 (2016-) |
||||
|
||||
* 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 |
||||
* Significant performance enhancements |
||||
|
||||
* 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 |
@ -1,19 +0,0 @@
@@ -1,19 +0,0 @@
|
||||
Copyright (c) 2011-2016 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. |
@ -1,37 +0,0 @@
@@ -1,37 +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: |
||||
phpunit |
||||
|
||||
cover: |
||||
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/react \
|
||||
-s vendor/guzzle \
|
||||
-s vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/Session \
|
||||
-s vendor/symfony/routing/Symfony/Component/Routing \
|
||||
-s vendor/evenement/evenement/src/Evenement |
@ -1,83 +0,0 @@
@@ -1,83 +0,0 @@
|
||||
#Ratchet |
||||
|
||||
[](http://travis-ci.org/ratchetphp/Ratchet) |
||||
[](http://socketo.me/reports/ab/index.html) |
||||
[](https://packagist.org/packages/cboden/ratchet) |
||||
|
||||
A PHP 5.4 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#serverconfiguration). |
||||
|
||||
### 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 |
||||
<?php |
||||
use Ratchet\MessageComponentInterface; |
||||
use Ratchet\ConnectionInterface; |
||||
|
||||
// Make sure composer dependencies have been installed |
||||
require __DIR__ . '/vendor/autoload.php'; |
||||
|
||||
/** |
||||
* chat.php |
||||
* Send any incoming messages to all connected clients (except sender) |
||||
*/ |
||||
class MyChat implements MessageComponentInterface { |
||||
protected $clients; |
||||
|
||||
public function __construct() { |
||||
$this->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); |
||||
$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.send('Hello Me!'); |
||||
``` |
@ -1,36 +0,0 @@
@@ -1,36 +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" |
||||
} |
||||
] |
||||
, "support": { |
||||
"forum": "https://groups.google.com/forum/#!forum/ratchet-php" |
||||
, "issues": "https://github.com/ratchetphp/Ratchet/issues" |
||||
, "irc": "irc://irc.freenode.org/reactphp" |
||||
} |
||||
, "autoload": { |
||||
"psr-4": { |
||||
"Ratchet\\": "src/Ratchet" |
||||
} |
||||
} |
||||
, "suggest": { |
||||
"ext-pecl_http": "^2.0" |
||||
} |
||||
, "require": { |
||||
"php": ">=5.4.2" |
||||
, "ratchet/rfc6455": "^0.2" |
||||
, "react/socket": "^0.3 || ^0.4" |
||||
, "guzzlehttp/psr7": "^1.0" |
||||
, "symfony/http-foundation": "^2.2|^3.0" |
||||
, "symfony/routing": "^2.2|^3.0" |
||||
} |
||||
} |
@ -1,30 +0,0 @@
@@ -1,30 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<phpunit |
||||
forceCoversAnnotation="true" |
||||
mapTestClassNameToCoveredClassName="true" |
||||
bootstrap="tests/bootstrap.php" |
||||
colors="true" |
||||
backupGlobals="false" |
||||
backupStaticAttributes="false" |
||||
syntaxCheck="false" |
||||
stopOnError="false" |
||||
> |
||||
|
||||
<testsuites> |
||||
<testsuite name="unit"> |
||||
<directory>./tests/unit/</directory> |
||||
</testsuite> |
||||
</testsuites> |
||||
|
||||
<testsuites> |
||||
<testsuite name="integration"> |
||||
<directory>./tests/integration/</directory> |
||||
</testsuite> |
||||
</testsuites> |
||||
|
||||
<filter> |
||||
<whitelist> |
||||
<directory>./src/</directory> |
||||
</whitelist> |
||||
</filter> |
||||
</phpunit> |
@ -1,41 +0,0 @@
@@ -1,41 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet; |
||||
|
||||
/** |
||||
* Wraps ConnectionInterface objects via the decorator pattern but allows |
||||
* parameters to bubble through with magic methods |
||||
* @todo It sure would be nice if I could make most of this a trait... |
||||
*/ |
||||
abstract class AbstractConnectionDecorator implements ConnectionInterface { |
||||
/** |
||||
* @var ConnectionInterface |
||||
*/ |
||||
protected $wrappedConn; |
||||
|
||||
public function __construct(ConnectionInterface $conn) { |
||||
$this->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); |
||||
} |
||||
} |
@ -1,150 +0,0 @@
@@ -1,150 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet; |
||||
use React\EventLoop\LoopInterface; |
||||
use React\EventLoop\Factory as LoopFactory; |
||||
use React\Socket\Server as Reactor; |
||||
use Ratchet\Http\HttpServerInterface; |
||||
use Ratchet\Http\OriginCheck; |
||||
use Ratchet\Wamp\WampServerInterface; |
||||
use Ratchet\Server\IoServer; |
||||
use Ratchet\Server\FlashPolicy; |
||||
use Ratchet\Http\HttpServer; |
||||
use Ratchet\Http\Router; |
||||
use Ratchet\WebSocket\WsServer; |
||||
use Ratchet\Wamp\WampServer; |
||||
use Symfony\Component\Routing\RouteCollection; |
||||
use Symfony\Component\Routing\Route; |
||||
use Symfony\Component\Routing\RequestContext; |
||||
use Symfony\Component\Routing\Matcher\UrlMatcher; |
||||
|
||||
/** |
||||
* An opinionated facade class to quickly and easily create a WebSocket server. |
||||
* A few configuration assumptions are made and some best-practice security conventions are applied by default. |
||||
*/ |
||||
class App { |
||||
/** |
||||
* @var \Symfony\Component\Routing\RouteCollection |
||||
*/ |
||||
public $routes; |
||||
|
||||
/** |
||||
* @var \Ratchet\Server\IoServer |
||||
*/ |
||||
public $flashServer; |
||||
|
||||
/** |
||||
* @var \Ratchet\Server\IoServer |
||||
*/ |
||||
protected $_server; |
||||
|
||||
/** |
||||
* The Host passed in construct used for same origin policy |
||||
* @var string |
||||
*/ |
||||
protected $httpHost; |
||||
|
||||
/*** |
||||
* The port the socket is listening |
||||
* @var int |
||||
*/ |
||||
protected $port; |
||||
|
||||
/** |
||||
* @var int |
||||
*/ |
||||
protected $_routeCounter = 0; |
||||
|
||||
/** |
||||
* @param string $httpHost HTTP hostname clients intend to connect to. MUST match JS `new WebSocket('ws://$httpHost');` |
||||
* @param int $port Port to listen on. If 80, assuming production, Flash on 843 otherwise expecting Flash to be proxied through 8843 |
||||
* @param string $address IP address to bind to. Default is localhost/proxy only. '0.0.0.0' for any machine. |
||||
* @param LoopInterface $loop Specific React\EventLoop to bind the application to. null will create one for you. |
||||
*/ |
||||
public function __construct($httpHost = 'localhost', $port = 8080, $address = '127.0.0.1', LoopInterface $loop = null) { |
||||
if (extension_loaded('xdebug')) { |
||||
trigger_error('XDebug extension detected. Remember to disable this if performance testing or going live!', E_USER_WARNING); |
||||
} |
||||
|
||||
if (3 !== strlen('✓')) { |
||||
throw new \DomainException('Bad encoding, length of unicode character ✓ should be 3. Ensure charset UTF-8 and check ini val mbstring.func_autoload'); |
||||
} |
||||
|
||||
if (null === $loop) { |
||||
$loop = LoopFactory::create(); |
||||
} |
||||
|
||||
$this->httpHost = $httpHost; |
||||
$this->port = $port; |
||||
|
||||
$socket = new Reactor($loop); |
||||
$socket->listen($port, $address); |
||||
|
||||
$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); |
||||
$flashSock = new Reactor($loop); |
||||
$this->flashServer = new IoServer($policy, $flashSock); |
||||
if (80 == $port) { |
||||
$flashSock->listen(843, '0.0.0.0'); |
||||
} else { |
||||
$flashSock->listen(8843); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 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)); |
||||
} elseif ($controller instanceof MessageComponentInterface) { |
||||
$decorated = new WsServer($controller); |
||||
} else { |
||||
$decorated = $controller; |
||||
} |
||||
|
||||
if ($decorated instanceof WsServer) { |
||||
$decorated->enableKeepAlive($this->_server->loop, 30); |
||||
} |
||||
|
||||
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)); |
||||
|
||||
return $decorated; |
||||
} |
||||
|
||||
/** |
||||
* Run the server by entering the event loop |
||||
*/ |
||||
public function run() { |
||||
$this->_server->run(); |
||||
} |
||||
} |
@ -1,31 +0,0 @@
@@ -1,31 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet; |
||||
|
||||
/** |
||||
* This is the interface to build a Ratchet application with. |
||||
* It implements the decorator pattern to build an application stack |
||||
*/ |
||||
interface ComponentInterface { |
||||
/** |
||||
* When a new connection is opened it will be passed to this method |
||||
* @param ConnectionInterface $conn The socket/connection that just connected to your application |
||||
* @throws \Exception |
||||
*/ |
||||
function onOpen(ConnectionInterface $conn); |
||||
|
||||
/** |
||||
* This is called before or after a socket is closed (depends on how it's closed). SendMessage to $conn will not result in an error if it has already been closed. |
||||
* @param ConnectionInterface $conn The socket/connection that is closing/closed |
||||
* @throws \Exception |
||||
*/ |
||||
function onClose(ConnectionInterface $conn); |
||||
|
||||
/** |
||||
* If there is an error with one of the sockets, or somewhere in the application where an Exception is thrown, |
||||
* the Exception is sent back down the stack, handled by the Server and bubbled back up the application through this method |
||||
* @param ConnectionInterface $conn |
||||
* @param \Exception $e |
||||
* @throws \Exception |
||||
*/ |
||||
function onError(ConnectionInterface $conn, \Exception $e); |
||||
} |
@ -1,26 +0,0 @@
@@ -1,26 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet; |
||||
|
||||
/** |
||||
* The version of Ratchet being used |
||||
* @var string |
||||
*/ |
||||
const VERSION = 'Ratchet/0.4'; |
||||
|
||||
/** |
||||
* A proxy object representing a connection to the application |
||||
* This acts as a container to store data (in memory) about the connection |
||||
*/ |
||||
interface ConnectionInterface { |
||||
/** |
||||
* Send data to the connection |
||||
* @param string $data |
||||
* @return \Ratchet\ConnectionInterface |
||||
*/ |
||||
function send($data); |
||||
|
||||
/** |
||||
* Close the connection |
||||
*/ |
||||
function close(); |
||||
} |
@ -1,22 +0,0 @@
@@ -1,22 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Http; |
||||
use Ratchet\ConnectionInterface; |
||||
use GuzzleHttp\Psr7 as gPsr; |
||||
use GuzzleHttp\Psr7\Response; |
||||
|
||||
trait CloseResponseTrait { |
||||
/** |
||||
* Close a connection with an HTTP response |
||||
* @param \Ratchet\ConnectionInterface $conn |
||||
* @param int $code HTTP status code |
||||
* @return null |
||||
*/ |
||||
private function close(ConnectionInterface $conn, $code = 400, array $additional_headers = []) { |
||||
$response = new Response($code, array_merge([ |
||||
'X-Powered-By' => \Ratchet\VERSION |
||||
], $additional_headers)); |
||||
|
||||
$conn->send(gPsr\str($response)); |
||||
$conn->close(); |
||||
} |
||||
} |
@ -1,76 +0,0 @@
@@ -1,76 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Http; |
||||
use Ratchet\MessageInterface; |
||||
use Ratchet\ConnectionInterface; |
||||
use GuzzleHttp\Psr7 as gPsr; |
||||
|
||||
/** |
||||
* This class receives streaming data from a client request |
||||
* and parses HTTP headers, returning a PSR-7 Request object |
||||
* once it's been buffered |
||||
*/ |
||||
class HttpRequestParser implements MessageInterface { |
||||
const EOM = "\r\n\r\n"; |
||||
|
||||
/** |
||||
* The maximum number of bytes the request can be |
||||
* This is a security measure to prevent attacks |
||||
* @var int |
||||
*/ |
||||
public $maxSize = 4096; |
||||
|
||||
/** |
||||
* @param \Ratchet\ConnectionInterface $context |
||||
* @param string $data Data stream to buffer |
||||
* @return \Psr\Http\Message\RequestInterface |
||||
* @throws \OverflowException If the message buffer has become too large |
||||
*/ |
||||
public function onMessage(ConnectionInterface $context, $data) { |
||||
if (!isset($context->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) { |
||||
if (function_exists('http_parse_message')) { |
||||
$parts = http_parse_message($headers); |
||||
|
||||
return new gPsr\Request( |
||||
$parts->requestMethod |
||||
, $parts->requestUrl |
||||
, $parts->headers |
||||
, null |
||||
, $parts->httpVersion |
||||
); |
||||
} else { |
||||
return gPsr\parse_request($headers); |
||||
} |
||||
} |
||||
} |
@ -1,76 +0,0 @@
@@ -1,76 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Http; |
||||
use Ratchet\MessageComponentInterface; |
||||
use Ratchet\ConnectionInterface; |
||||
|
||||
class HttpServer implements MessageComponentInterface { |
||||
use CloseResponseTrait; |
||||
|
||||
/** |
||||
* Buffers incoming HTTP requests returning a Guzzle Request when coalesced |
||||
* @var HttpRequestParser |
||||
* @note May not expose this in the future, may do through facade methods |
||||
*/ |
||||
protected $_reqParser; |
||||
|
||||
/** |
||||
* @var \Ratchet\Http\HttpServerInterface |
||||
*/ |
||||
protected $_httpServer; |
||||
|
||||
/** |
||||
* @param HttpServerInterface |
||||
*/ |
||||
public function __construct(HttpServerInterface $component) { |
||||
$this->_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); |
||||
} |
||||
} |
||||
} |
@ -1,14 +0,0 @@
@@ -1,14 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Http; |
||||
use Ratchet\MessageComponentInterface; |
||||
use Ratchet\ConnectionInterface; |
||||
use Psr\Http\Message\RequestInterface; |
||||
|
||||
interface HttpServerInterface extends MessageComponentInterface { |
||||
/** |
||||
* @param \Ratchet\ConnectionInterface $conn |
||||
* @param \Psr\Http\Message\RequestInterface $request null is default because PHP won't let me overload; don't pass null!!! |
||||
* @throws \UnexpectedValueException if a RequestInterface is not passed |
||||
*/ |
||||
public function onOpen(ConnectionInterface $conn, RequestInterface $request = null); |
||||
} |
@ -1,65 +0,0 @@
@@ -1,65 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Http; |
||||
use Ratchet\ConnectionInterface; |
||||
use Ratchet\MessageComponentInterface; |
||||
use Psr\Http\Message\RequestInterface; |
||||
|
||||
/** |
||||
* A middleware to ensure JavaScript clients connecting are from the expected domain. |
||||
* This protects other websites from open WebSocket connections to your application. |
||||
* Note: This can be spoofed from non-web browser clients |
||||
*/ |
||||
class OriginCheck implements HttpServerInterface { |
||||
use CloseResponseTrait; |
||||
|
||||
/** |
||||
* @var \Ratchet\MessageComponentInterface |
||||
*/ |
||||
protected $_component; |
||||
|
||||
public $allowedOrigins = []; |
||||
|
||||
/** |
||||
* @param MessageComponentInterface $component Component/Application to decorate |
||||
* @param array $allowed An array of allowed domains that are allowed to connect from |
||||
*/ |
||||
public function __construct(MessageComponentInterface $component, array $allowed = []) { |
||||
$this->_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); |
||||
} |
||||
} |
@ -1,91 +0,0 @@
@@ -1,91 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Http; |
||||
use Ratchet\ConnectionInterface; |
||||
use Psr\Http\Message\RequestInterface; |
||||
use Symfony\Component\Routing\Matcher\UrlMatcherInterface; |
||||
use Symfony\Component\Routing\Exception\MethodNotAllowedException; |
||||
use Symfony\Component\Routing\Exception\ResourceNotFoundException; |
||||
use GuzzleHttp\Psr7 as gPsr; |
||||
|
||||
class Router implements HttpServerInterface { |
||||
use CloseResponseTrait; |
||||
|
||||
/** |
||||
* @var \Symfony\Component\Routing\Matcher\UrlMatcherInterface |
||||
*/ |
||||
protected $_matcher; |
||||
|
||||
public function __construct(UrlMatcherInterface $matcher) { |
||||
$this->_matcher = $matcher; |
||||
} |
||||
|
||||
/** |
||||
* {@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'); |
||||
} |
||||
|
||||
$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, 403); |
||||
} 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, gPsr\parse_query($uri->getQuery() ?: '')); |
||||
|
||||
$request = $request->withUri($uri->withQuery(gPsr\build_query($parameters))); |
||||
|
||||
$conn->controller = $route['_controller']; |
||||
$conn->controller->onOpen($conn, $request); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
function onMessage(ConnectionInterface $from, $msg) { |
||||
$from->controller->onMessage($from, $msg); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
function onClose(ConnectionInterface $conn) { |
||||
if (isset($conn->controller)) { |
||||
$conn->controller->onClose($conn); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
function onError(ConnectionInterface $conn, \Exception $e) { |
||||
if (isset($conn->controller)) { |
||||
$conn->controller->onError($conn, $e); |
||||
} |
||||
} |
||||
} |
@ -1,5 +0,0 @@
@@ -1,5 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet; |
||||
|
||||
interface MessageComponentInterface extends ComponentInterface, MessageInterface { |
||||
} |
@ -1,12 +0,0 @@
@@ -1,12 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet; |
||||
|
||||
interface MessageInterface { |
||||
/** |
||||
* Triggered when a client sends data through the socket |
||||
* @param \Ratchet\ConnectionInterface $from The socket/connection that sent the message to your application |
||||
* @param string $msg The message received |
||||
* @throws \Exception |
||||
*/ |
||||
function onMessage(ConnectionInterface $from, $msg); |
||||
} |
@ -1,23 +0,0 @@
@@ -1,23 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Server; |
||||
use Ratchet\MessageComponentInterface; |
||||
use Ratchet\ConnectionInterface; |
||||
|
||||
/** |
||||
* A simple Ratchet application that will reply to all messages with the message it received |
||||
*/ |
||||
class EchoServer implements MessageComponentInterface { |
||||
public function onOpen(ConnectionInterface $conn) { |
||||
} |
||||
|
||||
public function onMessage(ConnectionInterface $from, $msg) { |
||||
$from->send($msg); |
||||
} |
||||
|
||||
public function onClose(ConnectionInterface $conn) { |
||||
} |
||||
|
||||
public function onError(ConnectionInterface $conn, \Exception $e) { |
||||
$conn->close(); |
||||
} |
||||
} |
@ -1,200 +0,0 @@
@@ -1,200 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Server; |
||||
use Ratchet\MessageComponentInterface; |
||||
use Ratchet\ConnectionInterface; |
||||
|
||||
/** |
||||
* An app to go on a server stack to pass a policy file to a Flash socket |
||||
* Useful if you're using Flash as a WebSocket polyfill on IE |
||||
* Be sure to run your server instance on port 843 |
||||
* By default this lets accepts everything, make sure you tighten the rules up for production |
||||
* @final |
||||
* @link http://www.adobe.com/devnet/articles/crossdomain_policy_file_spec.html |
||||
* @link http://learn.adobe.com/wiki/download/attachments/64389123/CrossDomain_PolicyFile_Specification.pdf?version=1 |
||||
* @link view-source:http://www.adobe.com/xml/schemas/PolicyFileSocket.xsd |
||||
*/ |
||||
class FlashPolicy implements MessageComponentInterface { |
||||
|
||||
/** |
||||
* Contains the root policy node |
||||
* @var string |
||||
*/ |
||||
protected $_policy = '<?xml version="1.0"?><!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd"><cross-domain-policy></cross-domain-policy>'; |
||||
|
||||
/** |
||||
* 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); |
||||
} |
||||
} |
@ -1,38 +0,0 @@
@@ -1,38 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Server; |
||||
use Ratchet\ConnectionInterface; |
||||
use React\Socket\ConnectionInterface as ReactConn; |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
class IoConnection implements ConnectionInterface { |
||||
/** |
||||
* @var \React\Socket\ConnectionInterface |
||||
*/ |
||||
protected $conn; |
||||
|
||||
|
||||
/** |
||||
* @param \React\Socket\ConnectionInterface $conn |
||||
*/ |
||||
public function __construct(ReactConn $conn) { |
||||
$this->conn = $conn; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function send($data) { |
||||
$this->conn->write($data); |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function close() { |
||||
$this->conn->end(); |
||||
} |
||||
} |
@ -1,141 +0,0 @@
@@ -1,141 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Server; |
||||
use Ratchet\MessageComponentInterface; |
||||
use React\EventLoop\LoopInterface; |
||||
use React\Socket\ServerInterface; |
||||
use React\EventLoop\Factory as LoopFactory; |
||||
use React\Socket\Server as Reactor; |
||||
|
||||
/** |
||||
* Creates an open-ended socket to listen on a port for incoming connections. |
||||
* Events are delegated through this to attached applications |
||||
*/ |
||||
class IoServer { |
||||
/** |
||||
* @var \React\EventLoop\LoopInterface |
||||
*/ |
||||
public $loop; |
||||
|
||||
/** |
||||
* @var \Ratchet\MessageComponentInterface |
||||
*/ |
||||
public $app; |
||||
|
||||
/** |
||||
* Array of React event handlers |
||||
* @var \SplFixedArray |
||||
*/ |
||||
protected $handlers; |
||||
|
||||
/** |
||||
* The socket server the Ratchet Application is run off of |
||||
* @var \React\Socket\ServerInterface |
||||
*/ |
||||
public $socket; |
||||
|
||||
/** |
||||
* @param \Ratchet\MessageComponentInterface $app The Ratchet application stack to host |
||||
* @param \React\Socket\ServerInterface $socket The React socket server to run the Ratchet application off of |
||||
* @param \React\EventLoop\LoopInterface|null $loop The React looper to run the Ratchet application off of |
||||
*/ |
||||
public function __construct(MessageComponentInterface $app, ServerInterface $socket, LoopInterface $loop = null) { |
||||
if (false === strpos(PHP_VERSION, "hiphop")) { |
||||
gc_enable(); |
||||
} |
||||
|
||||
set_time_limit(0); |
||||
ob_implicit_flush(); |
||||
|
||||
$this->loop = $loop; |
||||
$this->app = $app; |
||||
$this->socket = $socket; |
||||
|
||||
$socket->on('connection', array($this, 'handleConnect')); |
||||
|
||||
$this->handlers = new \SplFixedArray(3); |
||||
$this->handlers[0] = array($this, 'handleData'); |
||||
$this->handlers[1] = array($this, 'handleEnd'); |
||||
$this->handlers[2] = array($this, 'handleError'); |
||||
} |
||||
|
||||
/** |
||||
* @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($loop); |
||||
$socket->listen($port, $address); |
||||
|
||||
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; |
||||
$conn->decor->remoteAddress = $conn->getRemoteAddress(); |
||||
|
||||
$this->app->onOpen($conn->decor); |
||||
|
||||
$conn->on('data', $this->handlers[0]); |
||||
$conn->on('end', $this->handlers[1]); |
||||
$conn->on('error', $this->handlers[2]); |
||||
} |
||||
|
||||
/** |
||||
* 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); |
||||
} |
||||
} |
@ -1,111 +0,0 @@
@@ -1,111 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Server; |
||||
use Ratchet\MessageComponentInterface; |
||||
use Ratchet\ConnectionInterface; |
||||
|
||||
class IpBlackList implements MessageComponentInterface { |
||||
/** |
||||
* @var array |
||||
*/ |
||||
protected $_blacklist = array(); |
||||
|
||||
/** |
||||
* @var \Ratchet\MessageComponentInterface |
||||
*/ |
||||
protected $_decorating; |
||||
|
||||
/** |
||||
* @param \Ratchet\MessageComponentInterface $component |
||||
*/ |
||||
public function __construct(MessageComponentInterface $component) { |
||||
$this->_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); |
||||
} |
||||
} |
||||
} |
@ -1,16 +0,0 @@
@@ -1,16 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Session\Serialize; |
||||
|
||||
interface HandlerInterface { |
||||
/** |
||||
* @param array |
||||
* @return string |
||||
*/ |
||||
function serialize(array $data); |
||||
|
||||
/** |
||||
* @param string |
||||
* @return array |
||||
*/ |
||||
function unserialize($raw); |
||||
} |
@ -1,33 +0,0 @@
@@ -1,33 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Session\Serialize; |
||||
|
||||
class PhpBinaryHandler implements HandlerInterface { |
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
function serialize(array $data) { |
||||
throw new \RuntimeException("Serialize PhpHandler:serialize code not written yet, write me!"); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
* @link http://ca2.php.net/manual/en/function.session-decode.php#108037 Code from this comment on php.net |
||||
*/ |
||||
public function unserialize($raw) { |
||||
$returnData = array(); |
||||
$offset = 0; |
||||
|
||||
while ($offset < strlen($raw)) { |
||||
$num = ord($raw[$offset]); |
||||
$offset += 1; |
||||
$varname = substr($raw, $offset, $num); |
||||
$offset += $num; |
||||
$data = unserialize(substr($raw, $offset)); |
||||
|
||||
$returnData[$varname] = $data; |
||||
$offset += strlen(serialize($data)); |
||||
} |
||||
|
||||
return $returnData; |
||||
} |
||||
} |
@ -1,38 +0,0 @@
@@ -1,38 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Session\Serialize; |
||||
|
||||
class PhpHandler implements HandlerInterface { |
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
function serialize(array $data) { |
||||
throw new \RuntimeException("Serialize PhpHandler:serialize code not written yet, write me!"); |
||||
} |
||||
|
||||
/** |
||||
* {@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; |
||||
} |
||||
} |
@ -1,243 +0,0 @@
@@ -1,243 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Session; |
||||
use Ratchet\ConnectionInterface; |
||||
use Ratchet\Http\HttpServerInterface; |
||||
use Psr\Http\Message\RequestInterface; |
||||
use Ratchet\Session\Storage\VirtualSessionStorage; |
||||
use Ratchet\Session\Serialize\HandlerInterface; |
||||
use Symfony\Component\HttpFoundation\Session\Session; |
||||
use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler; |
||||
|
||||
/** |
||||
* This component will allow access to session data from your website for each user connected |
||||
* Symfony HttpFoundation is required for this component to work |
||||
* Your website must also use Symfony HttpFoundation Sessions to read your sites session data |
||||
* If your are not using at least PHP 5.4 you must include a SessionHandlerInterface stub (is included in Symfony HttpFoundation, loaded w/ composer) |
||||
*/ |
||||
class SessionProvider implements HttpServerInterface { |
||||
/** |
||||
* @var \Ratchet\MessageComponentInterface |
||||
*/ |
||||
protected $_app; |
||||
|
||||
/** |
||||
* Selected handler storage assigned by the developer |
||||
* @var \SessionHandlerInterface |
||||
*/ |
||||
protected $_handler; |
||||
|
||||
/** |
||||
* Null storage handler if no previous session was found |
||||
* @var \SessionHandlerInterface |
||||
*/ |
||||
protected $_null; |
||||
|
||||
/** |
||||
* @var \Ratchet\Session\Serialize\HandlerInterface |
||||
*/ |
||||
protected $_serializer; |
||||
|
||||
/** |
||||
* @param \Ratchet\Http\HttpServerInterface $app |
||||
* @param \SessionHandlerInterface $handler |
||||
* @param array $options |
||||
* @param \Ratchet\Session\Serialize\HandlerInterface $serializer |
||||
* @throws \RuntimeException |
||||
*/ |
||||
public function __construct(HttpServerInterface $app, \SessionHandlerInterface $handler, array $options = array(), HandlerInterface $serializer = null) { |
||||
$this->_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; |
||||
} |
||||
} |
@ -1,54 +0,0 @@
@@ -1,54 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Session\Storage\Proxy; |
||||
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy; |
||||
|
||||
class VirtualProxy extends SessionHandlerProxy { |
||||
/** |
||||
* @var string |
||||
*/ |
||||
protected $_sessionId; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
protected $_sessionName; |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function __construct(\SessionHandlerInterface $handler) { |
||||
parent::__construct($handler); |
||||
|
||||
$this->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"); |
||||
} |
||||
} |
@ -1,88 +0,0 @@
@@ -1,88 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Session\Storage; |
||||
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; |
||||
use Ratchet\Session\Storage\Proxy\VirtualProxy; |
||||
use Ratchet\Session\Serialize\HandlerInterface; |
||||
|
||||
class VirtualSessionStorage extends NativeSessionStorage { |
||||
/** |
||||
* @var \Ratchet\Session\Serialize\HandlerInterface |
||||
*/ |
||||
protected $_serializer; |
||||
|
||||
/** |
||||
* @param \SessionHandlerInterface $handler |
||||
* @param string $sessionId The ID of the session to retrieve |
||||
* @param \Ratchet\Session\Serialize\HandlerInterface $serializer |
||||
*/ |
||||
public function __construct(\SessionHandlerInterface $handler, $sessionId, HandlerInterface $serializer) { |
||||
$this->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; |
||||
} |
||||
} |
@ -1,5 +0,0 @@
@@ -1,5 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Wamp; |
||||
|
||||
class Exception extends \Exception { |
||||
} |
@ -1,31 +0,0 @@
@@ -1,31 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Wamp; |
||||
|
||||
class JsonException extends Exception { |
||||
public function __construct() { |
||||
$code = json_last_error(); |
||||
|
||||
switch ($code) { |
||||
case JSON_ERROR_DEPTH: |
||||
$msg = 'Maximum stack depth exceeded'; |
||||
break; |
||||
case JSON_ERROR_STATE_MISMATCH: |
||||
$msg = 'Underflow or the modes mismatch'; |
||||
break; |
||||
case JSON_ERROR_CTRL_CHAR: |
||||
$msg = 'Unexpected control character found'; |
||||
break; |
||||
case JSON_ERROR_SYNTAX: |
||||
$msg = 'Syntax error, malformed JSON'; |
||||
break; |
||||
case JSON_ERROR_UTF8: |
||||
$msg = 'Malformed UTF-8 characters, possibly incorrectly encoded'; |
||||
break; |
||||
default: |
||||
$msg = 'Unknown error'; |
||||
break; |
||||
} |
||||
|
||||
parent::__construct($msg, $code); |
||||
} |
||||
} |
@ -1,157 +0,0 @@
@@ -1,157 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Wamp; |
||||
use Ratchet\MessageComponentInterface; |
||||
use Ratchet\WebSocket\WsServerInterface; |
||||
use Ratchet\ConnectionInterface; |
||||
|
||||
/** |
||||
* WebSocket Application Messaging Protocol |
||||
* |
||||
* @link http://wamp.ws/spec |
||||
* @link https://github.com/oberstet/AutobahnJS |
||||
* |
||||
* +--------------+----+------------------+ |
||||
* | Message Type | ID | DIRECTION | |
||||
* |--------------+----+------------------+ |
||||
* | WELCOME | 0 | Server-to-Client | |
||||
* | PREFIX | 1 | Bi-Directional | |
||||
* | CALL | 2 | Client-to-Server | |
||||
* | CALL RESULT | 3 | Server-to-Client | |
||||
* | CALL ERROR | 4 | Server-to-Client | |
||||
* | SUBSCRIBE | 5 | Client-to-Server | |
||||
* | UNSUBSCRIBE | 6 | Client-to-Server | |
||||
* | PUBLISH | 7 | Client-to-Server | |
||||
* | EVENT | 8 | Server-to-Client | |
||||
* +--------------+----+------------------+ |
||||
*/ |
||||
class ServerProtocol implements MessageComponentInterface, WsServerInterface { |
||||
const MSG_WELCOME = 0; |
||||
const MSG_PREFIX = 1; |
||||
const MSG_CALL = 2; |
||||
const MSG_CALL_RESULT = 3; |
||||
const MSG_CALL_ERROR = 4; |
||||
const MSG_SUBSCRIBE = 5; |
||||
const MSG_UNSUBSCRIBE = 6; |
||||
const MSG_PUBLISH = 7; |
||||
const MSG_EVENT = 8; |
||||
|
||||
/** |
||||
* @var WampServerInterface |
||||
*/ |
||||
protected $_decorating; |
||||
|
||||
/** |
||||
* @var \SplObjectStorage |
||||
*/ |
||||
protected $connections; |
||||
|
||||
/** |
||||
* @param WampServerInterface $serverComponent An class to propagate calls through |
||||
*/ |
||||
public function __construct(WampServerInterface $serverComponent) { |
||||
$this->_decorating = $serverComponent; |
||||
$this->connections = new \SplObjectStorage; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getSubProtocols() { |
||||
if ($this->_decorating instanceof WsServerInterface) { |
||||
$subs = $this->_decorating->getSubProtocols(); |
||||
$subs[] = 'wamp'; |
||||
|
||||
return $subs; |
||||
} else { |
||||
return array('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"); |
||||
} |
||||
|
||||
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 = array($from->WAMP->sessionId); |
||||
} else { |
||||
$exclude = array(); |
||||
} |
||||
} |
||||
|
||||
$eligible = (array_key_exists(4, $json) ? $json[4] : array()); |
||||
|
||||
$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); |
||||
} |
||||
} |
@ -1,106 +0,0 @@
@@ -1,106 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Wamp; |
||||
use Ratchet\ConnectionInterface; |
||||
|
||||
/** |
||||
* A topic/channel containing connections that have subscribed to it |
||||
*/ |
||||
class Topic implements \IteratorAggregate, \Countable { |
||||
/** |
||||
* If true the TopicManager will destroy this object if it's ever empty of connections |
||||
* @deprecated in v0.4 |
||||
* @type bool |
||||
*/ |
||||
public $autoDelete = false; |
||||
|
||||
private $id; |
||||
|
||||
private $subscribers; |
||||
|
||||
/** |
||||
* @param string $topicId Unique ID for this object |
||||
*/ |
||||
public function __construct($topicId) { |
||||
$this->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 $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} |
||||
*/ |
||||
public function getIterator() { |
||||
return $this->subscribers; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function count() { |
||||
return $this->subscribers->count(); |
||||
} |
||||
} |
@ -1,125 +0,0 @@
@@ -1,125 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Wamp; |
||||
use Ratchet\ConnectionInterface; |
||||
use Ratchet\WebSocket\WsServerInterface; |
||||
|
||||
class TopicManager implements WsServerInterface, WampServerInterface { |
||||
/** |
||||
* @var WampServerInterface |
||||
*/ |
||||
protected $app; |
||||
|
||||
/** |
||||
* @var array |
||||
*/ |
||||
protected $topicLookup = array(); |
||||
|
||||
public function __construct(WampServerInterface $app) { |
||||
$this->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 ($topic->autoDelete && 0 === $topic->count()) { |
||||
unset($this->topicLookup[$topic->getId()]); |
||||
} |
||||
} |
||||
} |
@ -1,115 +0,0 @@
@@ -1,115 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Wamp; |
||||
use Ratchet\ConnectionInterface; |
||||
use Ratchet\AbstractConnectionDecorator; |
||||
use Ratchet\Wamp\ServerProtocol as WAMP; |
||||
|
||||
/** |
||||
* A ConnectionInterface object wrapper that is passed to your WAMP application |
||||
* representing a client. Methods on this Connection are therefore different. |
||||
* @property \stdClass $WAMP |
||||
*/ |
||||
class WampConnection extends AbstractConnectionDecorator { |
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function __construct(ConnectionInterface $conn) { |
||||
parent::__construct($conn); |
||||
|
||||
$this->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); |
||||
} |
||||
|
||||
} |
@ -1,67 +0,0 @@
@@ -1,67 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Wamp; |
||||
use Ratchet\MessageComponentInterface; |
||||
use Ratchet\WebSocket\WsServerInterface; |
||||
use Ratchet\ConnectionInterface; |
||||
|
||||
/** |
||||
* Enable support for the official WAMP sub-protocol in your application |
||||
* WAMP allows for Pub/Sub and RPC |
||||
* @link http://wamp.ws The WAMP specification |
||||
* @link https://github.com/oberstet/AutobahnJS Souce for client side library |
||||
* @link http://autobahn.s3.amazonaws.com/js/autobahn.min.js Minified client side library |
||||
*/ |
||||
class WampServer implements MessageComponentInterface, WsServerInterface { |
||||
/** |
||||
* @var ServerProtocol |
||||
*/ |
||||
protected $wampProtocol; |
||||
|
||||
/** |
||||
* This class just makes it 1 step easier to use Topic objects in WAMP |
||||
* If you're looking at the source code, look in the __construct of this |
||||
* class and use that to make your application instead of using this |
||||
*/ |
||||
public function __construct(WampServerInterface $app) { |
||||
$this->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(); |
||||
} |
||||
} |
@ -1,43 +0,0 @@
@@ -1,43 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Wamp; |
||||
use Ratchet\ComponentInterface; |
||||
use Ratchet\ConnectionInterface; |
||||
|
||||
/** |
||||
* An extension of Ratchet\ComponentInterface to server a WAMP application |
||||
* onMessage is replaced by various types of messages for this protocol (pub/sub or rpc) |
||||
*/ |
||||
interface WampServerInterface extends ComponentInterface { |
||||
/** |
||||
* An RPC call has been received |
||||
* @param \Ratchet\ConnectionInterface $conn |
||||
* @param string $id The unique ID of the RPC, required to respond to |
||||
* @param string|Topic $topic The topic to execute the call against |
||||
* @param array $params Call parameters received from the client |
||||
*/ |
||||
function onCall(ConnectionInterface $conn, $id, $topic, array $params); |
||||
|
||||
/** |
||||
* A request to subscribe to a topic has been made |
||||
* @param \Ratchet\ConnectionInterface $conn |
||||
* @param string|Topic $topic The topic to subscribe to |
||||
*/ |
||||
function onSubscribe(ConnectionInterface $conn, $topic); |
||||
|
||||
/** |
||||
* A request to unsubscribe from a topic has been made |
||||
* @param \Ratchet\ConnectionInterface $conn |
||||
* @param string|Topic $topic The topic to unsubscribe from |
||||
*/ |
||||
function onUnSubscribe(ConnectionInterface $conn, $topic); |
||||
|
||||
/** |
||||
* A client is attempting to publish content to a subscribed connections on a URI |
||||
* @param \Ratchet\ConnectionInterface $conn |
||||
* @param string|Topic $topic The topic the user has attempted to publish to |
||||
* @param string $event Payload of the 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) |
||||
*/ |
||||
function onPublish(ConnectionInterface $conn, $topic, $event, array $exclude, array $eligible); |
||||
} |
@ -1,20 +0,0 @@
@@ -1,20 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\WebSocket; |
||||
use Ratchet\RFC6455\Messaging\MessageBuffer; |
||||
|
||||
class ConnContext { |
||||
/** |
||||
* @var \Ratchet\WebSocket\WsConnection |
||||
*/ |
||||
public $connection; |
||||
|
||||
/** |
||||
* @var \Ratchet\RFC6455\Messaging\MessageBuffer; |
||||
*/ |
||||
public $buffer; |
||||
|
||||
public function __construct(WsConnection $conn, MessageBuffer $buffer) { |
||||
$this->connection = $conn; |
||||
$this->buffer = $buffer; |
||||
} |
||||
} |
@ -1,8 +0,0 @@
@@ -1,8 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\WebSocket; |
||||
use Ratchet\ConnectionInterface; |
||||
use Ratchet\RFC6455\Messaging\MessageInterface; |
||||
|
||||
interface MessageCallableInterface { |
||||
public function onMessage(ConnectionInterface $conn, MessageInterface $msg); |
||||
} |
@ -1,6 +0,0 @@
@@ -1,6 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\WebSocket; |
||||
use Ratchet\ComponentInterface; |
||||
|
||||
interface MessageComponentInterface extends ComponentInterface, MessageCallableInterface { |
||||
} |
@ -1,45 +0,0 @@
@@ -1,45 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\WebSocket; |
||||
use Ratchet\AbstractConnectionDecorator; |
||||
use Ratchet\RFC6455\Messaging\DataInterface; |
||||
use Ratchet\RFC6455\Messaging\Frame; |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
* @property \StdClass $WebSocket |
||||
*/ |
||||
class WsConnection extends AbstractConnectionDecorator { |
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function send($msg) { |
||||
if (!$this->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; |
||||
} |
||||
} |
@ -1,221 +0,0 @@
@@ -1,221 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\WebSocket; |
||||
use Ratchet\ComponentInterface; |
||||
use Ratchet\ConnectionInterface; |
||||
use Ratchet\MessageComponentInterface as DataComponentInterface; |
||||
use Ratchet\Http\HttpServerInterface; |
||||
use Ratchet\Http\CloseResponseTrait; |
||||
use Psr\Http\Message\RequestInterface; |
||||
use Ratchet\RFC6455\Messaging\MessageInterface; |
||||
use Ratchet\RFC6455\Messaging\FrameInterface; |
||||
use Ratchet\RFC6455\Messaging\Frame; |
||||
use Ratchet\RFC6455\Messaging\MessageBuffer; |
||||
use Ratchet\RFC6455\Messaging\CloseFrameChecker; |
||||
use Ratchet\RFC6455\Handshake\ServerNegotiator; |
||||
use Ratchet\RFC6455\Handshake\RequestVerifier; |
||||
use React\EventLoop\LoopInterface; |
||||
use GuzzleHttp\Psr7 as gPsr; |
||||
|
||||
/** |
||||
* The adapter to handle WebSocket requests/responses |
||||
* This is a mediator between the Server and your application to handle real-time messaging through a web browser |
||||
* @link http://ca.php.net/manual/en/ref.http.php |
||||
* @link http://dev.w3.org/html5/websockets/ |
||||
*/ |
||||
class WsServer implements HttpServerInterface { |
||||
use CloseResponseTrait; |
||||
|
||||
/** |
||||
* Decorated component |
||||
* @var \Ratchet\ComponentInterface |
||||
*/ |
||||
private $delegate; |
||||
|
||||
/** |
||||
* @var \SplObjectStorage |
||||
*/ |
||||
protected $connections; |
||||
|
||||
/** |
||||
* @var \Ratchet\RFC6455\Messaging\CloseFrameChecker |
||||
*/ |
||||
private $closeFrameChecker; |
||||
|
||||
/** |
||||
* @var \Ratchet\RFC6455\Handshake\ServerNegotiator |
||||
*/ |
||||
private $handshakeNegotiator; |
||||
|
||||
/** |
||||
* @var \Closure |
||||
*/ |
||||
private $ueFlowFactory; |
||||
|
||||
/** |
||||
* @var \Closure |
||||
*/ |
||||
private $pongReceiver; |
||||
|
||||
/** |
||||
* @var \Closure |
||||
*/ |
||||
private $msgCb; |
||||
|
||||
/** |
||||
* @param \Ratchet\WebSocket\MessageComponentInterface|\Ratchet\MessageComponentInterface $component Your application to run with WebSockets |
||||
* @note If you want to enable sub-protocols have your component implement WsServerInterface as well |
||||
*/ |
||||
public function __construct(ComponentInterface $component) { |
||||
if ($component instanceof MessageComponentInterface) { |
||||
$this->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'); |
||||
} |
||||
|
||||
$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(gPsr\str($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); |
||||
} |
||||
}); |
||||
} |
||||
} |
@ -1,14 +0,0 @@
@@ -1,14 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\WebSocket; |
||||
|
||||
/** |
||||
* WebSocket Server Interface |
||||
*/ |
||||
interface WsServerInterface { |
||||
/** |
||||
* If any component in a stack supports a WebSocket sub-protocol return each supported in an array |
||||
* @return array |
||||
* @todo This method may be removed in future version (note that will not break code, just make some code obsolete) |
||||
*/ |
||||
function getSubProtocols(); |
||||
} |
@ -1,38 +0,0 @@
@@ -1,38 +0,0 @@
|
||||
<?php |
||||
use Ratchet\ConnectionInterface; |
||||
|
||||
require dirname(dirname(dirname(__DIR__))) . '/vendor/autoload.php'; |
||||
|
||||
class BinaryEcho implements \Ratchet\WebSocket\MessageComponentInterface { |
||||
public function onMessage(ConnectionInterface $from, \Ratchet\RFC6455\Messaging\MessageInterface $msg) { |
||||
$from->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($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); |
||||
|
||||
$sock->listen($port, '0.0.0.0'); |
||||
|
||||
$server = new Ratchet\Server\IoServer($app, $sock, $loop); |
||||
$server->run(); |
@ -1,15 +0,0 @@
@@ -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": {} |
||||
} |
@ -1,12 +0,0 @@
@@ -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": {} |
||||
} |
@ -1,12 +0,0 @@
@@ -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": {} |
||||
} |
@ -1,4 +0,0 @@
@@ -1,4 +0,0 @@
|
||||
<?php |
||||
|
||||
$loader = require __DIR__ . '/../vendor/autoload.php'; |
||||
$loader->addPsr4('Ratchet\\', __DIR__ . '/helpers/Ratchet'); |
@ -1,50 +0,0 @@
@@ -1,50 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet; |
||||
|
||||
abstract class AbstractMessageComponentTestCase extends \PHPUnit_Framework_TestCase { |
||||
protected $_app; |
||||
protected $_serv; |
||||
protected $_conn; |
||||
|
||||
abstract public function getConnectionClassString(); |
||||
abstract public function getDecoratorClassString(); |
||||
abstract public function getComponentClassString(); |
||||
|
||||
public function setUp() { |
||||
$this->_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); |
||||
} |
||||
} |
@ -1,35 +0,0 @@
@@ -1,35 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Mock; |
||||
use Ratchet\MessageComponentInterface; |
||||
use Ratchet\WebSocket\WsServerInterface; |
||||
use Ratchet\ConnectionInterface; |
||||
|
||||
class Component implements MessageComponentInterface, WsServerInterface { |
||||
public $last = array(); |
||||
|
||||
public $protocols = array(); |
||||
|
||||
public function __construct(ComponentInterface $app = null) { |
||||
$this->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; |
||||
} |
||||
} |
@ -1,20 +0,0 @@
@@ -1,20 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Mock; |
||||
use Ratchet\ConnectionInterface; |
||||
|
||||
class Connection implements ConnectionInterface { |
||||
public $last = array( |
||||
'send' => '' |
||||
, 'close' => false |
||||
); |
||||
|
||||
public $remoteAddress = '127.0.0.1'; |
||||
|
||||
public function send($data) { |
||||
$this->last[__FUNCTION__] = $data; |
||||
} |
||||
|
||||
public function close() { |
||||
$this->last[__FUNCTION__] = true; |
||||
} |
||||
} |
@ -1,22 +0,0 @@
@@ -1,22 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Mock; |
||||
use Ratchet\AbstractConnectionDecorator; |
||||
|
||||
class ConnectionDecorator extends AbstractConnectionDecorator { |
||||
public $last = array( |
||||
'write' => '' |
||||
, 'end' => false |
||||
); |
||||
|
||||
public function send($data) { |
||||
$this->last[__FUNCTION__] = $data; |
||||
|
||||
$this->getConnection()->send($data); |
||||
} |
||||
|
||||
public function close() { |
||||
$this->last[__FUNCTION__] = true; |
||||
|
||||
$this->getConnection()->close(); |
||||
} |
||||
} |
@ -1,43 +0,0 @@
@@ -1,43 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Mock; |
||||
use Ratchet\Wamp\WampServerInterface; |
||||
use Ratchet\WebSocket\WsServerInterface; |
||||
use Ratchet\ConnectionInterface; |
||||
|
||||
class WampComponent implements WampServerInterface, WsServerInterface { |
||||
public $last = array(); |
||||
|
||||
public $protocols = array(); |
||||
|
||||
public function getSubProtocols() { |
||||
return $this->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(); |
||||
} |
||||
} |
@ -1,28 +0,0 @@
@@ -1,28 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet; |
||||
use Ratchet\ConnectionInterface; |
||||
use Ratchet\MessageComponentInterface; |
||||
use Ratchet\WebSocket\WsServerInterface; |
||||
use Ratchet\Wamp\WampServerInterface; |
||||
|
||||
class NullComponent implements MessageComponentInterface, WsServerInterface, WampServerInterface { |
||||
public function onOpen(ConnectionInterface $conn) {} |
||||
|
||||
public function onMessage(ConnectionInterface $conn, $msg) {} |
||||
|
||||
public function onClose(ConnectionInterface $conn) {} |
||||
|
||||
public function onError(ConnectionInterface $conn, \Exception $e) {} |
||||
|
||||
public function onCall(ConnectionInterface $conn, $id, $topic, array $params) {} |
||||
|
||||
public function onSubscribe(ConnectionInterface $conn, $topic) {} |
||||
|
||||
public function onUnSubscribe(ConnectionInterface $conn, $topic) {} |
||||
|
||||
public function onPublish(ConnectionInterface $conn, $topic, $event, array $exclude = array(), array $eligible = array()) {} |
||||
|
||||
public function getSubProtocols() { |
||||
return array(); |
||||
} |
||||
} |
@ -1,7 +0,0 @@
@@ -1,7 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Wamp\Stub; |
||||
use Ratchet\WebSocket\WsServerInterface; |
||||
use Ratchet\Wamp\WampServerInterface; |
||||
|
||||
interface WsWampServerInterface extends WsServerInterface, WampServerInterface { |
||||
} |
@ -1,7 +0,0 @@
@@ -1,7 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\WebSocket\Stub; |
||||
use Ratchet\MessageComponentInterface; |
||||
use Ratchet\WebSocket\WsServerInterface; |
||||
|
||||
interface WsMessageComponentInterface extends MessageComponentInterface, WsServerInterface { |
||||
} |
@ -1,147 +0,0 @@
@@ -1,147 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet; |
||||
use Ratchet\Mock\ConnectionDecorator; |
||||
|
||||
/** |
||||
* @covers Ratchet\AbstractConnectionDecorator |
||||
* @covers Ratchet\ConnectionInterface |
||||
*/ |
||||
class AbstractConnectionDecoratorTest extends \PHPUnit_Framework_TestCase { |
||||
protected $mock; |
||||
protected $l1; |
||||
protected $l2; |
||||
|
||||
public function setUp() { |
||||
$this->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; |
||||
} |
||||
} |
@ -1,50 +0,0 @@
@@ -1,50 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Http; |
||||
|
||||
/** |
||||
* @covers Ratchet\Http\HttpRequestParser |
||||
*/ |
||||
class HttpRequestParserTest extends \PHPUnit_Framework_TestCase { |
||||
protected $parser; |
||||
|
||||
public function setUp() { |
||||
$this->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); |
||||
} |
||||
} |
@ -1,64 +0,0 @@
@@ -1,64 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Http; |
||||
use Ratchet\AbstractMessageComponentTestCase; |
||||
|
||||
/** |
||||
* @covers Ratchet\Http\HttpServer |
||||
*/ |
||||
class HttpServerTest extends AbstractMessageComponentTestCase { |
||||
public function setUp() { |
||||
parent::setUp(); |
||||
$this->_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"); |
||||
} |
||||
} |
@ -1,46 +0,0 @@
@@ -1,46 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Http; |
||||
use Ratchet\AbstractMessageComponentTestCase; |
||||
|
||||
/** |
||||
* @covers Ratchet\Http\OriginCheck |
||||
*/ |
||||
class OriginCheckTest extends AbstractMessageComponentTestCase { |
||||
protected $_reqStub; |
||||
|
||||
public function setUp() { |
||||
$this->_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!'); |
||||
} |
||||
} |
@ -1,143 +0,0 @@
@@ -1,143 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Http; |
||||
use Ratchet\WebSocket\WsServerInterface; |
||||
use Symfony\Component\Routing\Exception\ResourceNotFoundException; |
||||
use Symfony\Component\Routing\Matcher\UrlMatcherInterface; |
||||
|
||||
/** |
||||
* @covers Ratchet\Http\Router |
||||
*/ |
||||
class RouterTest extends \PHPUnit_Framework_TestCase { |
||||
protected $_router; |
||||
protected $_matcher; |
||||
protected $_conn; |
||||
protected $_uri; |
||||
protected $_req; |
||||
|
||||
public function setUp() { |
||||
$this->_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()); |
||||
} |
||||
} |
@ -1,26 +0,0 @@
@@ -1,26 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Server; |
||||
use Ratchet\Server\EchoServer; |
||||
|
||||
class EchoServerTest extends \PHPUnit_Framework_TestCase { |
||||
protected $_conn; |
||||
protected $_comp; |
||||
|
||||
public function setUp() { |
||||
$this->_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(); |
||||
} |
||||
} |
@ -1,152 +0,0 @@
@@ -1,152 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Application\Server; |
||||
use Ratchet\Server\FlashPolicy; |
||||
|
||||
/** |
||||
* @covers Ratchet\Server\FlashPolicy |
||||
*/ |
||||
class FlashPolicyTest extends \PHPUnit_Framework_TestCase { |
||||
|
||||
protected $_policy; |
||||
|
||||
public function setUp() { |
||||
$this->_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); |
||||
} |
||||
} |
@ -1,32 +0,0 @@
@@ -1,32 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Application\Server; |
||||
use Ratchet\Server\IoConnection; |
||||
|
||||
/** |
||||
* @covers Ratchet\Server\IoConnection |
||||
*/ |
||||
class IoConnectionTest extends \PHPUnit_Framework_TestCase { |
||||
protected $sock; |
||||
protected $conn; |
||||
|
||||
public function setUp() { |
||||
$this->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')); |
||||
} |
||||
} |
@ -1,118 +0,0 @@
@@ -1,118 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Server; |
||||
use Ratchet\Server\IoServer; |
||||
use React\EventLoop\StreamSelectLoop; |
||||
use React\Socket\Server; |
||||
|
||||
/** |
||||
* @covers Ratchet\Server\IoServer |
||||
*/ |
||||
class IoServerTest extends \PHPUnit_Framework_TestCase { |
||||
protected $server; |
||||
|
||||
protected $app; |
||||
|
||||
protected $port; |
||||
|
||||
protected $reactor; |
||||
|
||||
public function setUp() { |
||||
$this->app = $this->getMock('\\Ratchet\\MessageComponentInterface'); |
||||
|
||||
$loop = new StreamSelectLoop; |
||||
$this->reactor = new Server($loop); |
||||
$this->reactor->listen(0); |
||||
|
||||
$this->port = $this->reactor->getPort(); |
||||
$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->server->loop->tick(); |
||||
|
||||
//$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->server->loop->tick(); |
||||
|
||||
socket_write($client, $msg); |
||||
$this->server->loop->tick(); |
||||
|
||||
socket_shutdown($client, 1); |
||||
socket_shutdown($client, 0); |
||||
socket_close($client); |
||||
|
||||
$this->server->loop->tick(); |
||||
} |
||||
|
||||
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->server->loop->tick(); |
||||
|
||||
socket_shutdown($client, 1); |
||||
socket_shutdown($client, 0); |
||||
socket_close($client); |
||||
|
||||
$this->server->loop->tick(); |
||||
} |
||||
|
||||
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); |
||||
} |
||||
} |
@ -1,125 +0,0 @@
@@ -1,125 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Server; |
||||
use Ratchet\Server\IpBlackList; |
||||
|
||||
/** |
||||
* @covers Ratchet\Server\IpBlackList |
||||
*/ |
||||
class IpBlackListTest extends \PHPUnit_Framework_TestCase { |
||||
protected $blocker; |
||||
protected $mock; |
||||
|
||||
public function setUp() { |
||||
$this->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; |
||||
} |
||||
} |
@ -1,36 +0,0 @@
@@ -1,36 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Session\Serialize; |
||||
use Ratchet\Session\Serialize\PhpHandler; |
||||
|
||||
/** |
||||
* @covers Ratchet\Session\Serialize\PhpHandler |
||||
*/ |
||||
class PhpHandlerTest extends \PHPUnit_Framework_TestCase { |
||||
protected $_handler; |
||||
|
||||
public function setUp() { |
||||
$this->_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)); |
||||
} |
||||
} |
@ -1,124 +0,0 @@
@@ -1,124 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Session; |
||||
use Ratchet\AbstractMessageComponentTestCase; |
||||
use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler; |
||||
use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler; |
||||
|
||||
/** |
||||
* @covers Ratchet\Session\SessionProvider |
||||
* @covers Ratchet\Session\Storage\VirtualSessionStorage |
||||
* @covers Ratchet\Session\Storage\Proxy\VirtualProxy |
||||
*/ |
||||
class SessionProviderTest extends AbstractMessageComponentTestCase { |
||||
public function setUp() { |
||||
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); |
||||
} |
||||
} |
@ -1,53 +0,0 @@
@@ -1,53 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Session\Storage; |
||||
use Ratchet\Session\Serialize\PhpHandler; |
||||
use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; |
||||
use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; |
||||
use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler; |
||||
|
||||
class VirtualSessionStoragePDOTest extends \PHPUnit_Framework_TestCase { |
||||
/** |
||||
* @var VirtualSessionStorage |
||||
*/ |
||||
protected $_virtualSessionStorage; |
||||
|
||||
protected $_pathToDB; |
||||
|
||||
public function setUp() { |
||||
if (!extension_loaded('PDO') || !extension_loaded('pdo_sqlite')) { |
||||
return $this->markTestSkipped('Session test requires PDO and pdo_sqlite'); |
||||
} |
||||
|
||||
$schema = <<<SQL |
||||
CREATE TABLE `sessions` ( |
||||
`sess_id` VARBINARY(128) NOT NULL PRIMARY KEY, |
||||
`sess_data` BLOB NOT NULL, |
||||
`sess_time` INTEGER UNSIGNED NOT NULL, |
||||
`sess_lifetime` MEDIUMINT NOT NULL |
||||
); |
||||
SQL; |
||||
$this->_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()); |
||||
} |
||||
} |
@ -1,268 +0,0 @@
@@ -1,268 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Wamp; |
||||
use Ratchet\Mock\Connection; |
||||
use Ratchet\Mock\WampComponent as TestComponent; |
||||
|
||||
/** |
||||
* @covers Ratchet\Wamp\ServerProtocol |
||||
* @covers Ratchet\Wamp\WampServerInterface |
||||
* @covers Ratchet\Wamp\WampConnection |
||||
*/ |
||||
class ServerProtocolTest extends \PHPUnit_Framework_TestCase { |
||||
protected $_comp; |
||||
|
||||
protected $_app; |
||||
|
||||
public function setUp() { |
||||
$this->_app = new TestComponent; |
||||
$this->_comp = new ServerProtocol($this->_app); |
||||
} |
||||
|
||||
protected function newConn() { |
||||
return new Connection; |
||||
} |
||||
|
||||
public function invalidMessageProvider() { |
||||
return array( |
||||
array(0) |
||||
, array(3) |
||||
, array(4) |
||||
, array(8) |
||||
, array(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(array($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 array( |
||||
array(2, 'a', 'b') |
||||
, array(2, array('a', 'b')) |
||||
, array(1, 'one') |
||||
, array(3, 'one', 'two', 'three') |
||||
, array(3, array('un', 'deux', 'trois')) |
||||
, array(2, 'hi', array('hello', 'world')) |
||||
, array(2, array('hello', 'world'), 'hi') |
||||
, array(2, array('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(); |
||||
$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(); |
||||
$friend = uniqid(); |
||||
|
||||
$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); |
||||
} |
||||
} |
@ -1,229 +0,0 @@
@@ -1,229 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Wamp; |
||||
|
||||
/** |
||||
* @covers Ratchet\Wamp\TopicManager |
||||
*/ |
||||
class TopicManagerTest extends \PHPUnit_Framework_TestCase { |
||||
private $mock; |
||||
|
||||
/** |
||||
* @var \Ratchet\Wamp\TopicManager |
||||
*/ |
||||
private $mngr; |
||||
|
||||
/** |
||||
* @var \Ratchet\ConnectionInterface |
||||
*/ |
||||
private $conn; |
||||
|
||||
public function setUp() { |
||||
$this->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 array( |
||||
array(true, 'onClose', 0) |
||||
, array(true, 'onUnsubscribe', 0) |
||||
, array(false, 'onClose', 1) |
||||
, array(false, 'onUnsubscribe', 1) |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* @dataProvider topicConnExpectationProvider |
||||
*/ |
||||
public function testTopicRetentionFromLeavingConnections($autoDelete, $methodCall, $expectation) { |
||||
$topicName = 'checkTopic'; |
||||
list($topic, $attribute) = $this->topicProvider($topicName); |
||||
$topic->autoDelete = $autoDelete; |
||||
|
||||
$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()); |
||||
} |
||||
} |
@ -1,164 +0,0 @@
@@ -1,164 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Wamp; |
||||
|
||||
/** |
||||
* @covers Ratchet\Wamp\Topic |
||||
*/ |
||||
class TopicTest extends \PHPUnit_Framework_TestCase { |
||||
public function testGetId() { |
||||
$id = uniqid(); |
||||
$topic = new Topic($id); |
||||
|
||||
$this->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')); |
||||
} |
||||
} |
@ -1,77 +0,0 @@
@@ -1,77 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Wamp; |
||||
|
||||
/** |
||||
* @covers Ratchet\Wamp\WampConnection |
||||
*/ |
||||
class WampConnectionTest extends \PHPUnit_Framework_TestCase { |
||||
protected $conn; |
||||
protected $mock; |
||||
|
||||
public function setUp() { |
||||
$this->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(); |
||||
} |
||||
} |
@ -1,49 +0,0 @@
@@ -1,49 +0,0 @@
|
||||
<?php |
||||
namespace Ratchet\Wamp; |
||||
use Ratchet\AbstractMessageComponentTestCase; |
||||
|
||||
/** |
||||
* @covers Ratchet\Wamp\WampServer |
||||
*/ |
||||
class WampServerTest extends AbstractMessageComponentTestCase { |
||||
public function getConnectionClassString() { |
||||
return '\Ratchet\Wamp\WampConnection'; |
||||
} |
||||
|
||||
public function getDecoratorClassString() { |
||||
return 'Ratchet\Wamp\WampServer'; |
||||
} |
||||
|
||||
public function getComponentClassString() { |
||||
return '\Ratchet\Wamp\WampServerInterface'; |
||||
} |
||||
|
||||
public function testOnMessageToEvent() { |
||||
$published = 'Client published this message'; |
||||
|
||||
$this->_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'))); |
||||
} |
||||
} |
@ -1,445 +0,0 @@
@@ -1,445 +0,0 @@
|
||||
<?php |
||||
|
||||
/* |
||||
* This file is part of Composer. |
||||
* |
||||
* (c) Nils Adermann <naderman@naderman.de> |
||||
* Jordi Boggiano <j.boggiano@seld.be> |
||||
* |
||||
* For the full copyright and license information, please view the LICENSE |
||||
* file that was distributed with this source code. |
||||
*/ |
||||
|
||||
namespace Composer\Autoload; |
||||
|
||||
/** |
||||
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader. |
||||
* |
||||
* $loader = new \Composer\Autoload\ClassLoader(); |
||||
* |
||||
* // register classes with namespaces |
||||
* $loader->add('Symfony\Component', __DIR__.'/component'); |
||||
* $loader->add('Symfony', __DIR__.'/framework'); |
||||
* |
||||
* // activate the autoloader |
||||
* $loader->register(); |
||||
* |
||||
* // to enable searching the include path (eg. for PEAR packages) |
||||
* $loader->setUseIncludePath(true); |
||||
* |
||||
* In this example, if you try to use a class in the Symfony\Component |
||||
* namespace or one of its children (Symfony\Component\Console for instance), |
||||
* the autoloader will first look for the class under the component/ |
||||
* directory, and it will then fallback to the framework/ directory if not |
||||
* found before giving up. |
||||
* |
||||
* This class is loosely based on the Symfony UniversalClassLoader. |
||||
* |
||||
* @author Fabien Potencier <fabien@symfony.com> |
||||
* @author Jordi Boggiano <j.boggiano@seld.be> |
||||
* @see http://www.php-fig.org/psr/psr-0/ |
||||
* @see http://www.php-fig.org/psr/psr-4/ |
||||
*/ |
||||
class ClassLoader |
||||
{ |
||||
// PSR-4 |
||||
private $prefixLengthsPsr4 = array(); |
||||
private $prefixDirsPsr4 = array(); |
||||
private $fallbackDirsPsr4 = array(); |
||||
|
||||
// PSR-0 |
||||
private $prefixesPsr0 = array(); |
||||
private $fallbackDirsPsr0 = array(); |
||||
|
||||
private $useIncludePath = false; |
||||
private $classMap = array(); |
||||
private $classMapAuthoritative = false; |
||||
private $missingClasses = array(); |
||||
private $apcuPrefix; |
||||
|
||||
public function getPrefixes() |
||||
{ |
||||
if (!empty($this->prefixesPsr0)) { |
||||
return call_user_func_array('array_merge', $this->prefixesPsr0); |
||||
} |
||||
|
||||
return array(); |
||||
} |
||||
|
||||
public function getPrefixesPsr4() |
||||
{ |
||||
return $this->prefixDirsPsr4; |
||||
} |
||||
|
||||
public function getFallbackDirs() |
||||
{ |
||||
return $this->fallbackDirsPsr0; |
||||
} |
||||
|
||||
public function getFallbackDirsPsr4() |
||||
{ |
||||
return $this->fallbackDirsPsr4; |
||||
} |
||||
|
||||
public function getClassMap() |
||||
{ |
||||
return $this->classMap; |
||||
} |
||||
|
||||
/** |
||||
* @param array $classMap Class to filename map |
||||
*/ |
||||
public function addClassMap(array $classMap) |
||||
{ |
||||
if ($this->classMap) { |
||||
$this->classMap = array_merge($this->classMap, $classMap); |
||||
} else { |
||||
$this->classMap = $classMap; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Registers a set of PSR-0 directories for a given prefix, either |
||||
* appending or prepending to the ones previously set for this prefix. |
||||
* |
||||
* @param string $prefix The prefix |
||||
* @param array|string $paths The PSR-0 root directories |
||||
* @param bool $prepend Whether to prepend the directories |
||||
*/ |
||||
public function add($prefix, $paths, $prepend = false) |
||||
{ |
||||
if (!$prefix) { |
||||
if ($prepend) { |
||||
$this->fallbackDirsPsr0 = array_merge( |
||||
(array) $paths, |
||||
$this->fallbackDirsPsr0 |
||||
); |
||||
} else { |
||||
$this->fallbackDirsPsr0 = array_merge( |
||||
$this->fallbackDirsPsr0, |
||||
(array) $paths |
||||
); |
||||
} |
||||
|
||||
return; |
||||
} |
||||
|
||||
$first = $prefix[0]; |
||||
if (!isset($this->prefixesPsr0[$first][$prefix])) { |
||||
$this->prefixesPsr0[$first][$prefix] = (array) $paths; |
||||
|
||||
return; |
||||
} |
||||
if ($prepend) { |
||||
$this->prefixesPsr0[$first][$prefix] = array_merge( |
||||
(array) $paths, |
||||
$this->prefixesPsr0[$first][$prefix] |
||||
); |
||||
} else { |
||||
$this->prefixesPsr0[$first][$prefix] = array_merge( |
||||
$this->prefixesPsr0[$first][$prefix], |
||||
(array) $paths |
||||
); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Registers a set of PSR-4 directories for a given namespace, either |
||||
* appending or prepending to the ones previously set for this namespace. |
||||
* |
||||
* @param string $prefix The prefix/namespace, with trailing '\\' |
||||
* @param array|string $paths The PSR-4 base directories |
||||
* @param bool $prepend Whether to prepend the directories |
||||
* |
||||
* @throws \InvalidArgumentException |
||||
*/ |
||||
public function addPsr4($prefix, $paths, $prepend = false) |
||||
{ |
||||
if (!$prefix) { |
||||
// Register directories for the root namespace. |
||||
if ($prepend) { |
||||
$this->fallbackDirsPsr4 = array_merge( |
||||
(array) $paths, |
||||
$this->fallbackDirsPsr4 |
||||
); |
||||
} else { |
||||
$this->fallbackDirsPsr4 = array_merge( |
||||
$this->fallbackDirsPsr4, |
||||
(array) $paths |
||||
); |
||||
} |
||||
} elseif (!isset($this->prefixDirsPsr4[$prefix])) { |
||||
// Register directories for a new namespace. |
||||
$length = strlen($prefix); |
||||
if ('\\' !== $prefix[$length - 1]) { |
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); |
||||
} |
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; |
||||
$this->prefixDirsPsr4[$prefix] = (array) $paths; |
||||
} elseif ($prepend) { |
||||
// Prepend directories for an already registered namespace. |
||||
$this->prefixDirsPsr4[$prefix] = array_merge( |
||||
(array) $paths, |
||||
$this->prefixDirsPsr4[$prefix] |
||||
); |
||||
} else { |
||||
// Append directories for an already registered namespace. |
||||
$this->prefixDirsPsr4[$prefix] = array_merge( |
||||
$this->prefixDirsPsr4[$prefix], |
||||
(array) $paths |
||||
); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Registers a set of PSR-0 directories for a given prefix, |
||||
* replacing any others previously set for this prefix. |
||||
* |
||||
* @param string $prefix The prefix |
||||
* @param array|string $paths The PSR-0 base directories |
||||
*/ |
||||
public function set($prefix, $paths) |
||||
{ |
||||
if (!$prefix) { |
||||
$this->fallbackDirsPsr0 = (array) $paths; |
||||
} else { |
||||
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Registers a set of PSR-4 directories for a given namespace, |
||||
* replacing any others previously set for this namespace. |
||||
* |
||||
* @param string $prefix The prefix/namespace, with trailing '\\' |
||||
* @param array|string $paths The PSR-4 base directories |
||||
* |
||||
* @throws \InvalidArgumentException |
||||
*/ |
||||
public function setPsr4($prefix, $paths) |
||||
{ |
||||
if (!$prefix) { |
||||
$this->fallbackDirsPsr4 = (array) $paths; |
||||
} else { |
||||
$length = strlen($prefix); |
||||
if ('\\' !== $prefix[$length - 1]) { |
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); |
||||
} |
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; |
||||
$this->prefixDirsPsr4[$prefix] = (array) $paths; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Turns on searching the include path for class files. |
||||
* |
||||
* @param bool $useIncludePath |
||||
*/ |
||||
public function setUseIncludePath($useIncludePath) |
||||
{ |
||||
$this->useIncludePath = $useIncludePath; |
||||
} |
||||
|
||||
/** |
||||
* Can be used to check if the autoloader uses the include path to check |
||||
* for classes. |
||||
* |
||||
* @return bool |
||||
*/ |
||||
public function getUseIncludePath() |
||||
{ |
||||
return $this->useIncludePath; |
||||
} |
||||
|
||||
/** |
||||
* Turns off searching the prefix and fallback directories for classes |
||||
* that have not been registered with the class map. |
||||
* |
||||
* @param bool $classMapAuthoritative |
||||
*/ |
||||
public function setClassMapAuthoritative($classMapAuthoritative) |
||||
{ |
||||
$this->classMapAuthoritative = $classMapAuthoritative; |
||||
} |
||||
|
||||
/** |
||||
* Should class lookup fail if not found in the current class map? |
||||
* |
||||
* @return bool |
||||
*/ |
||||
public function isClassMapAuthoritative() |
||||
{ |
||||
return $this->classMapAuthoritative; |
||||
} |
||||
|
||||
/** |
||||
* APCu prefix to use to cache found/not-found classes, if the extension is enabled. |
||||
* |
||||
* @param string|null $apcuPrefix |
||||
*/ |
||||
public function setApcuPrefix($apcuPrefix) |
||||
{ |
||||
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; |
||||
} |
||||
|
||||
/** |
||||
* The APCu prefix in use, or null if APCu caching is not enabled. |
||||
* |
||||
* @return string|null |
||||
*/ |
||||
public function getApcuPrefix() |
||||
{ |
||||
return $this->apcuPrefix; |
||||
} |
||||
|
||||
/** |
||||
* Registers this instance as an autoloader. |
||||
* |
||||
* @param bool $prepend Whether to prepend the autoloader or not |
||||
*/ |
||||
public function register($prepend = false) |
||||
{ |
||||
spl_autoload_register(array($this, 'loadClass'), true, $prepend); |
||||
} |
||||
|
||||
/** |
||||
* Unregisters this instance as an autoloader. |
||||
*/ |
||||
public function unregister() |
||||
{ |
||||
spl_autoload_unregister(array($this, 'loadClass')); |
||||
} |
||||
|
||||
/** |
||||
* Loads the given class or interface. |
||||
* |
||||
* @param string $class The name of the class |
||||
* @return bool|null True if loaded, null otherwise |
||||
*/ |
||||
public function loadClass($class) |
||||
{ |
||||
if ($file = $this->findFile($class)) { |
||||
includeFile($file); |
||||
|
||||
return true; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Finds the path to the file where the class is defined. |
||||
* |
||||
* @param string $class The name of the class |
||||
* |
||||
* @return string|false The path if found, false otherwise |
||||
*/ |
||||
public function findFile($class) |
||||
{ |
||||
// class map lookup |
||||
if (isset($this->classMap[$class])) { |
||||
return $this->classMap[$class]; |
||||
} |
||||
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { |
||||
return false; |
||||
} |
||||
if (null !== $this->apcuPrefix) { |
||||
$file = apcu_fetch($this->apcuPrefix.$class, $hit); |
||||
if ($hit) { |
||||
return $file; |
||||
} |
||||
} |
||||
|
||||
$file = $this->findFileWithExtension($class, '.php'); |
||||
|
||||
// Search for Hack files if we are running on HHVM |
||||
if (false === $file && defined('HHVM_VERSION')) { |
||||
$file = $this->findFileWithExtension($class, '.hh'); |
||||
} |
||||
|
||||
if (null !== $this->apcuPrefix) { |
||||
apcu_add($this->apcuPrefix.$class, $file); |
||||
} |
||||
|
||||
if (false === $file) { |
||||
// Remember that this class does not exist. |
||||
$this->missingClasses[$class] = true; |
||||
} |
||||
|
||||
return $file; |
||||
} |
||||
|
||||
private function findFileWithExtension($class, $ext) |
||||
{ |
||||
// PSR-4 lookup |
||||
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; |
||||
|
||||
$first = $class[0]; |
||||
if (isset($this->prefixLengthsPsr4[$first])) { |
||||
$subPath = $class; |
||||
while (false !== $lastPos = strrpos($subPath, '\\')) { |
||||
$subPath = substr($subPath, 0, $lastPos); |
||||
$search = $subPath . '\\'; |
||||
if (isset($this->prefixDirsPsr4[$search])) { |
||||
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); |
||||
foreach ($this->prefixDirsPsr4[$search] as $dir) { |
||||
if (file_exists($file = $dir . $pathEnd)) { |
||||
return $file; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
// PSR-4 fallback dirs |
||||
foreach ($this->fallbackDirsPsr4 as $dir) { |
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { |
||||
return $file; |
||||
} |
||||
} |
||||
|
||||
// PSR-0 lookup |
||||
if (false !== $pos = strrpos($class, '\\')) { |
||||
// namespaced class name |
||||
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) |
||||
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); |
||||
} else { |
||||
// PEAR-like class name |
||||
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; |
||||
} |
||||
|
||||
if (isset($this->prefixesPsr0[$first])) { |
||||
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { |
||||
if (0 === strpos($class, $prefix)) { |
||||
foreach ($dirs as $dir) { |
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { |
||||
return $file; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
// PSR-0 fallback dirs |
||||
foreach ($this->fallbackDirsPsr0 as $dir) { |
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { |
||||
return $file; |
||||
} |
||||
} |
||||
|
||||
// PSR-0 include paths. |
||||
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { |
||||
return $file; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Scope isolated include. |
||||
* |
||||
* Prevents access to $this/self from included files. |
||||
*/ |
||||
function includeFile($file) |
||||
{ |
||||
include $file; |
||||
} |
@ -1,21 +0,0 @@
@@ -1,21 +0,0 @@
|
||||
|
||||
Copyright (c) Nils Adermann, Jordi Boggiano |
||||
|
||||
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. |
||||
|
@ -1,16 +0,0 @@
@@ -1,16 +0,0 @@
|
||||
<?php |
||||
|
||||
// autoload_classmap.php @generated by Composer |
||||
|
||||
$vendorDir = dirname(dirname(__FILE__)); |
||||
$baseDir = dirname($vendorDir); |
||||
|
||||
return array( |
||||
'ArithmeticError' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/ArithmeticError.php', |
||||
'AssertionError' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/AssertionError.php', |
||||
'DivisionByZeroError' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/DivisionByZeroError.php', |
||||
'Error' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/Error.php', |
||||
'ParseError' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/ParseError.php', |
||||
'SessionUpdateTimestampHandlerInterface' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/SessionUpdateTimestampHandlerInterface.php', |
||||
'TypeError' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/TypeError.php', |
||||
); |
@ -1,14 +0,0 @@
@@ -1,14 +0,0 @@
|
||||
<?php |
||||
|
||||
// autoload_files.php @generated by Composer |
||||
|
||||
$vendorDir = dirname(dirname(__FILE__)); |
||||
$baseDir = dirname($vendorDir); |
||||
|
||||
return array( |
||||
'ad155f8f1cf0d418fe49e248db8c661b' => $vendorDir . '/react/promise/src/functions_include.php', |
||||
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php', |
||||
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php', |
||||
'023d27dca8066ef29e6739335ea73bad' => $vendorDir . '/symfony/polyfill-php70/bootstrap.php', |
||||
'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php', |
||||
); |
@ -1,10 +0,0 @@
@@ -1,10 +0,0 @@
|
||||
<?php |
||||
|
||||
// autoload_namespaces.php @generated by Composer |
||||
|
||||
$vendorDir = dirname(dirname(__FILE__)); |
||||
$baseDir = dirname($vendorDir); |
||||
|
||||
return array( |
||||
'Evenement' => array($vendorDir . '/evenement/evenement/src'), |
||||
); |
@ -1,22 +0,0 @@
@@ -1,22 +0,0 @@
|
||||
<?php |
||||
|
||||
// autoload_psr4.php @generated by Composer |
||||
|
||||
$vendorDir = dirname(dirname(__FILE__)); |
||||
$baseDir = dirname($vendorDir); |
||||
|
||||
return array( |
||||
'Symfony\\Polyfill\\Php70\\' => array($vendorDir . '/symfony/polyfill-php70'), |
||||
'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'), |
||||
'Symfony\\Component\\Routing\\' => array($vendorDir . '/symfony/routing'), |
||||
'Symfony\\Component\\HttpFoundation\\' => array($vendorDir . '/symfony/http-foundation'), |
||||
'React\\Stream\\' => array($vendorDir . '/react/stream/src'), |
||||
'React\\Socket\\' => array($vendorDir . '/react/socket/src'), |
||||
'React\\Promise\\' => array($vendorDir . '/react/promise/src'), |
||||
'React\\EventLoop\\' => array($vendorDir . '/react/event-loop/src'), |
||||
'Ratchet\\RFC6455\\' => array($vendorDir . '/ratchet/rfc6455/src'), |
||||
'Ratchet\\' => array($vendorDir . '/cboden/ratchet/src/Ratchet'), |
||||
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'), |
||||
'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'), |
||||
'Amir\\' => array($baseDir . '/bin/amir'), |
||||
); |
@ -1,70 +0,0 @@
@@ -1,70 +0,0 @@
|
||||
<?php |
||||
|
||||
// autoload_real.php @generated by Composer |
||||
|
||||
class ComposerAutoloaderInita3d708ca3bb0f3f4e817238e4fb57153 |
||||
{ |
||||
private static $loader; |
||||
|
||||
public static function loadClassLoader($class) |
||||
{ |
||||
if ('Composer\Autoload\ClassLoader' === $class) { |
||||
require __DIR__ . '/ClassLoader.php'; |
||||
} |
||||
} |
||||
|
||||
public static function getLoader() |
||||
{ |
||||
if (null !== self::$loader) { |
||||
return self::$loader; |
||||
} |
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInita3d708ca3bb0f3f4e817238e4fb57153', 'loadClassLoader'), true, true); |
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(); |
||||
spl_autoload_unregister(array('ComposerAutoloaderInita3d708ca3bb0f3f4e817238e4fb57153', 'loadClassLoader')); |
||||
|
||||
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); |
||||
if ($useStaticLoader) { |
||||
require_once __DIR__ . '/autoload_static.php'; |
||||
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInita3d708ca3bb0f3f4e817238e4fb57153::getInitializer($loader)); |
||||
} else { |
||||
$map = require __DIR__ . '/autoload_namespaces.php'; |
||||
foreach ($map as $namespace => $path) { |
||||
$loader->set($namespace, $path); |
||||
} |
||||
|
||||
$map = require __DIR__ . '/autoload_psr4.php'; |
||||
foreach ($map as $namespace => $path) { |
||||
$loader->setPsr4($namespace, $path); |
||||
} |
||||
|
||||
$classMap = require __DIR__ . '/autoload_classmap.php'; |
||||
if ($classMap) { |
||||
$loader->addClassMap($classMap); |
||||
} |
||||
} |
||||
|
||||
$loader->register(true); |
||||
|
||||
if ($useStaticLoader) { |
||||
$includeFiles = Composer\Autoload\ComposerStaticInita3d708ca3bb0f3f4e817238e4fb57153::$files; |
||||
} else { |
||||
$includeFiles = require __DIR__ . '/autoload_files.php'; |
||||
} |
||||
foreach ($includeFiles as $fileIdentifier => $file) { |
||||
composerRequirea3d708ca3bb0f3f4e817238e4fb57153($fileIdentifier, $file); |
||||
} |
||||
|
||||
return $loader; |
||||
} |
||||
} |
||||
|
||||
function composerRequirea3d708ca3bb0f3f4e817238e4fb57153($fileIdentifier, $file) |
||||
{ |
||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { |
||||
require $file; |
||||
|
||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; |
||||
} |
||||
} |
@ -1,133 +0,0 @@
@@ -1,133 +0,0 @@
|
||||
<?php |
||||
|
||||
// autoload_static.php @generated by Composer |
||||
|
||||
namespace Composer\Autoload; |
||||
|
||||
class ComposerStaticInita3d708ca3bb0f3f4e817238e4fb57153 |
||||
{ |
||||
public static $files = array ( |
||||
'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php', |
||||
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php', |
||||
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php', |
||||
'023d27dca8066ef29e6739335ea73bad' => __DIR__ . '/..' . '/symfony/polyfill-php70/bootstrap.php', |
||||
'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php', |
||||
); |
||||
|
||||
public static $prefixLengthsPsr4 = array ( |
||||
'S' => |
||||
array ( |
||||
'Symfony\\Polyfill\\Php70\\' => 23, |
||||
'Symfony\\Polyfill\\Mbstring\\' => 26, |
||||
'Symfony\\Component\\Routing\\' => 26, |
||||
'Symfony\\Component\\HttpFoundation\\' => 33, |
||||
), |
||||
'R' => |
||||
array ( |
||||
'React\\Stream\\' => 13, |
||||
'React\\Socket\\' => 13, |
||||
'React\\Promise\\' => 14, |
||||
'React\\EventLoop\\' => 16, |
||||
'Ratchet\\RFC6455\\' => 16, |
||||
'Ratchet\\' => 8, |
||||
), |
||||
'P' => |
||||
array ( |
||||
'Psr\\Http\\Message\\' => 17, |
||||
), |
||||
'G' => |
||||
array ( |
||||
'GuzzleHttp\\Psr7\\' => 16, |
||||
), |
||||
'A' => |
||||
array ( |
||||
'Amir\\' => 5, |
||||
), |
||||
); |
||||
|
||||
public static $prefixDirsPsr4 = array ( |
||||
'Symfony\\Polyfill\\Php70\\' => |
||||
array ( |
||||
0 => __DIR__ . '/..' . '/symfony/polyfill-php70', |
||||
), |
||||
'Symfony\\Polyfill\\Mbstring\\' => |
||||
array ( |
||||
0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring', |
||||
), |
||||
'Symfony\\Component\\Routing\\' => |
||||
array ( |
||||
0 => __DIR__ . '/..' . '/symfony/routing', |
||||
), |
||||
'Symfony\\Component\\HttpFoundation\\' => |
||||
array ( |
||||
0 => __DIR__ . '/..' . '/symfony/http-foundation', |
||||
), |
||||
'React\\Stream\\' => |
||||
array ( |
||||
0 => __DIR__ . '/..' . '/react/stream/src', |
||||
), |
||||
'React\\Socket\\' => |
||||
array ( |
||||
0 => __DIR__ . '/..' . '/react/socket/src', |
||||
), |
||||
'React\\Promise\\' => |
||||
array ( |
||||
0 => __DIR__ . '/..' . '/react/promise/src', |
||||
), |
||||
'React\\EventLoop\\' => |
||||
array ( |
||||
0 => __DIR__ . '/..' . '/react/event-loop/src', |
||||
), |
||||
'Ratchet\\RFC6455\\' => |
||||
array ( |
||||
0 => __DIR__ . '/..' . '/ratchet/rfc6455/src', |
||||
), |
||||
'Ratchet\\' => |
||||
array ( |
||||
0 => __DIR__ . '/..' . '/cboden/ratchet/src/Ratchet', |
||||
), |
||||
'Psr\\Http\\Message\\' => |
||||
array ( |
||||
0 => __DIR__ . '/..' . '/psr/http-message/src', |
||||
), |
||||
'GuzzleHttp\\Psr7\\' => |
||||
array ( |
||||
0 => __DIR__ . '/..' . '/guzzlehttp/psr7/src', |
||||
), |
||||
'Amir\\' => |
||||
array ( |
||||
0 => __DIR__ . '/../..' . '/bin/amir', |
||||
), |
||||
); |
||||
|
||||
public static $prefixesPsr0 = array ( |
||||
'E' => |
||||
array ( |
||||
'Evenement' => |
||||
array ( |
||||
0 => __DIR__ . '/..' . '/evenement/evenement/src', |
||||
), |
||||
), |
||||
); |
||||
|
||||
public static $classMap = array ( |
||||
'ArithmeticError' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/ArithmeticError.php', |
||||
'AssertionError' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/AssertionError.php', |
||||
'DivisionByZeroError' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/DivisionByZeroError.php', |
||||
'Error' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/Error.php', |
||||
'ParseError' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/ParseError.php', |
||||
'SessionUpdateTimestampHandlerInterface' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/SessionUpdateTimestampHandlerInterface.php', |
||||
'TypeError' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/TypeError.php', |
||||
); |
||||
|
||||
public static function getInitializer(ClassLoader $loader) |
||||
{ |
||||
return \Closure::bind(function () use ($loader) { |
||||
$loader->prefixLengthsPsr4 = ComposerStaticInita3d708ca3bb0f3f4e817238e4fb57153::$prefixLengthsPsr4; |
||||
$loader->prefixDirsPsr4 = ComposerStaticInita3d708ca3bb0f3f4e817238e4fb57153::$prefixDirsPsr4; |
||||
$loader->prefixesPsr0 = ComposerStaticInita3d708ca3bb0f3f4e817238e4fb57153::$prefixesPsr0; |
||||
$loader->classMap = ComposerStaticInita3d708ca3bb0f3f4e817238e4fb57153::$classMap; |
||||
|
||||
}, null, ClassLoader::class); |
||||
} |
||||
} |
@ -1,810 +0,0 @@
@@ -1,810 +0,0 @@
|
||||
[ |
||||
{ |
||||
"name": "cboden/ratchet", |
||||
"version": "0.4.x-dev", |
||||
"version_normalized": "0.4.9999999.9999999-dev", |
||||
"source": { |
||||
"type": "git", |
||||
"url": "https://github.com/ratchetphp/Ratchet.git", |
||||
"reference": "a78c8d2ddff78aef1d05cbf08e8bdcf8c21e1b14" |
||||
}, |
||||
"dist": { |
||||
"type": "zip", |
||||
"url": "https://api.github.com/repos/ratchetphp/Ratchet/zipball/a78c8d2ddff78aef1d05cbf08e8bdcf8c21e1b14", |
||||
"reference": "a78c8d2ddff78aef1d05cbf08e8bdcf8c21e1b14", |
||||
"shasum": "" |
||||
}, |
||||
"require": { |
||||
"guzzlehttp/psr7": "^1.0", |
||||
"php": ">=5.4.2", |
||||
"ratchet/rfc6455": "^0.2", |
||||
"react/socket": "^0.3 || ^0.4", |
||||
"symfony/http-foundation": "^2.2|^3.0", |
||||
"symfony/routing": "^2.2|^3.0" |
||||
}, |
||||
"suggest": { |
||||
"ext-pecl_http": "^2.0" |
||||
}, |
||||
"time": "2016-06-06T13:13:02+00:00", |
||||
"type": "library", |
||||
"installation-source": "dist", |
||||
"autoload": { |
||||
"psr-4": { |
||||
"Ratchet\\": "src/Ratchet" |
||||
} |
||||
}, |
||||
"notification-url": "https://packagist.org/downloads/", |
||||
"license": [ |
||||
"MIT" |
||||
], |
||||
"authors": [ |
||||
{ |
||||
"name": "Chris Boden", |
||||
"email": "cboden@gmail.com", |
||||
"role": "Developer" |
||||
} |
||||
], |
||||
"description": "PHP WebSocket library", |
||||
"homepage": "http://socketo.me", |
||||
"keywords": [ |
||||
"Ratchet", |
||||
"WebSockets", |
||||
"server", |
||||
"sockets", |
||||
"websocket" |
||||
] |
||||
}, |
||||
{ |
||||
"name": "evenement/evenement", |
||||
"version": "v2.1.0", |
||||
"version_normalized": "2.1.0.0", |
||||
"source": { |
||||
"type": "git", |
||||
"url": "https://github.com/igorw/evenement.git", |
||||
"reference": "6ba9a777870ab49f417e703229d53931ed40fd7a" |
||||
}, |
||||
"dist": { |
||||
"type": "zip", |
||||
"url": "https://api.github.com/repos/igorw/evenement/zipball/6ba9a777870ab49f417e703229d53931ed40fd7a", |
||||
"reference": "6ba9a777870ab49f417e703229d53931ed40fd7a", |
||||
"shasum": "" |
||||
}, |
||||
"require": { |
||||
"php": ">=5.4.0" |
||||
}, |
||||
"require-dev": { |
||||
"phpunit/phpunit": "^6.0||^5.7||^4.8.35" |
||||
}, |
||||
"time": "2017-07-17T17:39:19+00:00", |
||||
"type": "library", |
||||
"extra": { |
||||
"branch-alias": { |
||||
"dev-master": "2.0-dev" |
||||
} |
||||
}, |
||||
"installation-source": "dist", |
||||
"autoload": { |
||||
"psr-0": { |
||||
"Evenement": "src" |
||||
} |
||||
}, |
||||
"notification-url": "https://packagist.org/downloads/", |
||||
"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" |
||||
] |
||||
}, |
||||
{ |
||||
"name": "guzzlehttp/psr7", |
||||
"version": "1.6.1", |
||||
"version_normalized": "1.6.1.0", |
||||
"source": { |
||||
"type": "git", |
||||
"url": "https://github.com/guzzle/psr7.git", |
||||
"reference": "239400de7a173fe9901b9ac7c06497751f00727a" |
||||
}, |
||||
"dist": { |
||||
"type": "zip", |
||||
"url": "https://api.github.com/repos/guzzle/psr7/zipball/239400de7a173fe9901b9ac7c06497751f00727a", |
||||
"reference": "239400de7a173fe9901b9ac7c06497751f00727a", |
||||
"shasum": "" |
||||
}, |
||||
"require": { |
||||
"php": ">=5.4.0", |
||||
"psr/http-message": "~1.0", |
||||
"ralouphie/getallheaders": "^2.0.5 || ^3.0.0" |
||||
}, |
||||
"provide": { |
||||
"psr/http-message-implementation": "1.0" |
||||
}, |
||||
"require-dev": { |
||||
"ext-zlib": "*", |
||||
"phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8" |
||||
}, |
||||
"suggest": { |
||||
"zendframework/zend-httphandlerrunner": "Emit PSR-7 responses" |
||||
}, |
||||
"time": "2019-07-01T23:21:34+00:00", |
||||
"type": "library", |
||||
"extra": { |
||||
"branch-alias": { |
||||
"dev-master": "1.6-dev" |
||||
} |
||||
}, |
||||
"installation-source": "dist", |
||||
"autoload": { |
||||
"psr-4": { |
||||
"GuzzleHttp\\Psr7\\": "src/" |
||||
}, |
||||
"files": [ |
||||
"src/functions_include.php" |
||||
] |
||||
}, |
||||
"notification-url": "https://packagist.org/downloads/", |
||||
"license": [ |
||||
"MIT" |
||||
], |
||||
"authors": [ |
||||
{ |
||||
"name": "Michael Dowling", |
||||
"email": "mtdowling@gmail.com", |
||||
"homepage": "https://github.com/mtdowling" |
||||
}, |
||||
{ |
||||
"name": "Tobias Schultze", |
||||
"homepage": "https://github.com/Tobion" |
||||
} |
||||
], |
||||
"description": "PSR-7 message implementation that also provides common utility methods", |
||||
"keywords": [ |
||||
"http", |
||||
"message", |
||||
"psr-7", |
||||
"request", |
||||
"response", |
||||
"stream", |
||||
"uri", |
||||
"url" |
||||
] |
||||
}, |
||||
{ |
||||
"name": "paragonie/random_compat", |
||||
"version": "v9.99.99", |
||||
"version_normalized": "9.99.99.0", |
||||
"source": { |
||||
"type": "git", |
||||
"url": "https://github.com/paragonie/random_compat.git", |
||||
"reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95" |
||||
}, |
||||
"dist": { |
||||
"type": "zip", |
||||
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", |
||||
"reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", |
||||
"shasum": "" |
||||
}, |
||||
"require": { |
||||
"php": "^7" |
||||
}, |
||||
"require-dev": { |
||||
"phpunit/phpunit": "4.*|5.*", |
||||
"vimeo/psalm": "^1" |
||||
}, |
||||
"suggest": { |
||||
"ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." |
||||
}, |
||||
"time": "2018-07-02T15:55:56+00:00", |
||||
"type": "library", |
||||
"installation-source": "dist", |
||||
"notification-url": "https://packagist.org/downloads/", |
||||
"license": [ |
||||
"MIT" |
||||
], |
||||
"authors": [ |
||||
{ |
||||
"name": "Paragon Initiative Enterprises", |
||||
"email": "security@paragonie.com", |
||||
"homepage": "https://paragonie.com" |
||||
} |
||||
], |
||||
"description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", |
||||
"keywords": [ |
||||
"csprng", |
||||
"polyfill", |
||||
"pseudorandom", |
||||
"random" |
||||
] |
||||
}, |
||||
{ |
||||
"name": "psr/http-message", |
||||
"version": "1.0.1", |
||||
"version_normalized": "1.0.1.0", |
||||
"source": { |
||||
"type": "git", |
||||
"url": "https://github.com/php-fig/http-message.git", |
||||
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" |
||||
}, |
||||
"dist": { |
||||
"type": "zip", |
||||
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", |
||||
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", |
||||
"shasum": "" |
||||
}, |
||||
"require": { |
||||
"php": ">=5.3.0" |
||||
}, |
||||
"time": "2016-08-06T14:39:51+00:00", |
||||
"type": "library", |
||||
"extra": { |
||||
"branch-alias": { |
||||
"dev-master": "1.0.x-dev" |
||||
} |
||||
}, |
||||
"installation-source": "dist", |
||||
"autoload": { |
||||
"psr-4": { |
||||
"Psr\\Http\\Message\\": "src/" |
||||
} |
||||
}, |
||||
"notification-url": "https://packagist.org/downloads/", |
||||
"license": [ |
||||
"MIT" |
||||
], |
||||
"authors": [ |
||||
{ |
||||
"name": "PHP-FIG", |
||||
"homepage": "http://www.php-fig.org/" |
||||
} |
||||
], |
||||
"description": "Common interface for HTTP messages", |
||||
"homepage": "https://github.com/php-fig/http-message", |
||||
"keywords": [ |
||||
"http", |
||||
"http-message", |
||||
"psr", |
||||
"psr-7", |
||||
"request", |
||||
"response" |
||||
] |
||||
}, |
||||
{ |
||||
"name": "ralouphie/getallheaders", |
||||
"version": "3.0.3", |
||||
"version_normalized": "3.0.3.0", |
||||
"source": { |
||||
"type": "git", |
||||
"url": "https://github.com/ralouphie/getallheaders.git", |
||||
"reference": "120b605dfeb996808c31b6477290a714d356e822" |
||||
}, |
||||
"dist": { |
||||
"type": "zip", |
||||
"url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", |
||||
"reference": "120b605dfeb996808c31b6477290a714d356e822", |
||||
"shasum": "" |
||||
}, |
||||
"require": { |
||||
"php": ">=5.6" |
||||
}, |
||||
"require-dev": { |
||||
"php-coveralls/php-coveralls": "^2.1", |
||||
"phpunit/phpunit": "^5 || ^6.5" |
||||
}, |
||||
"time": "2019-03-08T08:55:37+00:00", |
||||
"type": "library", |
||||
"installation-source": "dist", |
||||
"autoload": { |
||||
"files": [ |
||||
"src/getallheaders.php" |
||||
] |
||||
}, |
||||
"notification-url": "https://packagist.org/downloads/", |
||||
"license": [ |
||||
"MIT" |
||||
], |
||||
"authors": [ |
||||
{ |
||||
"name": "Ralph Khattar", |
||||
"email": "ralph.khattar@gmail.com" |
||||
} |
||||
], |
||||
"description": "A polyfill for getallheaders." |
||||
}, |
||||
{ |
||||
"name": "ratchet/rfc6455", |
||||
"version": "v0.2.5", |
||||
"version_normalized": "0.2.5.0", |
||||
"source": { |
||||
"type": "git", |
||||
"url": "https://github.com/ratchetphp/RFC6455.git", |
||||
"reference": "c62f7cd95ffbb6e94fd657be694fc7372ecd6e62" |
||||
}, |
||||
"dist": { |
||||
"type": "zip", |
||||
"url": "https://api.github.com/repos/ratchetphp/RFC6455/zipball/c62f7cd95ffbb6e94fd657be694fc7372ecd6e62", |
||||
"reference": "c62f7cd95ffbb6e94fd657be694fc7372ecd6e62", |
||||
"shasum": "" |
||||
}, |
||||
"require": { |
||||
"guzzlehttp/psr7": "^1.0", |
||||
"php": ">=5.4.2" |
||||
}, |
||||
"require-dev": { |
||||
"phpunit/phpunit": "4.8.*", |
||||
"react/http": "^0.4.1", |
||||
"react/socket-client": "^0.4.3" |
||||
}, |
||||
"time": "2019-03-10T17:10:42+00:00", |
||||
"type": "library", |
||||
"installation-source": "dist", |
||||
"autoload": { |
||||
"psr-4": { |
||||
"Ratchet\\RFC6455\\": "src" |
||||
} |
||||
}, |
||||
"notification-url": "https://packagist.org/downloads/", |
||||
"license": [ |
||||
"MIT" |
||||
], |
||||
"authors": [ |
||||
{ |
||||
"name": "Chris Boden", |
||||
"email": "cboden@gmail.com", |
||||
"role": "Developer" |
||||
} |
||||
], |
||||
"description": "RFC6455 WebSocket protocol handler", |
||||
"homepage": "http://socketo.me", |
||||
"keywords": [ |
||||
"WebSockets", |
||||
"rfc6455", |
||||
"websocket" |
||||
] |
||||
}, |
||||
{ |
||||
"name": "react/event-loop", |
||||
"version": "v0.4.3", |
||||
"version_normalized": "0.4.3.0", |
||||
"source": { |
||||
"type": "git", |
||||
"url": "https://github.com/reactphp/event-loop.git", |
||||
"reference": "8bde03488ee897dc6bb3d91e4e17c353f9c5252f" |
||||
}, |
||||
"dist": { |
||||
"type": "zip", |
||||
"url": "https://api.github.com/repos/reactphp/event-loop/zipball/8bde03488ee897dc6bb3d91e4e17c353f9c5252f", |
||||
"reference": "8bde03488ee897dc6bb3d91e4e17c353f9c5252f", |
||||
"shasum": "" |
||||
}, |
||||
"require": { |
||||
"php": ">=5.4.0" |
||||
}, |
||||
"require-dev": { |
||||
"phpunit/phpunit": "~4.8" |
||||
}, |
||||
"suggest": { |
||||
"ext-event": "~1.0", |
||||
"ext-libev": "*", |
||||
"ext-libevent": ">=0.1.0" |
||||
}, |
||||
"time": "2017-04-27T10:56:23+00:00", |
||||
"type": "library", |
||||
"installation-source": "dist", |
||||
"autoload": { |
||||
"psr-4": { |
||||
"React\\EventLoop\\": "src" |
||||
} |
||||
}, |
||||
"notification-url": "https://packagist.org/downloads/", |
||||
"license": [ |
||||
"MIT" |
||||
], |
||||
"description": "Event loop abstraction layer that libraries can use for evented I/O.", |
||||
"keywords": [ |
||||
"asynchronous", |
||||
"event-loop" |
||||
] |
||||
}, |
||||
{ |
||||
"name": "react/promise", |
||||
"version": "v2.7.1", |
||||
"version_normalized": "2.7.1.0", |
||||
"source": { |
||||
"type": "git", |
||||
"url": "https://github.com/reactphp/promise.git", |
||||
"reference": "31ffa96f8d2ed0341a57848cbb84d88b89dd664d" |
||||
}, |
||||
"dist": { |
||||
"type": "zip", |
||||
"url": "https://api.github.com/repos/reactphp/promise/zipball/31ffa96f8d2ed0341a57848cbb84d88b89dd664d", |
||||
"reference": "31ffa96f8d2ed0341a57848cbb84d88b89dd664d", |
||||
"shasum": "" |
||||
}, |
||||
"require": { |
||||
"php": ">=5.4.0" |
||||
}, |
||||
"require-dev": { |
||||
"phpunit/phpunit": "~4.8" |
||||
}, |
||||
"time": "2019-01-07T21:25:54+00:00", |
||||
"type": "library", |
||||
"installation-source": "dist", |
||||
"autoload": { |
||||
"psr-4": { |
||||
"React\\Promise\\": "src/" |
||||
}, |
||||
"files": [ |
||||
"src/functions_include.php" |
||||
] |
||||
}, |
||||
"notification-url": "https://packagist.org/downloads/", |
||||
"license": [ |
||||
"MIT" |
||||
], |
||||
"authors": [ |
||||
{ |
||||
"name": "Jan Sorgalla", |
||||
"email": "jsorgalla@gmail.com" |
||||
} |
||||
], |
||||
"description": "A lightweight implementation of CommonJS Promises/A for PHP", |
||||
"keywords": [ |
||||
"promise", |
||||
"promises" |
||||
] |
||||
}, |
||||
{ |
||||
"name": "react/socket", |
||||
"version": "v0.4.6", |
||||
"version_normalized": "0.4.6.0", |
||||
"source": { |
||||
"type": "git", |
||||
"url": "https://github.com/reactphp/socket.git", |
||||
"reference": "cf074e53c974df52388ebd09710a9018894745d2" |
||||
}, |
||||
"dist": { |
||||
"type": "zip", |
||||
"url": "https://api.github.com/repos/reactphp/socket/zipball/cf074e53c974df52388ebd09710a9018894745d2", |
||||
"reference": "cf074e53c974df52388ebd09710a9018894745d2", |
||||
"shasum": "" |
||||
}, |
||||
"require": { |
||||
"evenement/evenement": "~2.0|~1.0", |
||||
"php": ">=5.3.0", |
||||
"react/event-loop": "0.4.*|0.3.*", |
||||
"react/promise": "^2.0 || ^1.1", |
||||
"react/stream": "^0.4.5" |
||||
}, |
||||
"require-dev": { |
||||
"clue/block-react": "^1.1", |
||||
"phpunit/phpunit": "~4.8", |
||||
"react/socket-client": "^0.5.1" |
||||
}, |
||||
"time": "2017-01-26T09:23:38+00:00", |
||||
"type": "library", |
||||
"installation-source": "dist", |
||||
"autoload": { |
||||
"psr-4": { |
||||
"React\\Socket\\": "src" |
||||
} |
||||
}, |
||||
"notification-url": "https://packagist.org/downloads/", |
||||
"license": [ |
||||
"MIT" |
||||
], |
||||
"description": "Async, streaming plaintext TCP/IP and secure TLS socket server for React PHP", |
||||
"keywords": [ |
||||
"Socket" |
||||
] |
||||
}, |
||||
{ |
||||
"name": "react/stream", |
||||
"version": "v0.4.6", |
||||
"version_normalized": "0.4.6.0", |
||||
"source": { |
||||
"type": "git", |
||||
"url": "https://github.com/reactphp/stream.git", |
||||
"reference": "44dc7f51ea48624110136b535b9ba44fd7d0c1ee" |
||||
}, |
||||
"dist": { |
||||
"type": "zip", |
||||
"url": "https://api.github.com/repos/reactphp/stream/zipball/44dc7f51ea48624110136b535b9ba44fd7d0c1ee", |
||||
"reference": "44dc7f51ea48624110136b535b9ba44fd7d0c1ee", |
||||
"shasum": "" |
||||
}, |
||||
"require": { |
||||
"evenement/evenement": "^2.0|^1.0", |
||||
"php": ">=5.3.8" |
||||
}, |
||||
"require-dev": { |
||||
"clue/stream-filter": "~1.2", |
||||
"react/event-loop": "^0.4|^0.3", |
||||
"react/promise": "^2.0|^1.0" |
||||
}, |
||||
"suggest": { |
||||
"react/event-loop": "^0.4", |
||||
"react/promise": "^2.0" |
||||
}, |
||||
"time": "2017-01-25T14:44:14+00:00", |
||||
"type": "library", |
||||
"installation-source": "dist", |
||||
"autoload": { |
||||
"psr-4": { |
||||
"React\\Stream\\": "src" |
||||
} |
||||
}, |
||||
"notification-url": "https://packagist.org/downloads/", |
||||
"license": [ |
||||
"MIT" |
||||
], |
||||
"description": "Basic readable and writable stream interfaces that support piping.", |
||||
"keywords": [ |
||||
"pipe", |
||||
"stream" |
||||
] |
||||
}, |
||||
{ |
||||
"name": "symfony/http-foundation", |
||||
"version": "v3.4.36", |
||||
"version_normalized": "3.4.36.0", |
||||
"source": { |
||||
"type": "git", |
||||
"url": "https://github.com/symfony/http-foundation.git", |
||||
"reference": "d2d0cfe8e319d9df44c4cca570710fcf221d4593" |
||||
}, |
||||
"dist": { |
||||
"type": "zip", |
||||
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/d2d0cfe8e319d9df44c4cca570710fcf221d4593", |
||||
"reference": "d2d0cfe8e319d9df44c4cca570710fcf221d4593", |
||||
"shasum": "" |
||||
}, |
||||
"require": { |
||||
"php": "^5.5.9|>=7.0.8", |
||||
"symfony/polyfill-mbstring": "~1.1", |
||||
"symfony/polyfill-php70": "~1.6" |
||||
}, |
||||
"require-dev": { |
||||
"symfony/expression-language": "~2.8|~3.0|~4.0" |
||||
}, |
||||
"time": "2019-11-28T12:52:59+00:00", |
||||
"type": "library", |
||||
"extra": { |
||||
"branch-alias": { |
||||
"dev-master": "3.4-dev" |
||||
} |
||||
}, |
||||
"installation-source": "dist", |
||||
"autoload": { |
||||
"psr-4": { |
||||
"Symfony\\Component\\HttpFoundation\\": "" |
||||
}, |
||||
"exclude-from-classmap": [ |
||||
"/Tests/" |
||||
] |
||||
}, |
||||
"notification-url": "https://packagist.org/downloads/", |
||||
"license": [ |
||||
"MIT" |
||||
], |
||||
"authors": [ |
||||
{ |
||||
"name": "Fabien Potencier", |
||||
"email": "fabien@symfony.com" |
||||
}, |
||||
{ |
||||
"name": "Symfony Community", |
||||
"homepage": "https://symfony.com/contributors" |
||||
} |
||||
], |
||||
"description": "Symfony HttpFoundation Component", |
||||
"homepage": "https://symfony.com" |
||||
}, |
||||
{ |
||||
"name": "symfony/polyfill-mbstring", |
||||
"version": "v1.13.1", |
||||
"version_normalized": "1.13.1.0", |
||||
"source": { |
||||
"type": "git", |
||||
"url": "https://github.com/symfony/polyfill-mbstring.git", |
||||
"reference": "7b4aab9743c30be783b73de055d24a39cf4b954f" |
||||
}, |
||||
"dist": { |
||||
"type": "zip", |
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/7b4aab9743c30be783b73de055d24a39cf4b954f", |
||||
"reference": "7b4aab9743c30be783b73de055d24a39cf4b954f", |
||||
"shasum": "" |
||||
}, |
||||
"require": { |
||||
"php": ">=5.3.3" |
||||
}, |
||||
"suggest": { |
||||
"ext-mbstring": "For best performance" |
||||
}, |
||||
"time": "2019-11-27T14:18:11+00:00", |
||||
"type": "library", |
||||
"extra": { |
||||
"branch-alias": { |
||||
"dev-master": "1.13-dev" |
||||
} |
||||
}, |
||||
"installation-source": "dist", |
||||
"autoload": { |
||||
"psr-4": { |
||||
"Symfony\\Polyfill\\Mbstring\\": "" |
||||
}, |
||||
"files": [ |
||||
"bootstrap.php" |
||||
] |
||||
}, |
||||
"notification-url": "https://packagist.org/downloads/", |
||||
"license": [ |
||||
"MIT" |
||||
], |
||||
"authors": [ |
||||
{ |
||||
"name": "Nicolas Grekas", |
||||
"email": "p@tchwork.com" |
||||
}, |
||||
{ |
||||
"name": "Symfony Community", |
||||
"homepage": "https://symfony.com/contributors" |
||||
} |
||||
], |
||||
"description": "Symfony polyfill for the Mbstring extension", |
||||
"homepage": "https://symfony.com", |
||||
"keywords": [ |
||||
"compatibility", |
||||
"mbstring", |
||||
"polyfill", |
||||
"portable", |
||||
"shim" |
||||
] |
||||
}, |
||||
{ |
||||
"name": "symfony/polyfill-php70", |
||||
"version": "v1.13.1", |
||||
"version_normalized": "1.13.1.0", |
||||
"source": { |
||||
"type": "git", |
||||
"url": "https://github.com/symfony/polyfill-php70.git", |
||||
"reference": "af23c7bb26a73b850840823662dda371484926c4" |
||||
}, |
||||
"dist": { |
||||
"type": "zip", |
||||
"url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/af23c7bb26a73b850840823662dda371484926c4", |
||||
"reference": "af23c7bb26a73b850840823662dda371484926c4", |
||||
"shasum": "" |
||||
}, |
||||
"require": { |
||||
"paragonie/random_compat": "~1.0|~2.0|~9.99", |
||||
"php": ">=5.3.3" |
||||
}, |
||||
"time": "2019-11-27T13:56:44+00:00", |
||||
"type": "library", |
||||
"extra": { |
||||
"branch-alias": { |
||||
"dev-master": "1.13-dev" |
||||
} |
||||
}, |
||||
"installation-source": "dist", |
||||
"autoload": { |
||||
"psr-4": { |
||||
"Symfony\\Polyfill\\Php70\\": "" |
||||
}, |
||||
"files": [ |
||||
"bootstrap.php" |
||||
], |
||||
"classmap": [ |
||||
"Resources/stubs" |
||||
] |
||||
}, |
||||
"notification-url": "https://packagist.org/downloads/", |
||||
"license": [ |
||||
"MIT" |
||||
], |
||||
"authors": [ |
||||
{ |
||||
"name": "Nicolas Grekas", |
||||
"email": "p@tchwork.com" |
||||
}, |
||||
{ |
||||
"name": "Symfony Community", |
||||
"homepage": "https://symfony.com/contributors" |
||||
} |
||||
], |
||||
"description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions", |
||||
"homepage": "https://symfony.com", |
||||
"keywords": [ |
||||
"compatibility", |
||||
"polyfill", |
||||
"portable", |
||||
"shim" |
||||
] |
||||
}, |
||||
{ |
||||
"name": "symfony/routing", |
||||
"version": "v3.4.36", |
||||
"version_normalized": "3.4.36.0", |
||||
"source": { |
||||
"type": "git", |
||||
"url": "https://github.com/symfony/routing.git", |
||||
"reference": "b689ccd48e234ea404806d94b07eeb45f9f6f06a" |
||||
}, |
||||
"dist": { |
||||
"type": "zip", |
||||
"url": "https://api.github.com/repos/symfony/routing/zipball/b689ccd48e234ea404806d94b07eeb45f9f6f06a", |
||||
"reference": "b689ccd48e234ea404806d94b07eeb45f9f6f06a", |
||||
"shasum": "" |
||||
}, |
||||
"require": { |
||||
"php": "^5.5.9|>=7.0.8" |
||||
}, |
||||
"conflict": { |
||||
"symfony/config": "<3.3.1", |
||||
"symfony/dependency-injection": "<3.3", |
||||
"symfony/yaml": "<3.4" |
||||
}, |
||||
"require-dev": { |
||||
"doctrine/annotations": "~1.0", |
||||
"psr/log": "~1.0", |
||||
"symfony/config": "^3.3.1|~4.0", |
||||
"symfony/dependency-injection": "~3.3|~4.0", |
||||
"symfony/expression-language": "~2.8|~3.0|~4.0", |
||||
"symfony/http-foundation": "~2.8|~3.0|~4.0", |
||||
"symfony/yaml": "~3.4|~4.0" |
||||
}, |
||||
"suggest": { |
||||
"doctrine/annotations": "For using the annotation loader", |
||||
"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": "2019-12-01T08:33:36+00:00", |
||||
"type": "library", |
||||
"extra": { |
||||
"branch-alias": { |
||||
"dev-master": "3.4-dev" |
||||
} |
||||
}, |
||||
"installation-source": "dist", |
||||
"autoload": { |
||||
"psr-4": { |
||||
"Symfony\\Component\\Routing\\": "" |
||||
}, |
||||
"exclude-from-classmap": [ |
||||
"/Tests/" |
||||
] |
||||
}, |
||||
"notification-url": "https://packagist.org/downloads/", |
||||
"license": [ |
||||
"MIT" |
||||
], |
||||
"authors": [ |
||||
{ |
||||
"name": "Fabien Potencier", |
||||
"email": "fabien@symfony.com" |
||||
}, |
||||
{ |
||||
"name": "Symfony Community", |
||||
"homepage": "https://symfony.com/contributors" |
||||
} |
||||
], |
||||
"description": "Symfony Routing Component", |
||||
"homepage": "https://symfony.com", |
||||
"keywords": [ |
||||
"router", |
||||
"routing", |
||||
"uri", |
||||
"url" |
||||
] |
||||
} |
||||
] |
@ -1,2 +0,0 @@
@@ -1,2 +0,0 @@
|
||||
composer.lock |
||||
vendor |
@ -1,26 +0,0 @@
@@ -1,26 +0,0 @@
|
||||
language: php |
||||
|
||||
php: |
||||
- 5.4 |
||||
- 5.5 |
||||
- 5.6 |
||||
- 7.0 |
||||
- 7.1 |
||||
- hhvm |
||||
- nightly |
||||
|
||||
matrix: |
||||
allow_failures: |
||||
- php: hhvm |
||||
- php: nightly |
||||
|
||||
before_script: |
||||
- wget http://getcomposer.org/composer.phar |
||||
- php composer.phar install |
||||
|
||||
script: |
||||
- ./vendor/bin/phpunit --coverage-text |
||||
- php -n examples/benchmark-emit-no-arguments.php |
||||
- php -n examples/benchmark-emit-one-argument.php |
||||
- php -n examples/benchmark-emit.php |
||||
- php -n examples/benchmark-emit-once.php |
@ -1,8 +0,0 @@
@@ -1,8 +0,0 @@
|
||||
CHANGELOG |
||||
========= |
||||
|
||||
* 2.0.0 (2012-11-02) |
||||
|
||||
* Require PHP >=5.4.0 |
||||
* Added EventEmitterTrait |
||||
* Removed EventEmitter2 |
@ -1,19 +0,0 @@
@@ -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. |
@ -1,83 +0,0 @@
@@ -1,83 +0,0 @@
|
||||
# Événement |
||||
|
||||
Événement is a very simple event dispatching library for PHP. |
||||
|
||||
It has the same design goals as [Silex](http://silex-project.org) and |
||||
[Pimple](http://pimple-project.org), to empower the user while staying concise |
||||
and simple. |
||||
|
||||
It is very strongly inspired by the EventEmitter API found in |
||||
[node.js](http://nodejs.org). |
||||
|
||||
[](http://travis-ci.org/igorw/evenement) |
||||
|
||||
## Fetch |
||||
|
||||
The recommended way to install Événement is [through composer](http://getcomposer.org). |
||||
|
||||
Just create a composer.json file for your project: |
||||
|
||||
```JSON |
||||
{ |
||||
"require": { |
||||
"evenement/evenement": "2.0.*" |
||||
} |
||||
} |
||||
``` |
||||
|
||||
**Note:** The `2.0.*` version of Événement requires PHP 5.4. If you are |
||||
using PHP 5.3, please use the `1.0.*` version: |
||||
|
||||
```JSON |
||||
{ |
||||
"require": { |
||||
"evenement/evenement": "1.0.*" |
||||
} |
||||
} |
||||
``` |
||||
|
||||
And run these two commands to install it: |
||||
|
||||
$ curl -s http://getcomposer.org/installer | php |
||||
$ php composer.phar install |
||||
|
||||
Now you can add the autoloader, and you will have access to the library: |
||||
|
||||
```php |
||||
<?php |
||||
require 'vendor/autoload.php'; |
||||
``` |
||||
|
||||
## Usage |
||||
|
||||
### Creating an Emitter |
||||
|
||||
```php |
||||
<?php |
||||
$emitter = new Evenement\EventEmitter(); |
||||
``` |
||||
|
||||
### Adding Listeners |
||||
|
||||
```php |
||||
<?php |
||||
$emitter->on('user.created', function (User $user) use ($logger) { |
||||
$logger->log(sprintf("User '%s' was created.", $user->getLogin())); |
||||
}); |
||||
``` |
||||
|
||||
### Emitting Events |
||||
|
||||
```php |
||||
<?php |
||||
$emitter->emit('user.created', array($user)); |
||||
``` |
||||
|
||||
Tests |
||||
----- |
||||
|
||||
$ phpunit |
||||
|
||||
License |
||||
------- |
||||
MIT, see LICENSE. |
@ -1,34 +0,0 @@
@@ -1,34 +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": ">=5.4.0" |
||||
}, |
||||
"require-dev": { |
||||
"phpunit/phpunit": "^6.0||^5.7||^4.8.35" |
||||
}, |
||||
"autoload": { |
||||
"psr-0": { |
||||
"Evenement": "src" |
||||
} |
||||
}, |
||||
"autoload-dev": { |
||||
"psr-0": { |
||||
"Evenement": "tests" |
||||
}, |
||||
"files": ["tests/Evenement/Tests/functions.php"] |
||||
}, |
||||
"extra": { |
||||
"branch-alias": { |
||||
"dev-master": "2.0-dev" |
||||
} |
||||
} |
||||
} |
@ -1,24 +0,0 @@
@@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
||||
<phpunit backupGlobals="false" |
||||
backupStaticAttributes="false" |
||||
colors="true" |
||||
convertErrorsToExceptions="true" |
||||
convertNoticesToExceptions="true" |
||||
convertWarningsToExceptions="true" |
||||
processIsolation="false" |
||||
stopOnFailure="false" |
||||
syntaxCheck="false" |
||||
> |
||||
<testsuites> |
||||
<testsuite name="Evenement Test Suite"> |
||||
<directory>./tests/Evenement/</directory> |
||||
</testsuite> |
||||
</testsuites> |
||||
|
||||
<filter> |
||||
<whitelist> |
||||
<directory>./src/</directory> |
||||
</whitelist> |
||||
</filter> |
||||
</phpunit> |
@ -1,17 +0,0 @@
@@ -1,17 +0,0 @@
|
||||
<?php |
||||
|
||||
/* |
||||
* This file is part of Evenement. |
||||
* |
||||
* (c) Igor Wiedler <igor@wiedler.ch> |
||||
* |
||||
* 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; |
||||
} |
@ -1,22 +0,0 @@
@@ -1,22 +0,0 @@
|
||||
<?php |
||||
|
||||
/* |
||||
* This file is part of Evenement. |
||||
* |
||||
* (c) Igor Wiedler <igor@wiedler.ch> |
||||
* |
||||
* 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); |
||||
public function emit($event, array $arguments = []); |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue