-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
### What's new - Responses with a 429 (Too Many Requests) error code now trigger a specific exception with properties exposing additional information (the call scope, rate limit and time to retry). ### Bug fixes - `Contact::setDataFields()` no longer breaks if passed an empty array. - The import summary property is now allowed to be empty. Related work items: #236362, #270151, #272401
- Loading branch information
Showing
9 changed files
with
185 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
<?php | ||
|
||
namespace Dotdigital\Exception; | ||
|
||
use Psr\Http\Message\ResponseInterface; | ||
|
||
class TooManyRequestsException extends \ErrorException implements ExceptionInterface | ||
{ | ||
/** | ||
* @var ?string | ||
*/ | ||
private $scope; | ||
|
||
/** | ||
* @var ?int | ||
*/ | ||
private $limit; | ||
|
||
/** | ||
* @var ?int | ||
*/ | ||
private $reset; | ||
|
||
/** | ||
* @param ResponseInterface $errorResponse | ||
* @return TooManyRequestsException | ||
*/ | ||
public static function fromErrorResponse( | ||
ResponseInterface $errorResponse | ||
): TooManyRequestsException { | ||
$message = $errorResponse->getReasonPhrase(); | ||
$status = $errorResponse->getStatusCode(); | ||
$exception = new self($message, $status); | ||
$exception->setScope($errorResponse); | ||
$exception->setLimit($errorResponse); | ||
$exception->setReset($errorResponse); | ||
return $exception; | ||
} | ||
|
||
/** | ||
* @param ResponseInterface $errorResponse | ||
* | ||
* @return void | ||
*/ | ||
public function setScope($errorResponse): void | ||
{ | ||
$this->scope = $errorResponse->hasHeader('x-ratelimit-scope') ? | ||
$errorResponse->getHeader('x-ratelimit-scope')[0] : | ||
null; | ||
} | ||
|
||
/** | ||
* @return string|null | ||
*/ | ||
public function getScope(): ?string | ||
{ | ||
return $this->scope; | ||
} | ||
|
||
/** | ||
* @param ResponseInterface $errorResponse | ||
* | ||
* @return void | ||
*/ | ||
public function setLimit(ResponseInterface $errorResponse) | ||
{ | ||
$this->limit = $errorResponse->hasHeader('x-ratelimit-limit') ? | ||
(int) $errorResponse->getHeader('x-ratelimit-limit')[0] : | ||
null; | ||
} | ||
|
||
/** | ||
* @return int|null | ||
*/ | ||
public function getLimit(): ?int | ||
{ | ||
return $this->limit; | ||
} | ||
|
||
/** | ||
* Set the time in seconds until the rate limit resets. | ||
* | ||
* @param ResponseInterface $errorResponse | ||
* | ||
* @return void | ||
*/ | ||
public function setReset(ResponseInterface $errorResponse) | ||
{ | ||
$this->reset = $errorResponse->hasHeader('x-ratelimit-reset') ? | ||
(int) $errorResponse->getHeader('x-ratelimit-reset')[0] : | ||
null; | ||
} | ||
|
||
/** | ||
* @return int|null | ||
*/ | ||
public function getReset(): ?int | ||
{ | ||
return $this->reset; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
<?php | ||
|
||
namespace Dotdigital\Tests\V3\Unit\Models\Contact; | ||
|
||
use Dotdigital\V3\Models\Contact; | ||
use Dotdigital\V3\Models\Contact\DataField; | ||
use Dotdigital\V3\Models\DataFieldCollection; | ||
use PHPUnit\Framework\TestCase; | ||
|
||
class DataFieldsTest extends TestCase | ||
{ | ||
public function testDataFieldsCanBeSet() | ||
{ | ||
$dataFields = [ | ||
'FIRSTNAME' => 'Chaz', | ||
'LASTNAME' => 'Knox', | ||
]; | ||
$contact = new Contact(); | ||
$contact->setDataFields($dataFields); | ||
|
||
$this->assertInstanceOf(DataFieldCollection::class, $contact->getDataFields()); | ||
} | ||
|
||
public function testDataFieldsAreNotSetIfNoneSupplied() | ||
{ | ||
$dataFields = []; | ||
$contact = new Contact(); | ||
$contact->setDataFields($dataFields); | ||
|
||
$this->assertEquals(null, $contact->getDataFields()); | ||
} | ||
|
||
public function testSetDataFieldsCanPassEmptyCollection() | ||
{ | ||
$dataFields = new DataFieldCollection(); | ||
$contact = new Contact(); | ||
$contact->setDataFields($dataFields); | ||
|
||
$this->assertInstanceOf(DataFieldCollection::class, $contact->getDataFields()); | ||
} | ||
|
||
public function testSetDataFieldsCanPassLoadedCollection() { | ||
$dataField = new DataField('FIRSTNAME', 'Chaz'); | ||
$dataFields = new DataFieldCollection(); | ||
$dataFields->add($dataField); | ||
|
||
$contact = new Contact(); | ||
$contact->setDataFields($dataFields); | ||
|
||
$this->assertInstanceOf(DataFieldCollection::class, $contact->getDataFields()); | ||
$this->assertInstanceOf(DataField::class, $contact->getDataFields()->first()); | ||
} | ||
} |