Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New PathMiddlewareDecorator #6

Closed
2 tasks done
weierophinney opened this issue Dec 31, 2019 · 2 comments
Closed
2 tasks done

New PathMiddlewareDecorator #6

weierophinney opened this issue Dec 31, 2019 · 2 comments
Labels
Won't Fix This will not be worked on

Comments

@weierophinney
Copy link
Member

  • I was not able to find an open or closed issue matching what I'm seeing.
  • This is not a question.

I was taking a look to the PathMiddlewareDecorator for a project I'm working on, but it kinda didn't suited my needs.

  • I needed it to match a routes flexibly using regular expressions if necessary.
  • I needed it to match optionally by request route
  • I needed to decide if the middleware being decorated was going to execute if the routed matched or didn't match.

So I ended up building my own decorator. How keen are you guys of accepting a PR with it? Here's a very naive implementation:

use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface as NextHandler;

/**
 * Decorates a middleware to be executed on a router pattern match/un-match
 *
 * You can optionally pass a method to the arguments.
 *
 * @author Matías Navarro Carter <[email protected]>
 */
final class PathMiddlewareDecorator implements MiddlewareInterface
{
    public const IF_MATCHES = 1;
    public const IF_NOT_MATCHES = 0;

    /**
     * @var MiddlewareInterface
     */
    private $middleware;
    /**
     * @var int
     */
    private $executionRule;
    /**
     * @var string|string[]
     */
    private $path;
    /**
     * @var string|null
     */
    private $method;

    /**
     * PathMiddlewareDecorator constructor.
     *
     * @param MiddlewareInterface $middleware The middleware to execute.
     * @param string|string[]     $path A path pattern or an array of patterns.
     * @param string|null         $method A method to match.
     * @param int                 $executionRule The rule of execution.
     */
    public function __construct(
        MiddlewareInterface $middleware,
        $path,
        string $method = null,
        int $executionRule = self::IF_MATCHES
    ) {
        $this->middleware = $middleware;
        $this->path = $path;
        $this->method = $method;
        $this->executionRule = $executionRule;
    }

    /**
     * @param Request     $request
     * @param NextHandler $handler
     *
     * @return Response
     */
    public function process(Request $request, NextHandler $handler): Response
    {
        $match = $this->matches($request);

        if (self::IF_MATCHES === $this->executionRule && true === $match) {
            return $this->middleware->process($request, $handler);
        }
        if (self::IF_NOT_MATCHES === $this->executionRule && false === $match) {
            return $this->middleware->process($request, $handler);
        }

        return $handler->handle($request);
    }

    /**
     * @param Request $request
     *
     * @return bool
     */
    private function matches(Request $request): bool
    {
        if ($this->method && $request->getMethod() !== $this->method) {
            return false;
        }

        return $this->matchesRegex($request->getUri()->getPath(), $this->path);
    }

    /**
     * @param string $requestPath
     * @param        $pathOrPaths
     *
     * @return bool
     */
    private function matchesRegex(string $requestPath, $pathOrPaths): bool
    {
        if (is_array($pathOrPaths)) {
            foreach ($pathOrPaths as $string) {
                $result = $this->matchesRegex($requestPath, $string);
                if (true === $result) {
                    return true;
                }
            }
        }
        if (\is_string($pathOrPaths)) {
            return 0 !== preg_match('/'.str_replace('/', '\/', $pathOrPaths).'/', $requestPath);
        }

        return false;
    }
}

Of course it should be named differently to the one you guys already have. Maybe ConfigurablePathMiddlewareDecorator?


Originally posted by @mnavarrocarter at zendframework/zend-stratigility#183

@weierophinney
Copy link
Member Author

This is definitely interesting. What we'd need from you is a pull request with:

  • The above class.
  • Unit tests demonstrating the various ways it can be used.
  • Documentation
  • Potentially a helper function similar to the path() utility function for simplifying decorating middleware/handlers with this.

Submit the PR against the develop branch.

Thanks!


Originally posted by @weierophinney at zendframework/zend-stratigility#183 (comment)

@weierophinney
Copy link
Member Author

Closing.

No PR was ever provided, and users can implement this themselves if needed.

If somebody would like to see this functionality, please submit a patch for review.

@boesing boesing closed this as not planned Won't fix, can't repro, duplicate, stale May 9, 2023
@boesing boesing added the Won't Fix This will not be worked on label May 9, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Won't Fix This will not be worked on
Projects
None yet
Development

No branches or pull requests

2 participants