Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
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
23 changes: 18 additions & 5 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,27 @@
WebPush is an open source library.
Feel free to contribute by submitting a pull request or creating (and solving) issues!

## Running Tests
## Installing a mock push service

Before running tests, you'll need to install the [web-push testing service](https://www.npmjs.com/package/web-push-testing-service):

```bash
npm install web-push-testing-service -g
```

NOTE: You might need to make sure command `web-push-testing-service` runs OK on cli. In my case on OSX, I needed to add a bash alias after install:

First, you will need to create your own configuration file by copying
phpunit.dist.xml to phpunit.xml and filling in the fields you need for
```~/.bash_profile
alias web-push-testing-service='/usr/local/Cellar/node/7.4.0/bin/web-push-testing-service'
```

After that, please create your own configuration file by copying
`phpunit.dist.xml` to phpunit.xml and filling in the fields you need for
testing (i.e. STANDARD_ENDPOINT, GCM_API_KEY etc.).

Then, download [phpunit](https://phpunit.de/) and test with one of the
following commands:
## Running Tests

Then, download [phpunit](https://phpunit.de/) and test with one of the following commands:

**For All Tests**
`php phpunit.phar`
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,8 @@
composer.lock
phpunit.xml

# web-push-testing-service logs
cli.log
module.log
.vagrant
Vagrantfile # temp, may be?
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ sudo: required
cache:
directories:
- ~/.selenium-assistant
- node_modules # cache modules too
- $HOME/.composer/cache/files # and composer packages

matrix:
allow_failures:
Expand Down
22 changes: 19 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,26 @@ foreach ($notifications as $notification) {
$notification['payload'] // optional (defaults null)
);
}
$webPush->flush();

// send one notification and flush directly
$webPush->sendNotification(
/**
* Check sent results
* @var MessageSentReport $report
*/
foreach ($webPush->flush() as $report) {
$endpoint = $report->getRequest()->getUri()->__toString();

if ($report->isSuccess()) {
echo "[v] Message sent successfully for subscription {$endpoint}.";
} else {
echo "[x] Message failed to sent for subscription {$endpoint}: {$report->getReason()}";
}
}

/**
* send one notification and flush directly
* @var \Generator<MessageSentReport> $sent
*/
$sent = $webPush->sendNotification(
$notifications[0]['subscription'],
$notifications[0]['payload'], // optional (defaults null)
true // optional (defaults false)
Expand Down
131 changes: 131 additions & 0 deletions src/MessageSentReport.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
<?php
/**
* @author Igor Timoshenkov [[email protected]]
* @started: 03.09.2018 9:21
*/

namespace Minishlink\WebPush;

use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;

/**
* Standardized response from sending a message
*/
class MessageSentReport {

/**
* @var boolean
*/
protected $success;

/**
* @var RequestInterface
*/
protected $request;

/**
* @var ResponseInterface
*/
protected $response;

/**
* @var string
*/
protected $reason;

/**
* @param RequestInterface $request
* @param ResponseInterface $response
* @param bool $success
* @param string $reason
*/
public function __construct(?RequestInterface $request = null, ?ResponseInterface $response = null, bool $success = true, $reason = 'OK') {
$this->success = $success;
$this->request = $request;
$this->response = $response;
$this->reason = $reason;
}

/**
* @return bool
*/
public function isSuccess(): bool {
return $this->success;
}

/**
* @param bool $success
*
* @return MessageSentReport
*/
public function setSuccess(bool $success): MessageSentReport {
$this->success = $success;
return $this;
}

/**
* @return RequestInterface
*/
public function getRequest(): RequestInterface {
return $this->request;
}

/**
* @param RequestInterface $request
*
* @return MessageSentReport
*/
public function setRequest(RequestInterface $request): MessageSentReport {
$this->request = $request;
return $this;
}

/**
* @return ResponseInterface
*/
public function getResponse(): ResponseInterface {
return $this->response;
}

/**
* @param ResponseInterface $response
*
* @return MessageSentReport
*/
public function setResponse(ResponseInterface $response): MessageSentReport {
$this->response = $response;
return $this;
}

/**
* @return string
*/
public function getEndpoint(): string {
return $this->request->getUri()->__toString();
}

/**
* @return bool
*/
public function isSubscriptionExpired(): bool {
return \in_array($this->response->getStatusCode(), [404, 410], true);
}

/**
* @return string
*/
public function getReason(): string {
return $this->reason;
}

/**
* @param string $reason
*
* @return MessageSentReport
*/
public function setReason(string $reason): MessageSentReport {
$this->reason = $reason;
return $this;
}
}
110 changes: 35 additions & 75 deletions src/WebPush.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Promise;
use Psr\Http\Message\ResponseInterface;

class WebPush
{
Expand Down Expand Up @@ -121,93 +121,53 @@ public function sendNotification(Subscription $subscription, ?string $payload =

$this->notifications[] = new Notification($subscription, $payload, $options, $auth);

if ($flush) {
$res = $this->flush();

// if there has been a problem with at least one notification
if (is_array($res)) {
// if there was only one notification, return the information directly
if (count($res) === 1) {
return $res[0];
}

return $res;
}

return true;
}

return true;
return false !== $flush ? $this->flush() : true;
}

/**
* Flush notifications. Triggers the requests.
*
* @param null|int $batchSize Defaults the value defined in defaultOptions during instantiation (which defaults to 1000).
*
* @return array|bool If there are no errors, return true.
* If there were no notifications in the queue, return false.
* Else return an array of information for each notification sent (success, statusCode, headers, content)
*
* @throws \ErrorException
*/
public function flush(?int $batchSize = null)
/**
* Flush notifications. Triggers the requests.
*
* @param null|int $batchSize Defaults the value defined in defaultOptions during instantiation (which defaults to 1000).
*
* @return iterable
* @throws \ErrorException
*/
public function flush(?int $batchSize = null) : iterable
{
if (empty($this->notifications)) {
return false;
yield from [];
}

if (null === $batchSize) {
$batchSize = $this->defaultOptions['batchSize'];
}

$batches = array_chunk($this->notifications, $batchSize);
$return = [];
$completeSuccess = true;
foreach ($batches as $batch) {
// for each endpoint server type
$requests = $this->prepare($batch);
$promises = [];
foreach ($requests as $request) {
$promises[] = $this->client->sendAsync($request);
}
$results = Promise\settle($promises)->wait();

foreach ($results as $result) {
if ($result['state'] === "rejected") {
/** @var RequestException $reason **/
$reason = $result['reason'];

$error = [
'success' => false,
'endpoint' => $reason->getRequest()->getUri(),
'message' => $reason->getMessage(),
];

$response = $reason->getResponse();
if ($response !== null) {
$statusCode = $response->getStatusCode();
$error['statusCode'] = $statusCode;
$error['reasonPhrase'] = $response->getReasonPhrase();
$error['expired'] = in_array($statusCode, [404, 410]);
$error['content'] = $response->getBody();
$error['headers'] = $response->getHeaders();
}

$return[] = $error;
$completeSuccess = false;
} else {
$return[] = [
'success' => true,
];
}
}
}

// reset queue
$this->notifications = null;
// reset queue
$this->notifications = [];

return $completeSuccess ? true : $return;
foreach ($batches as $batch) {
// for each endpoint server type
$requests = $this->prepare($batch);

foreach ($requests as $request) {
$result = null;

$this->client->sendAsync($request)
->then(function ($response) use ($request, &$result) {
/** @var ResponseInterface $response * */
$result = new MessageSentReport($request, $response);
})
->otherwise(function ($reason) use (&$result) {
/** @var RequestException $reason **/
$result = new MessageSentReport($reason->getRequest(), $reason->getResponse(), false, $reason->getMessage());
})
->wait(false);

yield $result;
}
}
}

/**
Expand Down
7 changes: 6 additions & 1 deletion tests/PushServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,12 @@ protected function createClosureTest($browserId, $browserVersion, $options)

try {
$sendResp = $this->webPush->sendNotification($subscription, $payload, true);
$this->assertTrue($sendResp);
$this->assertInstanceOf(\Generator::class, $sendResp);

/** @var \Minishlink\WebPush\MessageSentReport $report */
foreach ($sendResp as $report) {
$this->assertTrue($report->isSuccess());
}

$dataString = json_encode([
'testSuiteId' => self::$testSuiteId,
Expand Down
Loading