Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for multiple events #26

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/php.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
php: [ 8.1, 8.2 ]
include:
- laravel: 9.*
testbench: 6.*
testbench: 7.*
- laravel: 10.*
testbench: 8.*

Expand Down
41 changes: 41 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,47 @@ The *`getEvent()`* method is used to return the name of the webhook event, ie. `

The *`getData()`* method is used to return the payload of data that can be used within your handler. By default this is set to `$request->all()`.

#### Receiving multiple events in a single webhook

Sometimes the services will send multiple event payloads in a single webhook.

In this scenario you may return an array of mapped events from the `getEvent` method and Receiver will handle them each individually.

For example, if the payload looks like this:
```json
{
"time_ms": 1697717045179,
"events": [
{
"name": "channel_occupied",
"channel": "admin",
"data": {}
},
{
"name": "member_added",
"channel": "admin",
"data": {}
}
]
}
```

You may return the events from the `getEvent` method like so:
```php
public function getEvent(): array
{
return $events = $this->request
->collect('events')
->mapToGroups(
fn ($item) => [
$item['name'] => $item
]
)
->toArray();
}
```
Receiver will then handle each event individually.

### Securing Webhooks

Many webhooks have ways of verifying their authenticity as they are received, most commonly through signatures or basic authentication. No matter the strategy, Receiver allows you to write custom verification code as necessary. Simply implement the `verify` method in your provider and return true or false if it passes.
Expand Down
29 changes: 13 additions & 16 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true"
>
<coverage>
<include>
<directory suffix=".php">src</directory>
</include>
</coverage>
<testsuites>
<testsuite name="default">
<directory suffix="Test.php">tests</directory>
</testsuite>
</testsuites>
</phpunit>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.4/phpunit.xsd" bootstrap="vendor/autoload.php" colors="true">
<coverage/>
<testsuites>
<testsuite name="default">
<directory suffix="Test.php">tests</directory>
</testsuite>
</testsuites>
<source>
<include>
<directory suffix=".php">src</directory>
</include>
</source>
</phpunit>
17 changes: 17 additions & 0 deletions phpunit.xml.dist.bak
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true"
>
<coverage>
<include>
<directory suffix=".php">src</directory>
</include>
</coverage>
<testsuites>
<testsuite name="default">
<directory suffix="Test.php">tests</directory>
</testsuite>
</testsuites>
</phpunit>
32 changes: 22 additions & 10 deletions src/Providers/AbstractProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Illuminate\Contracts\Support\Responsable;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Receiver\Contracts\Provider as ProviderContract;
use Symfony\Component\HttpFoundation\Response;
Expand Down Expand Up @@ -35,9 +36,9 @@ abstract class AbstractProvider implements ProviderContract, Responsable
protected Closure|null $fallback = null;

/**
* @var bool
* @var array
*/
protected mixed $dispatched = false;
protected mixed $dispatchedEvents = [];

/**
* @var string
Expand All @@ -53,9 +54,9 @@ public function __construct(protected ?string $secret = null)

/**
* @param Request $request
* @return string
* @return string|array
*/
abstract public function getEvent(Request $request): string;
abstract public function getEvent(Request $request): string|array;

/**
* @param Request $request
Expand Down Expand Up @@ -138,11 +139,14 @@ public function webhook(): ?Webhook
}

/**
* @param string|null $key
* @return bool
*/
public function dispatched(): bool
public function dispatched(string $key = null): bool
{
return $this->dispatched;
return $key
? in_array($key, $this->dispatchedEvents)
: ! empty($this->dispatchedEvents);
}

/**
Expand All @@ -162,12 +166,20 @@ protected function mapWebhook(Request $request): Webhook
*/
protected function handle(): static
{
$class = $this->getClass($event = $this->webhook->getEvent());
$events = $this->webhook->getEvent();

if(! is_array($events)) {
$events = [$events => $this->webhook->getData()];
}

if (class_exists($class)) {
$class::dispatch($event, $this->webhook->getData());
foreach($events as $event => $data) {
$class = $this->getClass($event);

$this->dispatched = true;
if (class_exists($class)) {
$class::dispatch($event, $data);

$this->dispatchedEvents[] = $class;
}
}

return $this;
Expand Down
Loading