Skip to content

Commit 8673f60

Browse files
author
Jon Elverkilde
authored
Merge pull request #298 from pusher/async
Async
2 parents e402b83 + 50ca264 commit 8673f60

File tree

7 files changed

+550
-21
lines changed

7 files changed

+550
-21
lines changed

.github/workflows/release.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ jobs:
6363
- name: Prepare README
6464
run: |
6565
export MAJOR=$(echo "${{ env.VERSION }}" | cut -d'.' -f1)
66-
sed -i "s|\"pusher/pusher-php-server\": \"^[0-9]*\.0\"|\"pusher/pusher-php-server\": \"^${MAJOR}.0\"|" README.md
66+
export MINOR=$(echo "${{ env.VERSION }}" | cut -d'.' -f2)
67+
sed -i "s|\"pusher/pusher-php-server\": \"^[0-9]*\.[0-9]*\"|\"pusher/pusher-php-server\": \"^${MAJOR}.${MINOR}\"|" README.md
6768
- name: Prepare Pusher.php
6869
run: |
6970
sed -i "s|public static \$VERSION = '[^']*'|public static \$VERSION = '${{ env.VERSION }}'|" src/Pusher.php

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## 6.1.0
4+
5+
* [ADDED] triggerAsync and triggerBatchAsync using the Guzzle async interface.
6+
37
## 6.0.1
48

59
* [CHANGED] Use type hints where possible (mixed type not available in PHP7).

README.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Or add to `composer.json`:
1818

1919
```json
2020
"require": {
21-
"pusher/pusher-php-server": "^6.0"
21+
"pusher/pusher-php-server": "^6.1"
2222
}
2323
```
2424

@@ -132,6 +132,24 @@ $batch[] = array('channel' => 'my-channel', 'name' => 'my_event', 'data' => arra
132132
$pusher->triggerBatch($batch);
133133
```
134134

135+
### Asynchronous interface
136+
137+
Both `trigger` and `triggerBatch` have asynchronous counterparts in
138+
`triggerAsync` and `triggerBatchAsync`. These functions return [Guzzle
139+
promises](https://github.com/guzzle/promises) which can be chained
140+
with `->then`:
141+
142+
```php
143+
$promise = $pusher->triggerAsync( [ 'channel-1', 'channel-2' ], 'my_event', 'hello world' );
144+
145+
$promise->then(function ($result) {
146+
// do something with $result
147+
return $result;
148+
});
149+
150+
$final_result = $promise->wait();
151+
```
152+
135153
### Arrays
136154

137155
Objects are automatically converted to JSON format:

src/Pusher.php

Lines changed: 142 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
use Psr\Log\LoggerAwareTrait;
77
use Psr\Log\LoggerInterface;
88
use Psr\Log\LogLevel;
9+
use GuzzleHttp\Psr7\Request;
10+
use GuzzleHttp\Promise\PromiseInterface;
911

1012
class Pusher implements LoggerAwareInterface, PusherInterface
1113
{
@@ -14,7 +16,7 @@ class Pusher implements LoggerAwareInterface, PusherInterface
1416
/**
1517
* @var string Version
1618
*/
17-
public static $VERSION = '6.0.1';
19+
public static $VERSION = '6.1.0';
1820

1921
/**
2022
* @var null|PusherCrypto
@@ -326,8 +328,8 @@ public static function array_implode($glue, $separator, $array)
326328
}
327329

328330
/**
329-
* Trigger an event by providing event name and payload.
330-
* Optionally provide a socket ID to exclude a client (most likely the sender).
331+
* Helper function to prepare trigger request. Takes the same
332+
* parameters as the public trigger functions.
331333
*
332334
* @param array|string $channels A channel name or an array of channel names to publish the event on.
333335
* @param string $event
@@ -340,7 +342,7 @@ public static function array_implode($glue, $separator, $array)
340342
* @throws GuzzleException
341343
*
342344
*/
343-
public function trigger($channels, $event, $data, $params = array(), $already_encoded = false) : object
345+
public function make_request($channels, $event, $data, $params = array(), $already_encoded = false) : Request
344346
{
345347
if (is_string($channels) === true) {
346348
$channels = array($channels);
@@ -355,6 +357,7 @@ public function trigger($channels, $event, $data, $params = array(), $already_en
355357
foreach ($channels as $chan) {
356358
if (PusherCrypto::is_encrypted_channel($chan)) {
357359
$has_encrypted_channel = true;
360+
break;
358361
}
359362
}
360363

@@ -400,10 +403,33 @@ public function trigger($channels, $event, $data, $params = array(), $already_en
400403
'X-Pusher-Library' => 'pusher-http-php '.self::$VERSION
401404
];
402405

403-
$response = $this->client->post($path, [
404-
'query' => array_merge($signature, $query_params),
405-
'headers' => $headers,
406-
'body' => $post_value,
406+
$params = array_merge($signature, $query_params);
407+
$query_string = self::array_implode('=', '&', $params);
408+
$full_path = $path."?".$query_string;
409+
$request = new Request('POST', $full_path, $headers, $post_value);
410+
411+
return $request;
412+
}
413+
414+
/**
415+
* Trigger an event by providing event name and payload.
416+
* Optionally provide a socket ID to exclude a client (most likely the sender).
417+
*
418+
* @param array|string $channels A channel name or an array of channel names to publish the event on.
419+
* @param string $event
420+
* @param mixed $data Event data
421+
* @param array $params [optional]
422+
* @param bool $already_encoded [optional]
423+
*
424+
* @throws PusherException Throws PusherException if $channels is an array of size 101 or above or $socket_id is invalid
425+
* @throws ApiErrorException Throws ApiErrorException if the Channels HTTP API responds with an error
426+
* @throws GuzzleException
427+
*
428+
*/
429+
public function trigger($channels, $event, $data, $params = array(), $already_encoded = false) : object {
430+
$request = $this->make_request($channels, $event, $data, $params, $already_encoded);
431+
432+
$response = $this->client->send($request, [
407433
'http_errors' => false,
408434
'base_uri' => $this->channels_url_prefix()
409435
]);
@@ -425,16 +451,53 @@ public function trigger($channels, $event, $data, $params = array(), $already_en
425451
}
426452

427453
/**
428-
* Trigger multiple events at the same time.
454+
* Asynchronously trigger an event by providing event name and payload.
455+
* Optionally provide a socket ID to exclude a client (most likely the sender).
456+
*
457+
* @param array|string $channels A channel name or an array of channel names to publish the event on.
458+
* @param string $event
459+
* @param mixed $data Event data
460+
* @param array $params [optional]
461+
* @param bool $already_encoded [optional]
462+
*
463+
*/
464+
public function triggerAsync($channels, $event, $data, $params = array(), $already_encoded = false) : PromiseInterface
465+
{
466+
$request = $this->make_request($channels, $event, $data, $params, $already_encoded);
467+
468+
$promise = $this->client->sendAsync($request, [
469+
'http_errors' => false,
470+
'base_uri' => $this->channels_url_prefix()
471+
])->then(function ($response) {
472+
$status = $response->getStatusCode();
473+
474+
if ($status !== 200) {
475+
$body = (string) $response->getBody();
476+
throw new ApiErrorException($body, $status);
477+
}
478+
479+
$result = json_decode($response->getBody());
480+
481+
if (property_exists($result, 'channels')) {
482+
$result->channels = get_object_vars($result->channels);
483+
}
484+
485+
return $result;
486+
});
487+
488+
return $promise;
489+
}
490+
491+
/**
492+
* Helper function to prepare batch trigger request. Takes the same * parameters as the public batch trigger functions.
429493
*
430494
* @param array $batch [optional] An array of events to send
431495
* @param bool $already_encoded [optional]
432496
*
433497
* @throws ApiErrorException Throws ApiErrorException if the Channels HTTP API responds with an error
434-
* @throws GuzzleException
435498
*
436-
*/
437-
public function triggerBatch($batch = array(), $already_encoded = false) : object
499+
**/
500+
public function make_batch_request($batch = array(), $already_encoded = false) : Request
438501
{
439502
foreach ($batch as $key => $event) {
440503
$this->validate_channel($event['channel']);
@@ -471,10 +534,29 @@ public function triggerBatch($batch = array(), $already_encoded = false) : objec
471534
'X-Pusher-Library' => 'pusher-http-php '.self::$VERSION
472535
];
473536

474-
$response = $this->client->post($path, [
475-
'query' => array_merge($query_params, $signature),
476-
'body' => $post_value,
477-
'headers' => $headers,
537+
$params = array_merge($signature, $query_params);
538+
$query_string = self::array_implode('=', '&', $params);
539+
$full_path = $path."?".$query_string;
540+
$request = new Request('POST', $full_path, $headers, $post_value);
541+
542+
return $request;
543+
}
544+
545+
/**
546+
* Trigger multiple events at the same time.
547+
*
548+
* @param array $batch [optional] An array of events to send
549+
* @param bool $already_encoded [optional]
550+
*
551+
* @throws ApiErrorException Throws ApiErrorException if the Channels HTTP API responds with an error
552+
* @throws GuzzleException
553+
*
554+
*/
555+
public function triggerBatch($batch = array(), $already_encoded = false) : object
556+
{
557+
$request = $this->make_batch_request($batch, $already_encoded);
558+
559+
$response = $this->client->send($request, [
478560
'http_errors' => false,
479561
'base_uri' => $this->channels_url_prefix()
480562
]);
@@ -486,7 +568,50 @@ public function triggerBatch($batch = array(), $already_encoded = false) : objec
486568
throw new ApiErrorException($body, $status);
487569
}
488570

489-
return json_decode($response->getBody());
571+
$result = json_decode($response->getBody());
572+
573+
if (property_exists($result, 'channels')) {
574+
$result->channels = get_object_vars($result->channels);
575+
}
576+
577+
return $result;
578+
}
579+
580+
/**
581+
* Asynchronously trigger multiple events at the same time.
582+
*
583+
* @param array $batch [optional] An array of events to send
584+
* @param bool $already_encoded [optional]
585+
*
586+
* @throws ApiErrorException Throws ApiErrorException if the Channels HTTP API responds with an error
587+
*
588+
*/
589+
public function triggerBatchAsync($batch = array(), $already_encoded = false) : PromiseInterface
590+
{
591+
$request = $this->make_batch_request($batch, $already_encoded);
592+
593+
$promise = $this->client->sendAsync($request, [
594+
'http_errors' => false,
595+
'base_uri' => $this->channels_url_prefix()
596+
])->then(function ($response) {
597+
$status = $response->getStatusCode();
598+
599+
if ($status !== 200) {
600+
$body = (string) $response->getBody();
601+
throw new ApiErrorException($body, $status);
602+
}
603+
604+
$result = json_decode($response->getBody());
605+
606+
if (property_exists($result, 'channels')) {
607+
$result->channels = get_object_vars($result->channels);
608+
}
609+
610+
return $result;
611+
});
612+
613+
return $promise;
614+
490615
}
491616

492617
/**

src/PusherInterface.php

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<?php
22

33
namespace Pusher;
4+
use GuzzleHttp\Promise\PromiseInterface;
45

56
interface PusherInterface
67
{
@@ -29,7 +30,20 @@ public function getSettings();
2930
public function trigger($channels, $event, $data, $socket_id = null, $already_encoded = false) : object;
3031

3132
/**
32-
* Trigger multiple events at the same time.
33+
* Asynchronously trigger an event by providing event name and payload.
34+
* Optionally provide a socket ID to exclude a client (most likely the sender).
35+
*
36+
* @param array|string $channels A channel name or an array of channel names to publish the event on.
37+
* @param string $event
38+
* @param mixed $data Event data
39+
* @param array $params [optional]
40+
* @param bool $already_encoded [optional]
41+
*
42+
*/
43+
public function triggerAsync($channels, $event, $data, $params = array(), $already_encoded = false) : PromiseInterface;
44+
45+
/**
46+
*
3347
*
3448
* @param array $batch [optional] An array of events to send
3549
* @param bool $already_encoded [optional]
@@ -42,7 +56,19 @@ public function trigger($channels, $event, $data, $socket_id = null, $already_en
4256
public function triggerBatch($batch = array(), $already_encoded = false) : object;
4357

4458
/**
45-
* Fetch channel information for a specific channel.
59+
* Trigger multiple events at the same time.
60+
*
61+
* @param array $batch [optional] An array of events to send
62+
* @param bool $already_encoded [optional]
63+
*
64+
* @throws PusherException Throws exception if curl wasn't initialized correctly
65+
* @throws ApiErrorException Throws ApiErrorException if the Channels HTTP API responds with an error
66+
*
67+
*/
68+
public function triggerBatchAsync($batch = array(), $already_encoded = false) : PromiseInterface;
69+
70+
/**
71+
* Asynchronously trigger multiple events at the same time.
4672
*
4773
* @param string $channel The name of the channel
4874
* @param array $params Additional parameters for the query e.g. $params = array( 'info' => 'connection_count' )

0 commit comments

Comments
 (0)