Skip to content

Instantly share code, notes, and snippets.

@ScullWM
Last active January 6, 2020 10:36
Show Gist options
  • Save ScullWM/65c6d60a0b24418c964c4fc9785e0214 to your computer and use it in GitHub Desktop.
Save ScullWM/65c6d60a0b24418c964c4fc9785e0214 to your computer and use it in GitHub Desktop.
Body json
<?php
namespace App\EventSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\ParameterBag;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\KernelEvents;
class BodySubscriber implements EventSubscriberInterface
{
protected $strict;
/**
* BodyListener constructor.
*
* @param $strict
*/
public function __construct($strict = false)
{
$this->strict = $strict;
}
public static function getSubscribedEvents(): array
{
return [
KernelEvents::REQUEST => 'onKernelRequest',
];
}
public function onKernelRequest(GetResponseEvent $event)
{
$request = $event->getRequest();
$content = $request->getContent();
if (!empty($content)) {
if ($request->getContentType() == "json") {
$data = $this->decodeJson($content);
} elseif ($this->isFormRequest($request)) {
$data = $this->decodeForm($content);
} elseif ($this->isDecodeable($request)) {
$data = json_decode($request->getContent(), true);
} else {
return;
}
if (is_array($data)) {
$request->request = new ParameterBag($data);
}
}
}
/**
* Check if we should try to decode the body.
*
* @param Request $request
*
* @return bool
*/
protected function isDecodeable(Request $request)
{
if (!in_array($request->getMethod(), ['POST', 'PUT', 'PATCH', 'DELETE'])) {
return false;
}
return !$this->isFormRequest($request);
}
/**
* Check if the content type indicates a form submission.
*
* @param Request $request
*
* @return bool
*/
private function isFormRequest(Request $request)
{
$contentTypeParts = explode(';', $request->headers->get('Content-Type'));
if (isset($contentTypeParts[0])) {
return in_array($contentTypeParts[0], ['multipart/form-data', 'application/x-www-form-urlencoded', 'form']);
}
return false;
}
/**
* {@inheritdoc}
*/
public function decodeForm($data)
{
$decodedData = @json_decode($data, true);
if ($decodedData) {
$this->xWwwFormEncodedLike($decodedData);
}
return $decodedData;
}
public function decodeJson($data)
{
$json = @json_decode($data, true);
if(!$json && json_last_error() != JSON_ERROR_NONE && $this->strict) {
throw new \Exception(json_last_error_msg());
}
return $json;
}
/**
* Makes data decoded from JSON application/x-www-form-encoded compliant.
*
* @param array $data
*/
private function xWwwFormEncodedLike(&$data)
{
foreach ($data as $key => &$value) {
if (is_array($value)) {
// Encode recursively
$this->xWwwFormEncodedLike($value);
} elseif (false === $value) {
// Checkbox-like behavior removes false data but PATCH HTTP method with just checkboxes does not work
// To fix this issue we prefer transform false data to null
// See https://github.com/FriendsOfSymfony/FOSRestBundle/pull/883
$value = null;
} elseif (!is_string($value)) {
// Convert everything to string
// true values will be converted to '1', this is the default checkbox behavior
$value = strval($value);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment