diff --git a/core/lib/Drupal/Core/Serialization/JsonDecode.php b/core/lib/Drupal/Core/Serialization/JsonDecode.php new file mode 100644 index 0000000000..14179ea24c --- /dev/null +++ b/core/lib/Drupal/Core/Serialization/JsonDecode.php @@ -0,0 +1,80 @@ + false, + self::OPTIONS => 0, + self::RECURSION_DEPTH => 512, + ]; + + /** + * Constructs a new JsonDecode instance. + * + * @param array $defaultContext + */ + public function __construct($defaultContext = [], int $depth = 512) + { + if (!\is_array($defaultContext)) { + $defaultContext = [ + self::ASSOCIATIVE => (bool) $defaultContext, + self::RECURSION_DEPTH => $depth, + ]; + $this->associative = $defaultContext; + $this->recursionDepth = (int) $depth; + } + else { + $this->associative = isset($defaultContext[self::ASSOCIATIVE]) ? (bool) $defaultContext[self::ASSOCIATIVE] : FALSE; + $this->recursionDepth = isset($defaultContext[self::RECURSION_DEPTH]) ? (int) $defaultContext[self::RECURSION_DEPTH] : 512; + } + + $this->defaultContext = array_merge($this->defaultContext, $defaultContext); + } + + /** + * {@inheritdoc} + */ + public function decode($data, $format, array $context = array()) { + $associative = isset($context[self::ASSOCIATIVE]) ? $context[self::ASSOCIATIVE] : $this->defaultContext[self::ASSOCIATIVE]; + $recursionDepth = isset($context[self::RECURSION_DEPTH]) ? $context[self::RECURSION_DEPTH] : $this->defaultContext[self::RECURSION_DEPTH]; + $options = isset($context[self::OPTIONS]) ? $context[self::OPTIONS] : $this->defaultContext[self::OPTIONS]; + + $decodedData = json_decode($data, $associative, $recursionDepth, $options); + + if (JSON_ERROR_NONE !== json_last_error()) { + throw new NotEncodableValueException(json_last_error_msg()); + } + + return $decodedData; + } + +} diff --git a/core/lib/Drupal/Core/Serialization/JsonEncode.php b/core/lib/Drupal/Core/Serialization/JsonEncode.php new file mode 100644 index 0000000000..ab4c38049c --- /dev/null +++ b/core/lib/Drupal/Core/Serialization/JsonEncode.php @@ -0,0 +1,58 @@ + 0, + ]; + + protected $options; + + /** + * @param array $defaultContext + */ + public function __construct($defaultContext = []) { + if (!\is_array($defaultContext)) { + $this->defaultContext[self::OPTIONS] = (int) $defaultContext; + $this->options = $defaultContext; + } + else { + $this->options = $defaultContext[self::OPTIONS]; + $this->defaultContext = array_merge($this->defaultContext, $defaultContext); + } + } + + /** + * Encodes PHP data to a JSON string. + * + * {@inheritdoc} + */ + public function encode($data, $format, array $context = []) { + $jsonEncodeOptions = isset($context[self::OPTIONS]) ? $context[self::OPTIONS] : $this->defaultContext[self::OPTIONS]; + $encodedJson = json_encode($data, $jsonEncodeOptions); + + if (JSON_ERROR_NONE !== json_last_error() && (false === $encodedJson || !($jsonEncodeOptions & JSON_PARTIAL_OUTPUT_ON_ERROR))) { + throw new NotEncodableValueException(json_last_error_msg()); + } + + return $encodedJson; + } + + +} diff --git a/core/modules/serialization/src/Encoder/JsonEncoder.php b/core/modules/serialization/src/Encoder/JsonEncoder.php index 964c2951f6..9a018bce75 100644 --- a/core/modules/serialization/src/Encoder/JsonEncoder.php +++ b/core/modules/serialization/src/Encoder/JsonEncoder.php @@ -4,9 +4,9 @@ use Symfony\Component\Serializer\Encoder\DecoderInterface; use Symfony\Component\Serializer\Encoder\EncoderInterface; -use Symfony\Component\Serializer\Encoder\JsonDecode; -use Symfony\Component\Serializer\Encoder\JsonEncode; use Symfony\Component\Serializer\Encoder\JsonEncoder as BaseJsonEncoder; +use Drupal\Core\Serialization\JsonDecode; +use Drupal\Core\Serialization\JsonEncode; /** * Adds 'ajax to the supported content types of the JSON encoder' @@ -31,9 +31,9 @@ public function __construct(JsonEncode $encodingImpl = NULL, JsonDecode $decodin // Encode <, >, ', &, and " for RFC4627-compliant JSON, which may also be // embedded into HTML. // @see \Symfony\Component\HttpFoundation\JsonResponse - $json_encoding_options = JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT; + $json_encoding_options = [JsonEncode::OPTIONS => JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT]; $this->encodingImpl = $encodingImpl ?: new JsonEncode($json_encoding_options); - $this->decodingImpl = $decodingImpl ?: new JsonDecode(TRUE); + $this->decodingImpl = $decodingImpl ?: new JsonDecode([JsonDecode::ASSOCIATIVE => true]); } /** diff --git a/core/tests/Drupal/Tests/ComposerIntegrationTest.php b/core/tests/Drupal/Tests/ComposerIntegrationTest.php index 2d34dcb74c..59ff791295 100644 --- a/core/tests/Drupal/Tests/ComposerIntegrationTest.php +++ b/core/tests/Drupal/Tests/ComposerIntegrationTest.php @@ -18,7 +18,7 @@ class ComposerIntegrationTest extends UnitTestCase { * * @todo Remove as part of https://www.drupal.org/node/2908079 */ - const MIN_PHP_VERSION = '5.5.9'; + const MIN_PHP_VERSION = '7.1.3'; /** * Gets human-readable JSON error messages.