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

PHP 8 support #3015

Merged
merged 5 commits into from
Nov 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Slim/CallableResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ private function bindToContainer(callable $callable): callable
$callable = $callable[0];
}
if ($this->container && $callable instanceof Closure) {
/** @var Closure $callable */
$callable = $callable->bindTo($this->container);
}
return $callable;
Expand Down
19 changes: 17 additions & 2 deletions Slim/Middleware/BodyParsingMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
use function strtolower;
use function trim;

use const LIBXML_VERSION;

class BodyParsingMiddleware implements MiddlewareInterface
{
/**
Expand Down Expand Up @@ -118,11 +120,11 @@ protected function registerDefaultBodyParsers(): void
});

$xmlCallable = static function ($input) {
$backup = libxml_disable_entity_loader(true);
$backup = self::disableXmlEntityLoader(true);
$backup_errors = libxml_use_internal_errors(true);
$result = simplexml_load_string($input);

libxml_disable_entity_loader($backup);
self::disableXmlEntityLoader($backup);
libxml_clear_errors();
libxml_use_internal_errors($backup_errors);

Expand Down Expand Up @@ -188,4 +190,17 @@ protected function getMediaType(ServerRequestInterface $request): ?string

return null;
}

protected static function disableXmlEntityLoader(bool $disable): bool
{
if (LIBXML_VERSION >= 20900) {
// libxml >= 2.9.0 disables entity loading by default, so it is
// safe to skip the real call (deprecated in PHP 8).
return true;
}

// @codeCoverageIgnoreStart
return libxml_disable_entity_loader($disable);
// @codeCoverageIgnoreEnd
}
}
1 change: 1 addition & 0 deletions Slim/MiddlewareDispatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ public function addCallable(callable $middleware): self
$next = $this->tip;

if ($this->container && $middleware instanceof Closure) {
/** @var Closure $middleware */
$middleware = $middleware->bindTo($this->container);
}

Expand Down
5 changes: 4 additions & 1 deletion Slim/Routing/Route.php
Original file line number Diff line number Diff line change
Expand Up @@ -369,10 +369,13 @@ public function handle(ServerRequestInterface $request): ResponseInterface
}
$strategy = $this->invocationStrategy;

/** @var string[] $strategyImplements */
$strategyImplements = class_implements($strategy);

if (
is_array($callable)
&& $callable[0] instanceof RequestHandlerInterface
&& !in_array(RequestHandlerInvocationStrategyInterface::class, class_implements($strategy))
&& !in_array(RequestHandlerInvocationStrategyInterface::class, $strategyImplements)
) {
$strategy = new RequestHandler();
}
Expand Down
11 changes: 6 additions & 5 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,16 @@
"wiki": "https://github.com/slimphp/Slim/wiki"
},
"require": {
"php": "^7.2",
"php": "^7.2 || ^8.0",
"ext-json": "*",
"nikic/fast-route": "^1.3",
"psr/container": "^1.0",
"psr/http-factory": "^1.0",
"psr/http-message": "^1.0",
"psr/http-server-handler": "^1.0",
"psr/http-server-middleware": "^1.0",
"psr/log": "^1.1"
"psr/log": "^1.1",
"weirdan/prophecy-shim": "^1.0 || ^2.0.2"
},
"require-dev": {
"ext-simplexml": "*",
Expand All @@ -63,9 +64,9 @@
"nyholm/psr7-server": "^1.0.0",
"phpspec/prophecy": "^1.12",
"phpstan/phpstan": "^0.12.54",
"phpunit/phpunit": "^8.5",
"slim/http": "^1.1",
"slim/psr7": "^1.2",
"phpunit/phpunit": "^8.5 || ^9.3",
"slim/http": "^1.2",
"slim/psr7": "^1.3",
"squizlabs/php_codesniffer": "^3.5"
},
"autoload": {
Expand Down
32 changes: 19 additions & 13 deletions tests/Error/AbstractErrorRendererTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ public function testHTMLErrorRendererDisplaysErrorDetails()
$renderer = new HtmlErrorRenderer();
$output = $renderer->__invoke($exception, true);

$this->assertRegExp('/.*The application could not run because of the following error:.*/', $output);
$this->assertMatchesRegularExpression(
'/.*The application could not run because of the following error:.*/',
$output
);
$this->assertStringContainsString('Oops..', $output);
}

Expand All @@ -43,7 +46,10 @@ public function testHTMLErrorRendererNoErrorDetails()
$renderer = new HtmlErrorRenderer();
$output = $renderer->__invoke($exception, false);

$this->assertRegExp('/.*A website error has occurred. Sorry for the temporary inconvenience.*/', $output);
$this->assertMatchesRegularExpression(
'/.*A website error has occurred. Sorry for the temporary inconvenience.*/',
$output
);
$this->assertStringNotContainsString('Oops..', $output);
}

Expand All @@ -57,11 +63,11 @@ public function testHTMLErrorRendererRenderFragmentMethod()
$method->setAccessible(true);
$output = $method->invoke($renderer, $exception);

$this->assertRegExp('/.*Type:*/', $output);
$this->assertRegExp('/.*Code:*/', $output);
$this->assertRegExp('/.*Message*/', $output);
$this->assertRegExp('/.*File*/', $output);
$this->assertRegExp('/.*Line*/', $output);
$this->assertMatchesRegularExpression('/.*Type:*/', $output);
$this->assertMatchesRegularExpression('/.*Code:*/', $output);
$this->assertMatchesRegularExpression('/.*Message*/', $output);
$this->assertMatchesRegularExpression('/.*File*/', $output);
$this->assertMatchesRegularExpression('/.*Line*/', $output);
}

public function testHTMLErrorRendererRenderHttpException()
Expand Down Expand Up @@ -204,11 +210,11 @@ public function testPlainTextErrorRendererFormatFragmentMethod()
$method->setAccessible(true);
$output = $method->invoke($renderer, $exception);

$this->assertRegExp('/.*Type:*/', $output);
$this->assertRegExp('/.*Code:*/', $output);
$this->assertRegExp('/.*Message*/', $output);
$this->assertRegExp('/.*File*/', $output);
$this->assertRegExp('/.*Line*/', $output);
$this->assertMatchesRegularExpression('/.*Type:*/', $output);
$this->assertMatchesRegularExpression('/.*Code:*/', $output);
$this->assertMatchesRegularExpression('/.*Message*/', $output);
$this->assertMatchesRegularExpression('/.*File*/', $output);
$this->assertMatchesRegularExpression('/.*Line*/', $output);
}

public function testPlainTextErrorRendererDisplaysErrorDetails()
Expand All @@ -219,7 +225,7 @@ public function testPlainTextErrorRendererDisplaysErrorDetails()
$renderer = new PlainTextErrorRenderer();
$output = $renderer->__invoke($exception, true);

$this->assertRegExp('/Ooops.../', $output);
$this->assertMatchesRegularExpression('/Ooops.../', $output);
}

public function testPlainTextErrorRendererNotDisplaysErrorDetails()
Expand Down
20 changes: 20 additions & 0 deletions tests/MiddlewareDispatcherTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,26 @@ public function testDeferredResolvedCallableWithoutContainerAndNonAdvancedCallab
$this->assertEquals(1, $handler->getCalledCount());
}

public function testDeferredResolvedCallableWithDirectConstructorCall()
{
$callableResolverProphecy = $this->prophesize(CallableResolverInterface::class);

$callableResolverProphecy
->resolve(MockMiddlewareWithoutConstructor::class)
->willThrow(new RuntimeException('Callable not available from resolver'))
->shouldBeCalledOnce();

$handler = new MockRequestHandler();

$middlewareDispatcher = $this->createMiddlewareDispatcher($handler, null, $callableResolverProphecy->reveal());
$middlewareDispatcher->addDeferred(MockMiddlewareWithoutConstructor::class);

$request = $this->createServerRequest('/');
$middlewareDispatcher->handle($request);

$this->assertEquals(1, $handler->getCalledCount());
}

public function deferredCallableProvider()
{
return [
Expand Down
27 changes: 27 additions & 0 deletions tests/MigratePhpUnitDeprecations.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace Slim\Tests;

use PHPUnit\Framework\TestCase as PHPUnitTestCase;

if (method_exists(PHPUnitTestCase::class, 'assertMatchesRegularExpression')) {
trait MigratePhpUnitDeprecations
{

}
} else {
// @codingStandardsIgnoreStart
trait MigratePhpUnitDeprecations
{
// @codingStandardsIgnoreEnd
public static function assertMatchesRegularExpression(
string $pattern,
string $string,
string $message = ''
): void {
static::assertRegExp($pattern, $string, $message);
}
}
}
4 changes: 4 additions & 0 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
namespace Slim\Tests;

use PHPUnit\Framework\TestCase as PHPUnitTestCase;
use Prophecy\PhpUnit\ProphecyTrait;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface;
Expand All @@ -26,6 +27,9 @@

abstract class TestCase extends PhpUnitTestCase
{
use MigratePhpUnitDeprecations;
use ProphecyTrait;

/**
* @return ServerRequestFactoryInterface
*/
Expand Down