Skip to content

Commit 1f63526

Browse files
committed
Merge pull request #3 from php-http/implementation
Add Fulfilled and Rejected promise implementations
2 parents 0d0399f + 7e61385 commit 1f63526

17 files changed

+387
-11
lines changed

.editorconfig

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,3 @@ indent_size = 4
77
indent_style = space
88
insert_final_newline = true
99
trim_trailing_whitespace = true
10-
11-
[*.yml*]
12-
indent_size = 2

.gitattributes

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
1-
.editorconfig export-ignore
2-
.gitattributes export-ignore
3-
.gitignore export-ignore
4-
CONTRIBUTING.md export-ignore
5-
CONDUCT.md export-ignore
1+
spec/ export-ignore
2+
tests/ export-ignore
3+
.editorconfig export-ignore
4+
.gitattributes export-ignore
5+
.gitignore export-ignore
6+
.php_cs export-ignore
7+
.scrutinizer.yml export-ignore
8+
.styleci.yml export-ignore
9+
.travis.yml export-ignore
10+
CONDUCT.md export-ignore
11+
CONTRIBUTING.md export-ignore
12+
phpspec.yml.ci export-ignore
13+
phpspec.yml.dist export-ignore
14+
phpunit.xml.dist export-ignore

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
build/
22
vendor/
33
composer.lock
4+
phpspec.yml
5+
phpunit.xml

.php_cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
/*
4+
* In order to make it work, fabpot/php-cs-fixer and sllh/php-cs-fixer-styleci-bridge must be installed globally
5+
* with composer.
6+
*
7+
* @link https://github.com/Soullivaneuh/php-cs-fixer-styleci-bridge
8+
* @link https://github.com/FriendsOfPHP/PHP-CS-Fixer
9+
*/
10+
11+
use SLLH\StyleCIBridge\ConfigBridge;
12+
13+
return ConfigBridge::create();

.scrutinizer.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
filter:
2+
paths: [src/*]
3+
checks:
4+
php:
5+
code_rating: true
6+
duplication: true
7+
tools:
8+
external_code_coverage: true

.styleci.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
preset: symfony
2+
3+
finder:
4+
exclude:
5+
- "spec"
6+
- "tests"
7+
path:
8+
- "src"
9+
10+
enabled:
11+
- short_array_syntax
12+
13+
disabled:
14+
- unalign_double_arrow

.travis.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
language: php
2+
3+
sudo: false
4+
5+
cache:
6+
directories:
7+
- $HOME/.composer/cache
8+
9+
php:
10+
- 5.4
11+
- 5.5
12+
- 5.6
13+
- 7.0
14+
- hhvm
15+
16+
env:
17+
global:
18+
- TEST_COMMAND="composer test"
19+
20+
branches:
21+
except:
22+
- /^analysis-.*$/
23+
24+
matrix:
25+
fast_finish: true
26+
include:
27+
- php: 5.4
28+
env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest" COVERAGE=true TEST_COMMAND="composer test-ci"
29+
30+
before_install:
31+
- travis_retry composer self-update
32+
33+
install:
34+
- travis_retry composer update ${COMPOSER_FLAGS} --prefer-source --no-interaction
35+
36+
script:
37+
- $TEST_COMMAND
38+
39+
after_success:
40+
- if [[ "$COVERAGE" = true ]]; then wget https://scrutinizer-ci.com/ocular.phar; fi
41+
- if [[ "$COVERAGE" = true ]]; then php ocular.phar code-coverage:upload --format=php-clover build/coverage.xml; fi

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ $ git rebase -i HEAD~3
7575
If your branch conflicts with the master branch, you will need to rebase and repush it with the following commands:
7676

7777
``` bash
78-
$ git remote add upstream git@github.com:php-http/repo-name.git
78+
$ git remote add upstream git@github.com:orga/repo-name.git
7979
$ git pull --rebase upstream master
8080
$ git push -f origin feature-or-bug-fix-description
8181
```

README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,22 @@ $ composer require php-http/promise
2323
Please see the [official documentation](http://docs.httplug.io).
2424

2525

26+
## Testing
27+
28+
``` bash
29+
$ composer test
30+
```
31+
32+
2633
## Contributing
2734

2835
Please see [CONTRIBUTING](CONTRIBUTING.md) and [CONDUCT](CONDUCT.md) for details.
2936

3037

3138
## Security
3239

33-
If you discover any security related issues, please contact us at [security@php-http.org](mailto:security@php-http.org).
40+
If you discover any security related issues, please contact us at [security@httplug.io](mailto:security@httplug.io)
41+
or [security@php-http.org](mailto:security@php-http.org).
3442

3543

3644
## License

composer.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,22 @@
1414
"email": "mark.sagikazar@gmail.com"
1515
}
1616
],
17+
"require": {
18+
"psr/http-message": "^1.0"
19+
},
20+
"require-dev": {
21+
"phpspec/phpspec": "^2.4",
22+
"henrikbjorn/phpspec-code-coverage" : "^1.0"
23+
},
1724
"autoload": {
1825
"psr-4": {
1926
"Http\\Promise\\": "src/"
2027
}
2128
},
29+
"scripts": {
30+
"test": "vendor/bin/phpspec run",
31+
"test-ci": "vendor/bin/phpspec run -c phpspec.yml.ci"
32+
},
2233
"extra": {
2334
"branch-alias": {
2435
"dev-master": "0.2-dev"

phpspec.yml.ci

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
suites:
2+
tools_suite:
3+
namespace: Http\Promise
4+
psr4_prefix: Http\Promise
5+
formatter.name: pretty
6+
extensions:
7+
- PhpSpec\Extension\CodeCoverageExtension
8+
code_coverage:
9+
format: clover
10+
output: build/coverage.xml

phpspec.yml.dist

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
suites:
2+
tools_suite:
3+
namespace: Http\Promise
4+
psr4_prefix: Http\Promise
5+
formatter.name: pretty

spec/FulfilledPromiseSpec.php

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
3+
namespace spec\Http\Promise;
4+
5+
use Http\Promise\Promise;
6+
use Psr\Http\Message\RequestInterface;
7+
use Psr\Http\Message\ResponseInterface;
8+
use PhpSpec\ObjectBehavior;
9+
use Prophecy\Argument;
10+
11+
class FulfilledPromiseSpec extends ObjectBehavior
12+
{
13+
function let(ResponseInterface $response)
14+
{
15+
$this->beConstructedWith($response);
16+
}
17+
18+
function it_is_initializable(ResponseInterface $response)
19+
{
20+
$this->shouldHaveType('Http\Promise\FulfilledPromise');
21+
}
22+
23+
function it_is_a_promise()
24+
{
25+
$this->shouldImplement('Http\Promise\Promise');
26+
}
27+
28+
function it_returns_a_fulfilled_promise(ResponseInterface $response)
29+
{
30+
$promise = $this->then(function (ResponseInterface $responseReceived) use ($response) {
31+
if (Argument::is($responseReceived)->scoreArgument($response->getWrappedObject())) {
32+
return $response->getWrappedObject();
33+
}
34+
});
35+
36+
$promise->shouldHaveType('Http\Promise\Promise');
37+
$promise->shouldHaveType('Http\Promise\FulfilledPromise');
38+
$promise->getState()->shouldReturn(Promise::FULFILLED);
39+
$promise->wait()->shouldReturn($response);
40+
}
41+
42+
function it_returns_a_rejected_promise(RequestInterface $request, ResponseInterface $response)
43+
{
44+
$exception = new \Exception();
45+
46+
$promise = $this->then(function (ResponseInterface $responseReceived) use ($response, $exception) {
47+
if (Argument::is($responseReceived)->scoreArgument($response->getWrappedObject())) {
48+
throw $exception;
49+
}
50+
});
51+
52+
$promise->shouldHaveType('Http\Promise\Promise');
53+
$promise->shouldHaveType('Http\Promise\RejectedPromise');
54+
$promise->getState()->shouldReturn(Promise::REJECTED);
55+
$promise->shouldThrow($exception)->duringWait();
56+
}
57+
58+
function it_is_in_fulfilled_state()
59+
{
60+
$this->getState()->shouldReturn(Promise::FULFILLED);
61+
}
62+
63+
function it_has_a_response(ResponseInterface $response)
64+
{
65+
$this->wait()->shouldReturn($response);
66+
}
67+
}

spec/RejectedPromiseSpec.php

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
namespace spec\Http\Promise;
4+
5+
use Http\Promise\Promise;
6+
use Psr\Http\Message\ResponseInterface;
7+
use PhpSpec\ObjectBehavior;
8+
use Prophecy\Argument;
9+
10+
class RejectedPromiseSpec extends ObjectBehavior
11+
{
12+
function let()
13+
{
14+
$this->beConstructedWith(new \Exception());
15+
}
16+
17+
function it_is_initializable()
18+
{
19+
$this->shouldHaveType('Http\Promise\RejectedPromise');
20+
}
21+
22+
function it_is_a_promise()
23+
{
24+
$this->shouldImplement('Http\Promise\Promise');
25+
}
26+
27+
function it_returns_a_fulfilled_promise(ResponseInterface $response)
28+
{
29+
$exception = new \Exception();
30+
$this->beConstructedWith($exception);
31+
32+
$promise = $this->then(null, function (\Exception $exceptionReceived) use($exception, $response) {
33+
if (Argument::is($exceptionReceived)->scoreArgument($exception)) {
34+
return $response->getWrappedObject();
35+
}
36+
});
37+
38+
$promise->shouldHaveType('Http\Promise\Promise');
39+
$promise->shouldHaveType('Http\Promise\FulfilledPromise');
40+
$promise->getState()->shouldReturn(Promise::FULFILLED);
41+
$promise->wait()->shouldReturn($response);
42+
}
43+
44+
function it_returns_a_rejected_promise()
45+
{
46+
$exception = new \Exception();
47+
$this->beConstructedWith($exception);
48+
49+
$promise = $this->then(null, function (\Exception $exceptionReceived) use($exception) {
50+
if (Argument::is($exceptionReceived)->scoreArgument($exception)) {
51+
throw $exception;
52+
}
53+
});
54+
55+
$promise->shouldHaveType('Http\Promise\Promise');
56+
$promise->shouldHaveType('Http\Promise\RejectedPromise');
57+
$promise->getState()->shouldReturn(Promise::REJECTED);
58+
$promise->shouldThrow($exception)->duringWait();
59+
}
60+
61+
function it_is_in_rejected_state()
62+
{
63+
$this->getState()->shouldReturn(Promise::REJECTED);
64+
}
65+
66+
function it_returns_an_exception()
67+
{
68+
$exception = new \Exception();
69+
70+
$this->beConstructedWith($exception);
71+
$this->shouldThrow($exception)->duringWait();
72+
}
73+
}

src/FulfilledPromise.php

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
namespace Http\Promise;
4+
5+
use Psr\Http\Message\ResponseInterface;
6+
7+
/**
8+
* A promise already fulfilled.
9+
*
10+
* @author Joel Wurtz <jwurtz@jolicode.com>
11+
*/
12+
final class FulfilledPromise implements Promise
13+
{
14+
/**
15+
* @var ResponseInterface
16+
*/
17+
private $response;
18+
19+
/**
20+
* @param ResponseInterface $response
21+
*/
22+
public function __construct(ResponseInterface $response)
23+
{
24+
$this->response = $response;
25+
}
26+
27+
/**
28+
* {@inheritdoc}
29+
*/
30+
public function then(callable $onFulfilled = null, callable $onRejected = null)
31+
{
32+
if (null === $onFulfilled) {
33+
return $this;
34+
}
35+
36+
try {
37+
return new self($onFulfilled($this->response));
38+
} catch (\Exception $e) {
39+
return new RejectedPromise($e);
40+
}
41+
}
42+
43+
/**
44+
* {@inheritdoc}
45+
*/
46+
public function getState()
47+
{
48+
return Promise::FULFILLED;
49+
}
50+
51+
/**
52+
* {@inheritdoc}
53+
*/
54+
public function wait($unwrap = true)
55+
{
56+
if ($unwrap) {
57+
return $this->response;
58+
}
59+
}
60+
}

src/Promise.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public function getState();
6262
*
6363
* @return ResponseInterface|null Resolved value, null if $unwrap is set to false
6464
*
65-
* @throws \Http\Client\Exception The rejection reason.
65+
* @throws \Exception The rejection reason.
6666
*/
6767
public function wait($unwrap = true);
6868
}

0 commit comments

Comments
 (0)