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

Use protected properties and methods in WebPush class #324

Merged

Conversation

Kingdutch
Copy link
Contributor

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.

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.
@Kingdutch
Copy link
Contributor Author

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);
  }

}

Copy link
Member

@Minishlink Minishlink left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, it's not ideal but at least it's more customizable now :)

@Minishlink Minishlink merged commit 201d55d into web-push-libs:master Apr 8, 2021
@Kingdutch Kingdutch deleted the feature/extendable-webpush branch April 8, 2021 15:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants