diff --git a/composer.json b/composer.json
index 7b18724..43e4a5f 100644
--- a/composer.json
+++ b/composer.json
@@ -31,8 +31,12 @@
"ext-json": "*"
},
"require-dev": {
- "phpunit/phpunit": "^7",
- "mockery/mockery": "^1"
+ "phpunit/phpunit": "^8",
+ "mockery/mockery": "^1",
+ "phpstan/phpstan": "^0",
+ "phpstan/phpstan-phpunit": "^0",
+ "phpstan/phpstan-deprecation-rules": "^0",
+ "phpstan/phpstan-strict-rules": "^0"
},
"scripts": {
"test": [
@@ -44,4 +48,4 @@
"Pecee\\": "src/Pecee/"
}
}
-}
+}
\ No newline at end of file
diff --git a/phpstan.neon b/phpstan.neon
new file mode 100644
index 0000000..3719f4a
--- /dev/null
+++ b/phpstan.neon
@@ -0,0 +1,22 @@
+parameters:
+ level: 6
+ paths:
+ - src
+ fileExtensions:
+ - php
+ bootstrapFiles:
+ - ./vendor/autoload.php
+ ignoreErrors:
+ reportUnmatchedIgnoredErrors: true
+ checkMissingIterableValueType: false
+ checkGenericClassInNonGenericObjectType: false
+ parallel:
+ processTimeout: 300.0
+ jobSize: 10
+ maximumNumberOfProcesses: 4
+ minimumNumberOfJobsPerProcess: 4
+includes:
+ - vendor/phpstan/phpstan-strict-rules/rules.neon
+ - vendor/phpstan/phpstan-phpunit/extension.neon
+ - vendor/phpstan/phpstan-phpunit/rules.neon
+ - vendor/phpstan/phpstan-deprecation-rules/rules.neon
\ No newline at end of file
diff --git a/src/Pecee/Http/Input/IInputItem.php b/src/Pecee/Http/Input/IInputItem.php
index 0c851c8..430b557 100644
--- a/src/Pecee/Http/Input/IInputItem.php
+++ b/src/Pecee/Http/Input/IInputItem.php
@@ -13,8 +13,14 @@ interface IInputItem
public function setName(string $name): self;
+ /**
+ * @return mixed
+ */
public function getValue();
+ /**
+ * @param mixed $value
+ */
public function setValue($value): self;
public function __toString(): string;
diff --git a/src/Pecee/Http/Input/InputHandler.php b/src/Pecee/Http/Input/InputHandler.php
index e909382..8cbfae7 100644
--- a/src/Pecee/Http/Input/InputHandler.php
+++ b/src/Pecee/Http/Input/InputHandler.php
@@ -115,7 +115,7 @@ class InputHandler
// Handle array input
if (is_array($value['name']) === false) {
- $values['index'] = $parentKey ?? $key;
+ $values = ['index' => $parentKey ?? $key];
try {
$list[$key] = InputFile::createFromArray($values + $value);
@@ -161,7 +161,7 @@ class InputHandler
try {
$file = InputFile::createFromArray([
- 'index' => (empty($key) === true && empty($originalIndex) === false) ? $originalIndex : $key,
+ 'index' => ($key === '' && $originalIndex !== '') ? $originalIndex : $key,
'name' => $original['name'][$key],
'error' => $original['error'][$key],
'tmp_name' => $original['tmp_name'][$key],
diff --git a/src/Pecee/Http/Request.php b/src/Pecee/Http/Request.php
index 4c5ee42..12ede38 100644
--- a/src/Pecee/Http/Request.php
+++ b/src/Pecee/Http/Request.php
@@ -137,7 +137,7 @@ class Request
public function isSecure(): bool
{
- return $this->getHeader('http-x-forwarded-proto') === 'https' || $this->getHeader('https') !== null || $this->getHeader('server-port') === 443;
+ return $this->getHeader('http-x-forwarded-proto') === 'https' || $this->getHeader('https') !== null || (int)$this->getHeader('server-port') === 443;
}
/**
diff --git a/src/Pecee/Http/Url.php b/src/Pecee/Http/Url.php
index d856a54..3df21e2 100644
--- a/src/Pecee/Http/Url.php
+++ b/src/Pecee/Http/Url.php
@@ -387,7 +387,7 @@ class Url implements JsonSerializable
{
$encodedUrl = preg_replace_callback(
'/[^:\/@?&=#]+/u',
- static function ($matches) {
+ static function ($matches): string {
return urlencode($matches[0]);
},
$url
@@ -414,7 +414,7 @@ class Url implements JsonSerializable
if (count($getParams) !== 0) {
if ($includeEmpty === false) {
- $getParams = array_filter($getParams, static function ($item) {
+ $getParams = array_filter($getParams, static function ($item): bool {
return (trim($item) !== '');
});
}
@@ -458,7 +458,7 @@ class Url implements JsonSerializable
$port = $this->port !== null ? ':' . $this->port : '';
$user = $this->username ?? '';
$pass = $this->password !== null ? ':' . $this->password : '';
- $pass = ($user || $pass) ? $pass . '@' : '';
+ $pass = ($user !== '' || $pass !== '') ? $pass . '@' : '';
return $scheme . $user . $pass . $host . $port . $this->getRelativeUrl($includeParams);
}
@@ -466,7 +466,7 @@ class Url implements JsonSerializable
/**
* Specify data which should be serialized to JSON
* @link http://php.net/manual/en/jsonserializable.jsonserialize.php
- * @return mixed data which can be serialized by json_encode,
+ * @return string data which can be serialized by json_encode,
* which is a value of any type other than a resource.
* @since 5.4.0
*/
diff --git a/src/Pecee/SimpleRouter/Handlers/DebugEventHandler.php b/src/Pecee/SimpleRouter/Handlers/DebugEventHandler.php
index 92ff158..37eae16 100644
--- a/src/Pecee/SimpleRouter/Handlers/DebugEventHandler.php
+++ b/src/Pecee/SimpleRouter/Handlers/DebugEventHandler.php
@@ -17,7 +17,7 @@ class DebugEventHandler implements IEventHandler
public function __construct()
{
- $this->callback = static function (EventArgument $argument) {
+ $this->callback = static function (EventArgument $argument): void {
// todo: log in database
};
}
diff --git a/src/Pecee/SimpleRouter/Route/IControllerRoute.php b/src/Pecee/SimpleRouter/Route/IControllerRoute.php
index f5c879b..35e065e 100644
--- a/src/Pecee/SimpleRouter/Route/IControllerRoute.php
+++ b/src/Pecee/SimpleRouter/Route/IControllerRoute.php
@@ -2,7 +2,7 @@
namespace Pecee\SimpleRouter\Route;
-interface IControllerRoute extends IRoute
+interface IControllerRoute extends ILoadableRoute
{
/**
* Get controller class-name
diff --git a/src/Pecee/SimpleRouter/Route/Route.php b/src/Pecee/SimpleRouter/Route/Route.php
index 62da265..0932f31 100644
--- a/src/Pecee/SimpleRouter/Route/Route.php
+++ b/src/Pecee/SimpleRouter/Route/Route.php
@@ -67,7 +67,7 @@ abstract class Route implements IRoute
/* Filter parameters with null-value */
if ($this->filterEmptyParams === true) {
- $parameters = array_filter($parameters, static function ($var) {
+ $parameters = array_filter($parameters, static function ($var): bool {
return ($var !== null);
});
}
@@ -82,6 +82,7 @@ abstract class Route implements IRoute
}
/* When the callback is a function */
+
return $router->getClassLoader()->loadClosure($callback, $parameters);
}
@@ -280,7 +281,7 @@ abstract class Route implements IRoute
}
/**
- * @return string|callable
+ * @return string|callable|null
*/
public function getCallback()
{
@@ -337,6 +338,11 @@ abstract class Route implements IRoute
*/
public function setNamespace(string $namespace): IRoute
{
+ // Do not set namespace when class-hinting is used
+ if (is_array($this->callback) === true) {
+ return $this;
+ }
+
$ns = $this->getNamespace();
if ($ns !== null) {
diff --git a/src/Pecee/SimpleRouter/Route/RouteController.php b/src/Pecee/SimpleRouter/Route/RouteController.php
index 6c269b7..88c6597 100644
--- a/src/Pecee/SimpleRouter/Route/RouteController.php
+++ b/src/Pecee/SimpleRouter/Route/RouteController.php
@@ -52,7 +52,7 @@ class RouteController extends LoadableRoute implements IControllerRoute
public function findUrl(?string $method = null, $parameters = null, ?string $name = null): string
{
if (strpos($name, '.') !== false) {
- $found = array_search(substr($name, strrpos($name, '.') + 1), $this->names, false);
+ $found = array_search(substr($name, strrpos($name, '.') + 1), $this->names, true);
if ($found !== false) {
$method = (string)$found;
}
@@ -67,7 +67,7 @@ class RouteController extends LoadableRoute implements IControllerRoute
foreach (Request::$requestTypes as $requestType) {
if (stripos($method, $requestType) === 0) {
- $method = (string)substr($method, strlen($requestType));
+ $method = substr($method, strlen($requestType));
break;
}
}
diff --git a/src/Pecee/SimpleRouter/Route/RouteResource.php b/src/Pecee/SimpleRouter/Route/RouteResource.php
index 5bbd41e..f8be0b7 100644
--- a/src/Pecee/SimpleRouter/Route/RouteResource.php
+++ b/src/Pecee/SimpleRouter/Route/RouteResource.php
@@ -54,7 +54,7 @@ class RouteResource extends LoadableRoute implements IControllerRoute
/* Remove method/type */
if (strpos($name, '.') !== false) {
- $name = (string)substr($name, 0, strrpos($name, '.'));
+ $name = substr($name, 0, strrpos($name, '.'));
}
return (strtolower($this->name) === strtolower($name));
@@ -68,7 +68,7 @@ class RouteResource extends LoadableRoute implements IControllerRoute
*/
public function findUrl(?string $method = null, $parameters = null, ?string $name = null): string
{
- $url = array_search($name, $this->names, false);
+ $url = array_search($name, $this->names, true);
if ($url !== false) {
return rtrim($this->url . $this->urls[$url], '/') . '/';
}
diff --git a/src/Pecee/SimpleRouter/Router.php b/src/Pecee/SimpleRouter/Router.php
index 6225479..37b979a 100644
--- a/src/Pecee/SimpleRouter/Router.php
+++ b/src/Pecee/SimpleRouter/Router.php
@@ -44,7 +44,7 @@ class Router
/**
* List of processed routes
- * @var array
+ * @var array|ILoadableRoute[]
*/
protected $processedRoutes = [];
@@ -63,7 +63,7 @@ class Router
/**
* Csrf verifier class
- * @var BaseCsrfVerifier
+ * @var BaseCsrfVerifier|null
*/
protected $csrfVerifier;
@@ -107,7 +107,7 @@ class Router
/**
* Class loader instance
- * @var ClassLoader
+ * @var IClassLoader
*/
protected $classLoader;
@@ -215,7 +215,7 @@ class Router
$exceptionHandlers = [];
// Stop processing routes if no valid route is found.
- if ($this->request->getRewriteRoute() === null && $this->request->getUrl() === null) {
+ if ($this->request->getRewriteRoute() === null && $this->request->getUrl()->getOriginalUrl() === '') {
$this->debug('Halted route-processing as no valid route was found');
return;
@@ -575,7 +575,6 @@ class Router
'name' => $name,
]);
- /* @var $route ILoadableRoute */
foreach ($this->processedRoutes as $route) {
/* Check if the name matches with a name on the route. Should match either router alias or controller alias. */
@@ -593,7 +592,7 @@ class Router
}
/* Using @ is most definitely a controller@method or alias@method */
- if (is_string($name) === true && strpos($name, '@') !== false) {
+ if (strpos($name, '@') !== false) {
[$controller, $method] = array_map('strtolower', explode('@', $name));
if ($controller === strtolower($route->getClass()) && $method === strtolower($route->getMethod())) {
@@ -605,7 +604,7 @@ class Router
/* Check if callback matches (if it's not a function) */
$callback = $route->getCallback();
- if (is_string($name) === true && is_string($callback) === true && is_callable($callback) === false && strpos($name, '@') !== false && strpos($callback, '@') !== false) {
+ if (is_string($callback) === true && is_callable($callback) === false && strpos($name, '@') !== false && strpos($callback, '@') !== false) {
/* Check if the entire callback is matching */
if (strpos($callback, $name) === 0 || strtolower($callback) === strtolower($name)) {
@@ -656,10 +655,6 @@ class Router
'getParams' => $getParams,
]);
- if ($getParams !== null && is_array($getParams) === false) {
- throw new InvalidArgumentException('Invalid type for getParams. Must be array or null');
- }
-
if ($name === '' && $parameters === '') {
return new Url('/');
}
@@ -703,21 +698,21 @@ class Router
/* Loop through all the routes to see if we can find a match */
/* @var $route ILoadableRoute */
- foreach ($this->processedRoutes as $route) {
+ foreach ($this->processedRoutes as $processedRoute) {
/* Check if the route contains the name/alias */
- if ($route->hasName($controller) === true) {
+ if ($processedRoute->hasName($controller) === true) {
return $this->request
->getUrlCopy()
- ->setPath($route->findUrl($method, $parameters, $name))
+ ->setPath($processedRoute->findUrl($method, $parameters, $name))
->setParams($getParams);
}
/* Check if the route controller is equal to the name */
- if ($route instanceof IControllerRoute && strtolower($route->getController()) === strtolower($controller)) {
+ if ($processedRoute instanceof IControllerRoute && strtolower($processedRoute->getController()) === strtolower($controller)) {
return $this->request
->getUrlCopy()
- ->setPath($route->findUrl($method, $parameters, $name))
+ ->setPath($processedRoute->findUrl($method, $parameters, $name))
->setParams($getParams);
}
@@ -842,7 +837,7 @@ class Router
/**
* Get class loader
*
- * @return ClassLoader
+ * @return IClassLoader
*/
public function getClassLoader(): IClassLoader
{
diff --git a/src/Pecee/SimpleRouter/SimpleRouter.php b/src/Pecee/SimpleRouter/SimpleRouter.php
index 187a398..36aa73f 100644
--- a/src/Pecee/SimpleRouter/SimpleRouter.php
+++ b/src/Pecee/SimpleRouter/SimpleRouter.php
@@ -22,6 +22,7 @@ use Pecee\SimpleRouter\Exceptions\HttpException;
use Pecee\SimpleRouter\Handlers\CallbackExceptionHandler;
use Pecee\SimpleRouter\Handlers\IEventHandler;
use Pecee\SimpleRouter\Route\IGroupRoute;
+use Pecee\SimpleRouter\Route\ILoadableRoute;
use Pecee\SimpleRouter\Route\IPartialGroupRoute;
use Pecee\SimpleRouter\Route\IRoute;
use Pecee\SimpleRouter\Route\RouteController;
@@ -173,7 +174,7 @@ class SimpleRouter
*/
public static function redirect(string $where, string $to, int $httpCode = 301): IRoute
{
- return static::get($where, function () use ($to, $httpCode) {
+ return static::get($where, static function () use ($to, $httpCode): void {
static::response()->redirect($to, $httpCode);
});
}
@@ -185,7 +186,7 @@ class SimpleRouter
* @param string|array|Closure $callback
* @param array|null $settings
*
- * @return RouteUrl
+ * @return RouteUrl|IRoute
*/
public static function get(string $url, $callback, array $settings = null): IRoute
{
@@ -198,7 +199,7 @@ class SimpleRouter
* @param string $url
* @param string|array|Closure $callback
* @param array|null $settings
- * @return RouteUrl
+ * @return RouteUrl|IRoute
*/
public static function post(string $url, $callback, array $settings = null): IRoute
{
@@ -211,7 +212,7 @@ class SimpleRouter
* @param string $url
* @param string|array|Closure $callback
* @param array|null $settings
- * @return RouteUrl
+ * @return RouteUrl|IRoute
*/
public static function put(string $url, $callback, array $settings = null): IRoute
{
@@ -224,7 +225,7 @@ class SimpleRouter
* @param string $url
* @param string|array|Closure $callback
* @param array|null $settings
- * @return RouteUrl
+ * @return RouteUrl|IRoute
*/
public static function patch(string $url, $callback, array $settings = null): IRoute
{
@@ -237,7 +238,7 @@ class SimpleRouter
* @param string $url
* @param string|array|Closure $callback
* @param array|null $settings
- * @return RouteUrl
+ * @return RouteUrl|IRoute
*/
public static function options(string $url, $callback, array $settings = null): IRoute
{
@@ -250,7 +251,7 @@ class SimpleRouter
* @param string $url
* @param string|array|Closure $callback
* @param array|null $settings
- * @return RouteUrl
+ * @return RouteUrl|IRoute
*/
public static function delete(string $url, $callback, array $settings = null): IRoute
{
@@ -262,15 +263,11 @@ class SimpleRouter
*
* @param array $settings
* @param Closure $callback
- * @return RouteGroup
+ * @return RouteGroup|IGroupRoute
* @throws InvalidArgumentException
*/
public static function group(array $settings, Closure $callback): IGroupRoute
{
- if (is_callable($callback) === false) {
- throw new InvalidArgumentException('Invalid callback provided. Only functions or methods supported');
- }
-
$group = new RouteGroup();
$group->setCallback($callback);
$group->setSettings($settings);
@@ -287,15 +284,11 @@ class SimpleRouter
* @param string $url
* @param Closure $callback
* @param array $settings
- * @return RoutePartialGroup
+ * @return RoutePartialGroup|IPartialGroupRoute
* @throws InvalidArgumentException
*/
public static function partialGroup(string $url, Closure $callback, array $settings = []): IPartialGroupRoute
{
- if (is_callable($callback) === false) {
- throw new InvalidArgumentException('Invalid callback provided. Only functions or methods supported');
- }
-
$settings['prefix'] = $url;
$group = new RoutePartialGroup();
@@ -313,7 +306,7 @@ class SimpleRouter
* @param string $url
* @param string|array|Closure $callback
* @param array|null $settings
- * @return RouteUrl
+ * @return RouteUrl|IRoute
* @see SimpleRouter::form
*/
public static function basic(string $url, $callback, array $settings = null): IRoute
@@ -328,7 +321,7 @@ class SimpleRouter
* @param string $url
* @param string|array|Closure $callback
* @param array|null $settings
- * @return RouteUrl
+ * @return RouteUrl|IRoute
* @see SimpleRouter::form
*/
public static function form(string $url, $callback, array $settings = null): IRoute
@@ -499,7 +492,7 @@ class SimpleRouter
/**
* Prepends the default namespace to all new routes added.
*
- * @param IRoute $route
+ * @param ILoadableRoute|IRoute $route
* @return IRoute
*/
public static function addDefaultNamespace(IRoute $route): IRoute
diff --git a/tests/Pecee/SimpleRouter/Dummy/NSController.php b/tests/Pecee/SimpleRouter/Dummy/NSController.php
new file mode 100644
index 0000000..fe8e33e
--- /dev/null
+++ b/tests/Pecee/SimpleRouter/Dummy/NSController.php
@@ -0,0 +1,11 @@
+assertTrue(true);
}
+ public function testDefaultNameSpaceOverload()
+ {
+ TestRouter::setDefaultNamespace('DefaultNamespace\\Controllers');
+ TestRouter::get('/test', [\MyNamespace\NSController::class, 'method']);
+
+ $result = TestRouter::debugOutput('/test');
+
+ $this->assertTrue( (bool)$result);
+ }
+
public function testSameRoutes()
{
TestRouter::get('/recipe', 'DummyController@method1')->name('add');
diff --git a/tests/TestRouter.php b/tests/TestRouter.php
index 1a1b4c1..79509df 100644
--- a/tests/TestRouter.php
+++ b/tests/TestRouter.php
@@ -22,12 +22,14 @@ class TestRouter extends \Pecee\SimpleRouter\SimpleRouter
{
try {
static::debugNoReset($testUrl, $testMethod);
- } catch(\Exception $e) {
+ } catch (\Exception $e) {
+ static::$defaultNamespace = null;
static::router()->reset();
throw $e;
}
- if($reset === true) {
+ if ($reset === true) {
+ static::$defaultNamespace = null;
static::router()->reset();
}