Closed Kingdutch closed 3 years ago
As an example the following class allows sending push notifications using ReactPHP. I've intentionally positioned this next to the existing methods because creating new methods rather than using the same function signatures was easier.
<?php
use Minishlink\WebPush\MessageSentReport;
use Minishlink\WebPush\WebPush;
use Psr\Http\Message\ResponseInterface;
use React\Http\Browser;
use React\Promise\Promise;
use function React\Promise\all as promise_all;
use function React\Promise\resolve as promise_resolve;
/**
* WebPush implementation that uses the React HTTP client instead of Guzzle.
*/
class ReactWebPush extends WebPush {
/**
* A ReactPHP HTTP client connected to the application's event loop.
*/
protected Browser $reactClient;
/**
* Set the ReactPHP Browser to use.
*
* This is set in a separate method rather than an overwritten __construct so
* that the calling of the WebPush library remains the same.
*
* @param \React\Http\Browser $client
* A ReactPHP HTTP client connected to the application's event loop.
*
* @return $this
* This WebPush instance.
*/
public function setClient(Browser $client) : self {
$this->reactClient = $client;
return $this;
}
/**
* Flush notifications. Triggers the requests.
*
* Uses ReactPHP as HTTP client instead of Guzzle for better integration with
* the event loop.
*
* @return \React\Promise\Promise
* A promise that resolves to an array of MessageSentReport instances.
*/
public function flushAsync() : Promise {
if (empty($this->notifications)) {
return promise_resolve([]);
}
$promises = [];
$requests = $this->prepare($this->notifications);
$this->notifications = [];
/** @var \GuzzleHttp\Psr7\Request $request */
foreach ($requests as $request) {
// Convert a Guzzle request to our ReactPHP client's method call.
$promises[] = $this->reactClient
->request(
$request->getMethod(),
(string) $request->getUri(),
$request->getHeaders(),
$request->getBody()->getContents()
)
->then(
fn (ResponseInterface $response) => new MessageSentReport($request, $response),
fn (\Exception $e) => new MessageSentReport($request, method_exists($e, "getResponse") ? $e->getResponse() : NULL, FALSE, $e->getMessage())
);
}
return promise_all($promises);
}
}
This allows other projects to extend the WebPush class and alter the way it works. An example use-case is to replace Guzzle with a ReactPHP based HTTP client for better integration in long-running asynchronous processes.