Skip to content
This repository has been archived by the owner on Jan 29, 2020. It is now read-only.

Commit

Permalink
Merge branch 'feature/decorator-deprecation' into dev-2.0.0
Browse files Browse the repository at this point in the history
Forward port #70 to dev-2.0.0

Conflicts:
	doc/book/migration/to-v2.md
	src/FinalHandler.php
	test/FinalHandlerTest.php
	test/MiddlewarePipeTest.php
  • Loading branch information
weierophinney committed Sep 30, 2016
2 parents baa258f + f184106 commit 2f44424
Show file tree
Hide file tree
Showing 11 changed files with 363 additions and 2 deletions.
37 changes: 37 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,27 @@ details.
middleware you invoke as the application). This handler returns the response
provided to it verbatim.

- [#70](https://github.com/zendframework/zend-stratigility/pull/70) adds a new
class, `Zend\Stratigility\Middleware\OriginalMessages`. Compose this
middleware in an outermost layer, and it will inject the following attributes
in the request passed to nested layers:

- `originalRequest`, representing the request provided to it.
- `originalResponse`, representing the response provided to it.
- `originalUri`, representing URI instance composed in the request provided to it.

### Changed

- [#70](https://github.com/zendframework/zend-stratigility/pull/70) makes the
following changes to `Zend\Stratigility\FinalHandler`:

- It now pulls the original request using the `originalRequest` attribute,
instead of `getOriginalRequest()`; see the deprecation of
`Zend\Stratigility\Http\Request`, below, for why this works.
- It no longer writes to the response using the
`Zend\Stratigility\Http\Response`-specific `write()` method, but rather
pulls the message body and writes to that.

### Deprecated

- [#66](https://github.com/zendframework/zend-stratigility/pull/66) deprecates
Expand All @@ -122,6 +143,22 @@ details.
a non-null `$err` argument is provided; middleware should raise an exception,
instead of invoking middleware implementing `ErrorMiddlewareInterface`.

- [#70](https://github.com/zendframework/zend-stratigility/pull/70) deprecates
`Zend\Stratigility\Http\Request`. Additionally:

- The composed "PSR Request" is now injected with an additional attribute,
`originalRequest`, allowing retrieval using standard PSR-7 attribute access.
- The methods `getCurrentRequest()` and `getOriginalRequest()` now emit
deprecation notices when invoked, urging users to update their code.

- [#70](https://github.com/zendframework/zend-stratigility/pull/70) deprecates
`Zend\Stratigility\Http\ResponseInterface`.

- [#70](https://github.com/zendframework/zend-stratigility/pull/70) deprecates
`Zend\Stratigility\Http\Response`. Additionally, the methods `write()`,
`end()`, `isComplete()`, and `getOriginalResponse()` now emit deprecation
notices when invoked, urging users to update their code.

### Removed

- Nothing.
Expand Down
52 changes: 52 additions & 0 deletions doc/book/migration/to-v2.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,55 @@ To help you prepare your code for version 2, version 1.3.0 provides several
forwards compatibility features to assist you in the process. However, some
changes will still require changes to your code following the 2.0 release.

## Original request, response, and URI

In the original 1.X releases, Stratigility would decorate the request and
response instances with `Zend\Stratigility\Http\Request` and
`Zend\Stratigility\Http\Response`, respectively. This was done originally to
facilitate access to the incoming request in cases of nested layers, where the
URI path may have been truncated (`Next` truncates matched paths when executing
a layer if a path was provided when piping the middleware).

Internally, prior to 1.3, only `Zend\Stratigility\FinalHandler` was still using
this functionality:

- It would query the original request to get the original URI when creating a
404 response message.
- It passes the decorated request and response instances to `onerror` handlers.

Starting with 1.3.0, we now deprecate these message decorators, and recommend
against their usage.

If you still need access to the original request, response, or URI instance, we
recommend the following:

- Pipe `Zend\Stratigility\Middleware\OriginalMessages` as the outermost layer of
your application. This will inject the following request attributes into
layers beneath it:
- `originalRequest`, mapping to the request provided to it at invocation.
- `originalResponse`, mapping to the response provided to it at invocation.
- `originalUri`, mapping to the URI composed by the request provided to it at
invocation.

You can then access these values within other middleware:

```php
$originalRequest = $request->getAttribute('originalRequest');
$originalResponse = $request->getAttribute('originalResponse');
$originalUri = $request->getAttribute('originalUri');
```

Internally, starting with 1.3.0, we have updated the request decorator to add
the `originalRequest` attribute, and the `FinalHandler` to check for this,
instead of the decorated instance.

Finally, if you are creating an `onerror` handler for the `FinalHandler`, update
your typehints to refer to the PSR-7 request and response interfaces instead of
the Stratigility decorators, if you aren't already.

The `Zend\Stratigility\Http` classes, interfaces, and namespace will be removed
in version 2.0.0.

## Error handling

Prior to version 1.3, the recommended way to handle errors was via
Expand Down Expand Up @@ -95,6 +144,9 @@ The following classes, methods, and arguments are deprecated starting in version
- The `$err` argument to `Zend\Stratigility\Next`'s `__invoke()` method.
Starting in 1.3.0, if a non-null value is encountered, this method will now
emit an `E_USER_DEPRECATED` notice, referencing this documentation.
- `Zend\Stratigility\Http\Request` (class)
- `Zend\Stratigility\Http\ResponseInterface` (interface)
- `Zend\Stratigility\Http\Response` (class)

## Interface/signature changes

Expand Down
29 changes: 28 additions & 1 deletion src/Http/Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
*
* Decorates the PSR incoming request interface to add the ability to
* manipulate arbitrary instance members.
*
* @deprecated since 1.3.0; to be removed with 2.0.0. Track the original
* request via a request attribute or via a service instead; you can
* use Zend\Stratigility\Middleware\OriginalMessages to do so.
*/
class Request implements ServerRequestInterface
{
Expand Down Expand Up @@ -50,7 +54,9 @@ public function __construct(
}

$this->originalRequest = $originalRequest;
$this->psrRequest = $decoratedRequest->withAttribute('originalUri', $originalRequest->getUri());
$this->psrRequest = $decoratedRequest
->withAttribute('originalUri', $originalRequest->getUri())
->withAttribute('originalRequest', $originalRequest);
}

/**
Expand All @@ -60,6 +66,16 @@ public function __construct(
*/
public function getCurrentRequest()
{
trigger_error(sprintf(
'%s is now deprecated. The request passed to your method is the current '
. 'request now. %s will no longer be available starting in Stratigility 2.0.0. '
. 'Please see https://docs.zendframework.com/migration/to-v2/#original-request-response-and-uri '
. 'for full details.',
__CLASS__,
\Zend\Stratigility\Middleware\OriginalMessages::class,
__METHOD__
), E_USER_DEPRECATED);

return $this->psrRequest;
}

Expand All @@ -70,6 +86,17 @@ public function getCurrentRequest()
*/
public function getOriginalRequest()
{
trigger_error(sprintf(
'%s is now deprecated. Please register %s as your outermost middleware, '
. 'and pull the original request via the request "originalRequest" '
. 'attribute. %s will no longer be available starting in Stratigility 2.0.0. '
. 'Please see https://docs.zendframework.com/migration/to-v2/#original-request-response-and-uri '
. 'for full details.',
__CLASS__,
\Zend\Stratigility\Middleware\OriginalMessages::class,
__METHOD__
), E_USER_DEPRECATED);

return $this->originalRequest;
}

Expand Down
42 changes: 42 additions & 0 deletions src/Http/Response.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
*
* Adds in write, end, and isComplete from RequestInterface in order
* to provide a common interface for all PSR HTTP implementations.
*
* @deprecated since 1.3.0; to be removed with 2.0.0. Track the original
* response via a request attribute or via a service instead; you
* can use Zend\Stratigility\Middleware\OriginalMessages to do so. We
* recommend that you use only the methods defined in PSR-7.
*/
class Response implements
PsrResponseInterface,
Expand Down Expand Up @@ -48,6 +53,16 @@ public function __construct(PsrResponseInterface $response)
*/
public function getOriginalResponse()
{
trigger_error(sprintf(
'%s is now deprecated. Please register %s as your outermost middleware, '
. 'and pull the original response via the request "originalResponse" '
. 'attribute. %s will no longer be available starting in Stratigility 2.0.0. '
. 'Please see https://docs.zendframework.com/migration/to-v2/#original-request-response-and-uri '
. 'for full details.',
__CLASS__,
\Zend\Stratigility\Middleware\OriginalMessages::class,
__METHOD__
), E_USER_DEPRECATED);
return $this->psrResponse;
}

Expand All @@ -62,6 +77,15 @@ public function getOriginalResponse()
*/
public function write($data)
{
trigger_error(sprintf(
'%s is now deprecated; use $response->getBody()->write(). '
. '%s will no longer be available starting in Stratigility 2.0.0. '
. 'Please see https://docs.zendframework.com/migration/to-v2/#deprecated-functionality '
. 'for full details.',
__CLASS__,
__METHOD__
), E_USER_DEPRECATED);

if ($this->complete) {
throw $this->responseIsAlreadyCompleted(__METHOD__);
}
Expand All @@ -84,6 +108,15 @@ public function write($data)
*/
public function end($data = null)
{
trigger_error(sprintf(
'%s is now deprecated; use $response->getBody()->write(). '
. '%s will no longer be available starting in Stratigility 2.0.0. '
. 'Please see https://docs.zendframework.com/migration/to-v2/#deprecated-functionality '
. 'for full details.',
__CLASS__,
__METHOD__
), E_USER_DEPRECATED);

if ($this->complete) {
return $this;
}
Expand All @@ -106,6 +139,15 @@ public function end($data = null)
*/
public function isComplete()
{
trigger_error(sprintf(
'%s is now deprecated; use $response->getBody()->write(). '
. '%s will no longer be available starting in Stratigility 2.0.0. '
. 'Please see https://docs.zendframework.com/migration/to-v2/#deprecated-functionality '
. 'for full details.',
__CLASS__,
__METHOD__
), E_USER_DEPRECATED);

return $this->complete;
}

Expand Down
3 changes: 3 additions & 0 deletions src/Http/ResponseInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
* - Write to the content
* - End the response (mark it complete)
* - Determine if the response is complete
*
* @deprecated since 1.3.0; to be removed with 2.0.0. Do not use the methods
* defined in this interface; use only those defined in PSR-7.
*/
interface ResponseInterface
{
Expand Down
52 changes: 52 additions & 0 deletions src/Middleware/OriginalMessages.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php
/**
* @link http://github.com/zendframework/zend-stratigility for the canonical source repository
* @copyright Copyright (c) 2016 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/

namespace Zend\Stratigility\Middleware;

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Zend\Stratigility\MiddlewareInterface;

/**
* Inject attributes containing the original request, response, and URI instances.
*
* This middleware will add request attributes as follows:
*
* - "originalRequest", representing the request provided to this middleware.
* - "originalResponse", representing the response provided to this middleware.
* - "originalUri", representing the URI composed by the request provided to
* this middleware.
*
* These can then be reference later, for tasks such as:
*
* - Determining the base path when generating a URI (as layers may receive
* URIs stripping path segments).
* - Determining if changes to the response have occurred.
* - Providing prototypes for factories.
*/
class OriginalMessages implements MiddlewareInterface
{
/**
* @param ServerRequestInterface $request
* @param ResponseInterface $response
* @param null|callable $next
* @return ResponseInterface
*/
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next = null)
{
if (! $next) {
return $response;
}

$request = $request
->withAttribute('originalUri', $request->getUri())
->withAttribute('originalRequest', $request)
->withAttribute('originalResponse', $response);

return $next($request, $response);
}
}
21 changes: 21 additions & 0 deletions test/Http/RequestTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,34 @@

class RequestTest extends TestCase
{
public $errorHandler;

public function setUp()
{
$this->restoreErrorHandler();
$this->errorHandler = function ($errno, $errstr) {
return (false !== strstr($errstr, Request::class . ' is now deprecated'));
};
set_error_handler($this->errorHandler, E_USER_DEPRECATED);

$psrRequest = new PsrRequest([], [], 'http://example.com/', 'GET', 'php://memory');
$this->original = $psrRequest;
$this->request = new Request($this->original);
}

public function tearDown()
{
$this->restoreErrorHandler();
}

public function restoreErrorHandler()
{
if ($this->errorHandler) {
restore_error_handler();
$this->errorHandler = null;
}
}

public function testCallingSetUriSetsUriInRequestAndOriginalRequestInClone()
{
$url = 'http://example.com/foo';
Expand Down
21 changes: 21 additions & 0 deletions test/Http/ResponseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,33 @@

class ResponseTest extends TestCase
{
public $errorHandler;

public function setUp()
{
$this->restoreErrorHandler();
$this->errorHandler = function ($errno, $errstr) {
return (false !== strstr($errstr, Response::class . ' is now deprecated'));
};
set_error_handler($this->errorHandler, E_USER_DEPRECATED);

$this->original = new PsrResponse();
$this->response = new Response($this->original);
}

public function tearDown()
{
$this->restoreErrorHandler();
}

public function restoreErrorHandler()
{
if ($this->errorHandler) {
restore_error_handler();
$this->errorHandler = null;
}
}

public function testIsNotCompleteByDefault()
{
$this->assertFalse($this->response->isComplete());
Expand Down
Loading

0 comments on commit 2f44424

Please sign in to comment.