Skip to content

Commit

Permalink
Merge remote-tracking branch 'dingo/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
crynobone committed Apr 2, 2018
2 parents 413fa11 + 1422535 commit b26469e
Show file tree
Hide file tree
Showing 3 changed files with 304 additions and 3 deletions.
246 changes: 243 additions & 3 deletions src/Http/FormRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,145 @@

namespace Dingo\Api\Http;

use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Laravel\Lumen\Http\Redirector;
use Illuminate\Contracts\Container\Container;
use Illuminate\Contracts\Validation\Validator;
use Dingo\Api\Exception\ValidationHttpException;
use Illuminate\Validation\ValidatesWhenResolvedTrait;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Illuminate\Foundation\Http\FormRequest as IlluminateFormRequest;
use Illuminate\Contracts\Validation\ValidatesWhenResolved;
use Illuminate\Contracts\Validation\Factory as ValidationFactory;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;

class FormRequest extends IlluminateFormRequest
class FormRequest extends Request implements ValidatesWhenResolved
{
use ValidatesWhenResolvedTrait;

/**
* The container instance.
*
* @var \Illuminate\Contracts\Container\Container
*/
protected $container;

/**
* The redirector instance.
*
* @var \Illuminate\Routing\Redirector
*/
protected $redirector;

/**
* The URI to redirect to if validation fails.
*
* @var string
*/
protected $redirect;

/**
* The route to redirect to if validation fails.
*
* @var string
*/
protected $redirectRoute;

/**
* The controller action to redirect to if validation fails.
*
* @var string
*/
protected $redirectAction;

/**
* The key to be used for the view error bag.
*
* @var string
*/
protected $errorBag = 'default';

/**
* The input keys that should not be flashed on redirect.
*
* @var array
*/
protected $dontFlash = [
'password',
'password_confirmation',
];

/**
* Validate the request.
*/
public function validate()
{
if ($this->authorize() === false) {
throw new AccessDeniedHttpException();
}

$validator = app('validator')->make($this->all(), $this->rules(), $this->messages());

if ($validator->fails()) {
throw new ValidationHttpException($validator->errors());
}
}

/**
* Get the validator instance for the request.
*
* @return \Illuminate\Contracts\Validation\Validator
*
* @SuppressWarnings(PHPMD.ElseExpression)
*/
protected function getValidatorInstance()
{
$factory = $this->container->make(ValidationFactory::class);

if (method_exists($this, 'validator')) {
$validator = $this->container->call([$this, 'validator'], compact('factory'));
} else {
$validator = $this->createDefaultValidator($factory);
}

if (method_exists($this, 'withValidator')) {
$this->withValidator($validator);
}

return $validator;
}

/**
* Create the default validator instance.
*
* @param \Illuminate\Contracts\Validation\Factory $factory
*
* @return \Illuminate\Contracts\Validation\Validator
*/
protected function createDefaultValidator(ValidationFactory $factory)
{
return $factory->make(
$this->validationData(),
$this->container->call([$this, 'rules']),
$this->messages(),
$this->attributes()
);
}

/**
* Get data to be validated from the request.
*
* @return array
*/
protected function validationData()
{
return $this->all();
}

/**
* Handle a failed validation attempt.
*
* @param \Illuminate\Contracts\Validation\Validator $validator
* @param \Illuminate\Contracts\Validation\Validator $validator
*
* @return void
*/
Expand All @@ -25,6 +153,70 @@ protected function failedValidation(Validator $validator)
parent::failedValidation($validator);
}

/**
* Get the proper failed validation response for the request.
*
* @param array $errors
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function response(array $errors)
{
if ($this->expectsJson()) {
return new JsonResponse($errors, 422);
}

return $this->redirector->to($this->getRedirectUrl())
->withInput($this->except($this->dontFlash))
->withErrors($errors, $this->errorBag);
}

/**
* Format the errors from the given Validator instance.
*
* @param \Illuminate\Contracts\Validation\Validator $validator
*
* @return array
*/
protected function formatErrors(Validator $validator)
{
return $validator->getMessageBag()->toArray();
}

/**
* Get the URL to redirect to on a validation error.
*
* @return string
*/
protected function getRedirectUrl()
{
$url = $this->redirector->getUrlGenerator();

if ($this->redirect) {
return $url->to($this->redirect);
} elseif ($this->redirectRoute) {
return $url->route($this->redirectRoute);
} elseif ($this->redirectAction) {
return $url->action($this->redirectAction);
}

return $url->previous();
}

/**
* Determine if the request passes the authorization check.
*
* @return bool
*/
protected function passesAuthorization()
{
if (method_exists($this, 'authorize')) {
return $this->container->call([$this, 'authorize']);
}

return false;
}

/**
* Handle a failed authorization attempt.
*
Expand All @@ -38,4 +230,52 @@ protected function failedAuthorization()

parent::failedAuthorization();
}

/**
* Get custom messages for validator errors.
*
* @return array
*/
public function messages()
{
return [];
}

/**
* Get custom attributes for validator errors.
*
* @return array
*/
public function attributes()
{
return [];
}

/**
* Set the Redirector instance.
*
* @param Redirector $redirector
*
* @return $this
*/
public function setRedirector(Redirector $redirector)
{
$this->redirector = $redirector;

return $this;
}

/**
* Set the container implementation.
*
* @param \Illuminate\Contracts\Container\Container $container
*
* @return $this
*/
public function setContainer(Container $container)
{
$this->container = $container;

return $this;
}
}
51 changes: 51 additions & 0 deletions src/Provider/LumenServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
namespace Dingo\Api\Provider;

use ReflectionClass;
use Laravel\Lumen\Application;
use Dingo\Api\Http\FormRequest;
use Laravel\Lumen\Http\Redirector;
use Dingo\Api\Http\Middleware\Auth;
use Dingo\Api\Http\Middleware\Request;
use Dingo\Api\Http\Middleware\RateLimit;
Expand All @@ -11,13 +14,16 @@
use FastRoute\RouteParser\Std as StdRouteParser;
use Illuminate\Http\Request as IlluminateRequest;
use Dingo\Api\Routing\Adapter\Lumen as LumenAdapter;
use Illuminate\Contracts\Validation\ValidatesWhenResolved;
use FastRoute\DataGenerator\GroupCountBased as GcbDataGenerator;

class LumenServiceProvider extends DingoServiceProvider
{
/**
* Boot the service provider.
*
* @throws \ReflectionException
*
* @return void
*/
public function boot()
Expand Down Expand Up @@ -48,6 +54,16 @@ public function boot()
});
});

$this->app->afterResolving(ValidatesWhenResolved::class, function ($resolved) {
$resolved->validate();
});

$this->app->resolving(FormRequest::class, function (FormRequest $request, Application $app) {
$this->initializeRequest($request, $app['request']);

$request->setContainer($app)->setRedirector($app->make(Redirector::class));
});

$this->app->routeMiddleware([
'api.auth' => Auth::class,
'api.throttle' => RateLimit::class,
Expand Down Expand Up @@ -131,4 +147,39 @@ protected function gatherAppMiddleware(ReflectionClass $reflection)

return $middleware;
}

/**
* Initialize the form request with data from the given request.
*
* @param FormRequest $form
* @param IlluminateRequest $current
*
* @return void
*/
protected function initializeRequest(FormRequest $form, IlluminateRequest $current)
{
$files = $current->files->all();

$files = is_array($files) ? array_filter($files) : $files;

$form->initialize(
$current->query->all(),
$current->request->all(),
$current->attributes->all(),
$current->cookies->all(),
$files,
$current->server->all(),
$current->getContent()
);

$form->setJson($current->json());

if ($session = $current->getSession()) {
$form->setLaravelSession($session);
}

$form->setUserResolver($current->getUserResolver());

$form->setRouteResolver($current->getRouteResolver());
}
}
10 changes: 10 additions & 0 deletions src/Routing/Route.php
Original file line number Diff line number Diff line change
Expand Up @@ -533,4 +533,14 @@ public function secure()
{
return in_array('https', $this->action, true);
}

/**
* Return the middlewares for this route.
*
* @return array
*/
public function getMiddleware()
{
return $this->middleware;
}
}

0 comments on commit b26469e

Please sign in to comment.