Skip to content

Commit

Permalink
Merge branch 'channel-classes' of https://github.com/tonysm/framework
Browse files Browse the repository at this point in the history
…into tonysm-channel-classes
  • Loading branch information
taylorotwell committed Jan 3, 2018
2 parents 7472b1d + 5190646 commit 66d1ffd
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 4 deletions.
46 changes: 42 additions & 4 deletions src/Illuminate/Broadcasting/Broadcasters/Broadcaster.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ abstract class Broadcaster implements BroadcasterContract
* Register a channel authenticator.
*
* @param string $channel
* @param callable $callback
* @param callable|string $callback
* @return $this
*/
public function channel($channel, callable $callback)
public function channel($channel, $callback)
{
$this->channels[$channel] = $callback;

Expand All @@ -56,8 +56,9 @@ protected function verifyUserCanAccessChannel($request, $channel)
}

$parameters = $this->extractAuthParameters($pattern, $channel, $callback);
$handler = $this->normalizeChannelHandlerToCallable($callback);

if ($result = $callback($request->user(), ...$parameters)) {
if ($result = $handler($request->user(), ...$parameters)) {
return $this->validAuthenticationResponse($request, $result);
}
}
Expand All @@ -75,7 +76,7 @@ protected function verifyUserCanAccessChannel($request, $channel)
*/
protected function extractAuthParameters($pattern, $channel, $callback)
{
$callbackParameters = (new ReflectionFunction($callback))->getParameters();
$callbackParameters = $this->extractParameters($callback);

return collect($this->extractChannelKeys($pattern, $channel))->reject(function ($value, $key) {
return is_numeric($key);
Expand All @@ -84,6 +85,28 @@ protected function extractAuthParameters($pattern, $channel, $callback)
})->values()->all();
}

/**
* Extracts the parameters out of what the user passed to handle the channel authentication.
*
* @param callable|string $callback
* @return \ReflectionParameter[]
* @throws \Exception
*/
protected function extractParameters($callback)
{
if (is_callable($callback)) {
return (new ReflectionFunction($callback))->getParameters();
}

if (is_string($callback)) {
return (new \ReflectionClass($callback))
->getMethod('join')
->getParameters();
}

throw new \Exception('Unknown channel handler type.');
}

/**
* Extract the channel keys from the incoming channel name.
*
Expand Down Expand Up @@ -201,4 +224,19 @@ protected function binder()

return $this->bindingRegistrar;
}

/**
* @param $callback
* @return callable|\Closure
*/
protected function normalizeChannelHandlerToCallable($callback)
{
return is_callable($callback)
? $callback
: function (...$args) use ($callback) {
return Container::getInstance()
->make($callback)
->join(...$args);
};
}
}
50 changes: 50 additions & 0 deletions src/Illuminate/Foundation/Console/ChannelMakeCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

namespace Illuminate\Foundation\Console;

use Illuminate\Console\GeneratorCommand;

class ChannelMakeCommand extends GeneratorCommand
{
/**
* The console command name.
*
* @var string
*/
protected $name = 'make:channel';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Create a new channel class';

/**
* The type of class being generated.
*
* @var string
*/
protected $type = 'Broadcasting Channel';

/**
* Get the stub file for the generator.
*
* @return string
*/
protected function getStub()
{
return __DIR__.'/stubs/channel.stub';
}

/**
* Get the default namespace for the class.
*
* @param string $rootNamespace
* @return string
*/
protected function getDefaultNamespace($rootNamespace)
{
return $rootNamespace.'\Broadcasting';
}
}
26 changes: 26 additions & 0 deletions src/Illuminate/Foundation/Console/stubs/channel.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace DummyNamespace;

class DummyClass
{
/**
* Create a new broadcasting channel instance.
*
* @return void
*/
public function __construct()
{
//
}

/**
* Authenticates the channel.
*
* @return mixed
*/
public function join()
{
//
}
}
14 changes: 14 additions & 0 deletions src/Illuminate/Foundation/Providers/ArtisanServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
use Illuminate\Foundation\Console\RouteCacheCommand;
use Illuminate\Foundation\Console\RouteClearCommand;
use Illuminate\Console\Scheduling\ScheduleRunCommand;
use Illuminate\Foundation\Console\ChannelMakeCommand;
use Illuminate\Foundation\Console\ConfigCacheCommand;
use Illuminate\Foundation\Console\ConfigClearCommand;
use Illuminate\Foundation\Console\ConsoleMakeCommand;
Expand Down Expand Up @@ -127,6 +128,7 @@ class ArtisanServiceProvider extends ServiceProvider
'AppName' => 'command.app.name',
'AuthMake' => 'command.auth.make',
'CacheTable' => 'command.cache.table',
'ChannelMake' => 'command.channel.make',
'ConsoleMake' => 'command.console.make',
'ControllerMake' => 'command.controller.make',
'EventGenerate' => 'command.event.generate',
Expand Down Expand Up @@ -398,6 +400,18 @@ protected function registerJobMakeCommand()
});
}

/**
* Register the command.
*
* @return void
*/
protected function registerChannelMakeCommand()
{
$this->app->singleton('command.channel.make', function ($app) {
return new ChannelMakeCommand($app['files']);
});
}

/**
* Register the command.
*
Expand Down
36 changes: 36 additions & 0 deletions tests/Broadcasting/BroadcasterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,34 @@ public function testExtractingParametersWhileCheckingForUserAccess()
Container::setInstance(new Container);
}

public function testCanUseChannelClasses()
{
$broadcaster = new FakeBroadcaster;

$parameters = $broadcaster->extractAuthParameters('asd.{model}.{nonModel}', 'asd.1.something', DummyBroadcastingChannel::class);
$this->assertEquals(['model.1.instance', 'something'], $parameters);
}

/**
* @expectedException \Exception
* @expectedExceptionMessage Unknown channel handler type.
*/
public function testUnknownChannelAuthHandlerTypeThrowsException()
{
$broadcaster = new FakeBroadcaster;

$broadcaster->extractAuthParameters('asd.{model}.{nonModel}', 'asd.1.something', 123);
}

public function testCanRegisterChannelsAsClasses()
{
$broadcaster = new FakeBroadcaster;

$broadcaster->channel('something', function () {
});
$broadcaster->channel('somethingelse', DummyBroadcastingChannel::class);
}

/**
* @expectedException \Symfony\Component\HttpKernel\Exception\HttpException
* @expectedExceptionMessage
Expand Down Expand Up @@ -129,3 +157,11 @@ public function first()
//
}
}

class DummyBroadcastingChannel
{
public function join($user, BroadcasterTestEloquentModelStub $model, $nonModel)
{
//
}
}

0 comments on commit 66d1ffd

Please sign in to comment.