PusherBroadcaster.php 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. <?php
  2. namespace Illuminate\Broadcasting\Broadcasters;
  3. use Pusher\Pusher;
  4. use Illuminate\Support\Arr;
  5. use Illuminate\Support\Str;
  6. use Illuminate\Broadcasting\BroadcastException;
  7. use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
  8. class PusherBroadcaster extends Broadcaster
  9. {
  10. /**
  11. * The Pusher SDK instance.
  12. *
  13. * @var \Pusher\Pusher
  14. */
  15. protected $pusher;
  16. /**
  17. * Create a new broadcaster instance.
  18. *
  19. * @param \Pusher\Pusher $pusher
  20. * @return void
  21. */
  22. public function __construct(Pusher $pusher)
  23. {
  24. $this->pusher = $pusher;
  25. }
  26. /**
  27. * Authenticate the incoming request for a given channel.
  28. *
  29. * @param \Illuminate\Http\Request $request
  30. * @return mixed
  31. * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
  32. */
  33. public function auth($request)
  34. {
  35. if (Str::startsWith($request->channel_name, ['private-', 'presence-']) &&
  36. ! $request->user()) {
  37. throw new AccessDeniedHttpException;
  38. }
  39. $channelName = Str::startsWith($request->channel_name, 'private-')
  40. ? Str::replaceFirst('private-', '', $request->channel_name)
  41. : Str::replaceFirst('presence-', '', $request->channel_name);
  42. return parent::verifyUserCanAccessChannel(
  43. $request, $channelName
  44. );
  45. }
  46. /**
  47. * Return the valid authentication response.
  48. *
  49. * @param \Illuminate\Http\Request $request
  50. * @param mixed $result
  51. * @return mixed
  52. */
  53. public function validAuthenticationResponse($request, $result)
  54. {
  55. if (Str::startsWith($request->channel_name, 'private')) {
  56. return $this->decodePusherResponse(
  57. $request, $this->pusher->socket_auth($request->channel_name, $request->socket_id)
  58. );
  59. }
  60. return $this->decodePusherResponse(
  61. $request,
  62. $this->pusher->presence_auth(
  63. $request->channel_name, $request->socket_id,
  64. $request->user()->getAuthIdentifier(), $result
  65. )
  66. );
  67. }
  68. /**
  69. * Decode the given Pusher response.
  70. *
  71. * @param \Illuminate\Http\Request $request
  72. * @param mixed $response
  73. * @return array
  74. */
  75. protected function decodePusherResponse($request, $response)
  76. {
  77. if (! $request->callback) {
  78. return json_decode($response, true);
  79. }
  80. return response()->json(json_decode($response, true))
  81. ->withCallback($request->callback);
  82. }
  83. /**
  84. * Broadcast the given event.
  85. *
  86. * @param array $channels
  87. * @param string $event
  88. * @param array $payload
  89. * @return void
  90. */
  91. public function broadcast(array $channels, $event, array $payload = [])
  92. {
  93. $socket = Arr::pull($payload, 'socket');
  94. $response = $this->pusher->trigger(
  95. $this->formatChannels($channels), $event, $payload, $socket, true
  96. );
  97. if ((is_array($response) && $response['status'] >= 200 && $response['status'] <= 299)
  98. || $response === true) {
  99. return;
  100. }
  101. throw new BroadcastException(
  102. is_bool($response) ? 'Failed to connect to Pusher.' : $response['body']
  103. );
  104. }
  105. /**
  106. * Get the Pusher SDK instance.
  107. *
  108. * @return \Pusher\Pusher
  109. */
  110. public function getPusher()
  111. {
  112. return $this->pusher;
  113. }
  114. }