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

Deprecations and backports for 2.2.0 release #140

Merged

Conversation

weierophinney
Copy link
Member

This patch provides a number of changes for a new minor version in order to help developers prepare for the upcoming 3.0.0 release. They include:

  • Marking deprecated classes
    • Route
    • InvalidMiddlewareException
    • InvalidRequestTypeException
    • CallableDelegateDecorator
    • CallableInteropMiddlewareWrapper
    • CallableMiddlewareWrapper
    • CallableMiddlewareWrapperFactory
    • NoopFinalHandler
  • Backporting classes/functions:
    • CallableMiddlewareDecorator and the associated middleware() utility function
    • DoublePassMiddlewareDecorator and the associated doublePassMiddleware() utility function
    • PathMiddlewareDecorator and the associated path() utility function
  • Modifying internals:
    • Updating MiddlewarePipe::pipe() to:
      • trigger an E_USER_DEPRECATED error when two arguments are provided
      • decorate middleware in a PathMiddlewareDecorator instance when two arguments are provided
      • decorate PSR-15-compatible callables using CallableMiddlewareDecorator instances
      • decorate double-pass callables using DoublePassMiddlewareDecorator instances
    • Updating Route to:
      • decorate middleware in a PathMiddlewareDecorator instance when a non-root path is provided, and the middleware isn't already a decorator
    • Updating Next to:
      • remove path segregation, and instead only process middleware

These changes are mostly backwards compatible; the only ones that may affect users are the following:

  • Callables are decorated using different classes. If an extension relied on the old decorators, they will need to be updated. Since this was considered an internal detail, I'm unsure if this will or should have much impact.
  • Path segregated middleware is now decorated. Again, this should only affect extensions that were introspecting middleware in either the MiddlewarePipe, Route, or Next workflow. Again, I'm unsure if this will or should have much impact.

The patch removes some tests from Next, as they are now covered by the PathMiddlewareDecorator tests and new integration tests; existing behavior remains unchanged, however.

Finally, all changes are documented, with recommendations on how to prepare your application to remain compatible for version 3.

This patch marks as deprecated classes we plan to remove in version
3.0.0.
This patch backports the following classes from the release-3.0.0
development series:

- `Zend\Stratigility\Middleware\CallableMiddlewareDecorator`, for
  decorating middleware that follows the PSR-15 signature.
- `Zend\Stratigility\Middleware\DoublePassMiddlewareDecorator`, for
  decorating callable middleware that follows the double pass middleware
  signature.
- `Zend\Stratigility\Middleware\PathMiddlewareDecorator`, for providing
  path-segregated middleware. This required also extracting the class
  `Zend\Stratigility\Middleware\PathRequestHandlerDecorator`, which is
  used internally in order to decorate the request handler passed to
  middleware it decorates.

All classes and their were updated to adapt to the
http-middleware-compatibility shims.
This patch deprecates using the two-argument form of
`MiddlewarePipe::pipe()` in favor of using a `PathMiddlewareDecorator`
instance instead. It accomplishes this via the following:

- When a non-empty, non-root path argument is provided along with
  middleware, `MiddlewarePipe::pipe()` will trigger an
  `E_USER_DEPRECATED` error to notify the user that path segregation
  should be accomplished using the `PathMiddlewareDecorator`.
- When `MiddlewarePipe::pipe()` is called with two arguments, the
  path argument is not a root path, and the middleware is not a
  `PathMiddlewareDecorator` instance, it will be decorated as one.
- The constructor of `Route` will trigger an `E_USER_DEPRECATED` error
  if a non root path argument is provided with a
  non-`PathMiddlewareDecorator` middleware instance. It will then
  decorate the middleware in a `PathMiddlewareDecorator` instance.
- `Next` no longer handles path segregation internally.

The changes to `Next` are _almost_ a BC break. However, it includes some
code to cast `Route` instances that represent path-segregated middleware
to `PathMiddlewareDecorator` instances in the case that they are not
already (which can only happen with custom extensions). As such,
behavior is retained with this patch.

In updating tests, I discovered some edge cases to using the
`PathMiddlewareDecorator` approach; in particular, a path-segregated
middleware should be able to propagate changes to the request when
calling the handler passed to it. As such, the
`PathRequestHandlerDecorator` now updates the request URI with the path
from the original request URI only.
This patch updates the logic in `MiddlewarePipe` as follows:

- Detection of callable middleware, either interop or double-pass, now
  triggers an `E_USER_DEPRECATED` error indicating that this feature is
  deprecated, and that users should decorate their middleware before
  passing it to `pipe()`, recommending the backported decorator classes.
- By default, decoration of interop middleware is now done with a
  `CallableMiddlewareDecorator` instance.
- By default, decoration of double-pass middleware is now done with a
  `DoublePassMiddlewareDecorator` instance, unless a
  `CallableMiddlewareWrapperFactory` is composed.

Tests were refactored to decorate callable middleware when not testing
the decoration features. When testing the decoration features, tests
were updated to detect emission of the deprecation notices.

The `RouteTest` was updated to follow the same patterns as used in the
`MiddlewarePipeTest` for detection of the deprecation notice in order to
remove the necessity to close over a reference.
In particular, `__invoke()` double-pass middleware implementations.
This patch updates the documentation to use examples that follow current
code and standards. This includes:

- Using standards-based signatures _everywhere_, except when detailing
  what the double pass signature is.
- Updating the "Creating Middleware" chapter to emphasize
  standards-based middleware over double-pass middleware, and the
  proposed v2.2.0 middleware decorators over the legacy middleware
  "wrappers". (A similar approach was used in the API chapter.)
- Using the `PathMiddlewareDecorator` when demonstrating how to
  segregate middleware by path.
- Removing redundant discussion of http-interop, and pushing it into a
  single location, the Creating Middleware chapter.
- `path()` for creating `PathMiddlewareDecorator` instances.
- `middleware()` for creating `CallableMiddlewareDecorator` instances.
- `doublePassMiddleware()` for creating `DoublePassMiddlewareDecorator` instances.
docs/book/api.md Outdated
- Deprecated since 2.2.0

This is a middleware decorator for PHP callables that have a signature
compatible with http-interop/http-middleware version 0.4.1. Please see the
Copy link
Member

Choose a reason for hiding this comment

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

and 0.5.0 since 2.1.0

docs/book/api.md Outdated
````
function Zend\Stratigility\path(
string $pathPrefix,
Interop\Http\Server\MiddlewareInterface $middleware
Copy link
Member

Choose a reason for hiding this comment

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

If so it's compatible only with http-interoop 0.5.0

Copy link
Member Author

Choose a reason for hiding this comment

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

I'll update this to use the polyfill interfaces; the decorator classes already do.


Stratigility provides the following utility functions.

### path
Copy link
Member

Choose a reason for hiding this comment

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

should we quote function name with `?

Copy link
Member Author

Choose a reason for hiding this comment

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

Not in headers.

>
> The `CallableInteropMiddlewareWrapper` is deprecated starting in version
> 2.2.0, and will be removed entirely for version 3.0.0. We recommend updating
> your code to use http-middleware 0.5.0 and the `CallableMiddlewareDecorator`
Copy link
Member

Choose a reason for hiding this comment

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

It's not possible with expressive to update to 0.5.0 because we never released expressive compatible with http-interop 0.5.0.

Copy link
Member Author

Choose a reason for hiding this comment

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

I think we'll need to provide a new minor release of Expressive that allows this. That said, the decorator will also work with 0.4.1, so I'll also update this description.

Copy link
Member

Choose a reason for hiding this comment

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

you mean expressive v2 with support of http-interop 0.5.0 ? 😱


Our first double-pass middleware decorator is
`Zend\Stratigility\Middleware\CallableMiddlewareWrapper`, which implements the
http-middleware 0.4.1 `MiddlewareInterface`:
Copy link
Member

Choose a reason for hiding this comment

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

It works also with 0.5.0

* @dataProvider nestedPathCombinations
*/
public function testNestedMiddlewareOnlyMatchesAtPathBoundaries(
string $prefix,
Copy link
Member

Choose a reason for hiding this comment

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

we can't use these typehints as long as we support also PHP 5.6 in version 2.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yep, already fixed this in another commit that's been pushed, along with a number of anonymous class declarations.

/**
* @param string $pathPrefix
* @param string $path
* @return self
Copy link
Member

Choose a reason for hiding this comment

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

What about @internal annotation? Do we have this method in v3?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, the method is there as well.

I can see other use cases for this, particularly if you were to create routing middleware that operates similarly. As such, I'd rather not mark it internal at this time.

<?php
/**
* @see https://github.com/zendframework/zend-stratigility for the canonical source repository
* @copyright Copyright (c) 2017 Zend Technologies USA Inc. (http://www.zend.com)
Copy link
Member

Choose a reason for hiding this comment

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

2018 and https link

Copy link
Member Author

Choose a reason for hiding this comment

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

This branch uses the http, not https, scheme in the docheader. I'll update those in a later PR.

I'll update the dates for the new classes momentarily.

/**
* @param string $segment
* @param string $path
* @return string
Copy link
Member

Choose a reason for hiding this comment

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

missing @throws annotation (Exception\PathOutOfSyncException)

Copy link
Member Author

Choose a reason for hiding this comment

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

Added.

src/Next.php Outdated
if ('/' === substr($segment, -1)) {
// Re-try by submitting with / stripped from end of segment
return $this->getTruncatedPath(rtrim($segment, '/'), $path);
if (! in_array($path, ['', '/'])
Copy link
Member

Choose a reason for hiding this comment

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

why it's not strict ? (3rd param to true)

external router instance to attempt to route a request and delegate to the
middleware matched.

## MiddlewareInterface
Copy link
Member

Choose a reason for hiding this comment

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

PSR-15 MiddlewareInterface or Stratigility MiddlewareInterface?

Copy link
Member Author

Choose a reason for hiding this comment

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

Standards one; Stratigility's was deprecated prior to 2.0, and no longer consumed as of that version. The narrative only mentions the proposed standard versions.

Updates backported code and related tests to ensure it tests correctly
against PHP versions not supported by the release-3.0.0 branch but
currently supported by the develop branch.
This allows it to be used with either the 0.4.1 or 0.5.0 versions of
http-interop/http-middleware.
- Removes unnecessary aliases
- Use strict flag with `in_array`
- Ensure `@throws` annotations are present
- New revisions of malukenho/docheader require symfony/console, and thus
  we need to ensure that we get a version of that dep that satisfies our
  current PHP version.
- Do not define a composer script for it, as it is not a defined dependency of the shipped package
- Use the new package name (php-coveralls/php-coveralls, vs satooshi/php-coveralls)
- Update the invocation of the script within the travis configuration
@weierophinney weierophinney added this to the 2.2.0 milestone Jan 16, 2018
@@ -207,6 +241,19 @@ you will need to:
- Create and return a concrete response type, OR
- Operate on a response returned by invoking the delegate.

### RequestHandler invocation

- Since 2.1.0
Copy link
Member

Choose a reason for hiding this comment

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

Hm, 2.1.0 or 2.2.0 ?

Copy link
Member Author

Choose a reason for hiding this comment

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

That's been since 2.1.0, when we started supporting http-interop 0.5.0.

src/Route.php Outdated
@@ -43,6 +45,19 @@ public function __construct($path, ServerMiddlewareInterface $handler)
}

$this->path = $path;

if (! in_array($this->path, ['', '/'])
Copy link
Member

Choose a reason for hiding this comment

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

strict mode please

Adds unit tests to cover all behaviors of CallableDelegateDecorator.
Each of `__invoke()`, `process()`, and `next()` are deprecated, and
removed in v3.0.0.
A major change such as this one should not decrease code quality. As
such, adds tests and/or `@codeCoverageIgnore` annotations in order to
boost coverage.

Also marks an entire class to ignore for the coverage report, as testing
that class is unnecessary.
@weierophinney weierophinney merged commit e3711a6 into zendframework:develop Jan 25, 2018
weierophinney added a commit that referenced this pull request Jan 25, 2018
weierophinney added a commit that referenced this pull request Jan 25, 2018
@weierophinney weierophinney deleted the feature/deprecations branch January 25, 2018 22:02
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants