protected function checkPublicStaticCallable(
        $callable,
        array $parameters = [],
        string $returnType = null
    ): bool {
        /** @var callable|array|string $callable */

        // first of all check input is callable (class, method) in form of array or string...
        if (is_callable($callable) && is_string($callable) === true && strpos($callable, '::') !== false) {
            list ($class, $method) = explode('::', $callable, 2);
        } elseif (is_callable($callable) &&
            is_array($callable) === true &&
            count($callable) === 2 &&
            is_string($class = $callable[0]) &&
            is_string($method = $callable[1])
        ) {
        } else {
            return false;
        }

        $reflectionMethod = new ReflectionMethod($class, $method);
        unset($class);
        unset($method);

        // now check it's public and static
        if ($reflectionMethod->isPublic() !== true || $reflectionMethod->isStatic() !== true) {
            return false;
        }

        // then check method parameters...
        $methodParams = $reflectionMethod->getParameters();
        if (count($methodParams) > count($parameters)) {
            return false;
        }

        $index          = 0;
        $areAllParamsOk = true;
        foreach ($parameters as $parameter) {
            if ($index >= count($methodParams)) {
                continue;
            }

            $isParamOk   = true;
            $methodParam = $methodParams[$index];
            if (is_string($parameter) === true) {
                $methodType = $methodParam->getType();
                if ($methodType === null || (string)$methodType !== $parameter) {
                    $isParamOk = false;
                }
            } elseif ($parameter === null) {
                if ($methodParam->getType() !== null) {
                    $isParamOk = false;
                }
            } elseif ($parameter instanceof Closure) {
                $isOk = $parameter($methodParam);
                if ($isOk !== true) {
                    $isParamOk = false;
                }
            } else {
                throw new InvalidArgumentException('Parameters should be either strings or Closures.');
            }

            if ($isParamOk !== true) {
                $areAllParamsOk = false;
                break;
            }

            $index++;
        }

        // ... and return type
        $isReturnTypeOk = true;
        if ($areAllParamsOk === true && $returnType !== null) {
            $methodRetType  = $reflectionMethod->getReturnType();
            $isReturnTypeOk = $methodRetType !== null && (string)$methodRetType === $returnType;
        }

        $isOk = $areAllParamsOk === true && $isReturnTypeOk === true;

        if ($isOk === false) {
            // you can put here a breakpoint and see the failed condition
            $callable || $areAllParamsOk || $isReturnTypeOk ?: null;
        }

        return $isOk;
    }