Security update for Core, with self-updated composer
[yaffs-website] / web / core / lib / Drupal / Component / Serialization / YamlPecl.php
1 <?php
2
3 namespace Drupal\Component\Serialization;
4
5 use Drupal\Component\Serialization\Exception\InvalidDataTypeException;
6
7 /**
8  * Provides default serialization for YAML using the PECL extension.
9  */
10 class YamlPecl implements SerializationInterface {
11
12   /**
13    * {@inheritdoc}
14    */
15   public static function encode($data) {
16     static $init;
17     if (!isset($init)) {
18       ini_set('yaml.output_indent', 2);
19       // Do not break lines at 80 characters.
20       ini_set('yaml.output_width', -1);
21       $init = TRUE;
22     }
23     return yaml_emit($data, YAML_UTF8_ENCODING, YAML_LN_BREAK);
24   }
25
26   /**
27    * {@inheritdoc}
28    */
29   public static function decode($raw) {
30     static $init;
31     if (!isset($init)) {
32       // Decode binary, since Symfony YAML parser encodes binary from 3.1
33       // onwards.
34       ini_set('yaml.decode_binary', 1);
35       // We never want to unserialize !php/object.
36       ini_set('yaml.decode_php', 0);
37       $init = TRUE;
38     }
39     // yaml_parse() will error with an empty value.
40     if (!trim($raw)) {
41       return NULL;
42     }
43     // @todo Use ErrorExceptions when https://drupal.org/node/1247666 is in.
44     // yaml_parse() will throw errors instead of raising an exception. Until
45     // such time as Drupal supports native PHP ErrorExceptions as the error
46     // handler, we need to temporarily set the error handler as ::errorHandler()
47     // and then restore it after decoding has occurred. This allows us to turn
48     // parsing errors into a throwable exception.
49     // @see Drupal\Component\Serialization\Exception\InvalidDataTypeException
50     // @see http://php.net/manual/en/class.errorexception.php
51     set_error_handler([__CLASS__, 'errorHandler']);
52     $ndocs = 0;
53     $data = yaml_parse($raw, 0, $ndocs, [
54       YAML_BOOL_TAG => '\Drupal\Component\Serialization\YamlPecl::applyBooleanCallbacks',
55     ]);
56     restore_error_handler();
57     return $data;
58   }
59
60   /**
61    * Handles errors for \Drupal\Component\Serialization\YamlPecl::decode().
62    *
63    * @param int $severity
64    *   The severity level of the error.
65    * @param string $message
66    *   The error message to display.
67    *
68    * @see \Drupal\Component\Serialization\YamlPecl::decode()
69    */
70   public static function errorHandler($severity, $message) {
71     restore_error_handler();
72     throw new InvalidDataTypeException($message, $severity);
73   }
74
75   /**
76    * {@inheritdoc}
77    */
78   public static function getFileExtension() {
79     return 'yml';
80   }
81
82   /**
83    * Applies callbacks after parsing to ignore 1.1 style booleans.
84    *
85    * @param mixed $value
86    *   Value from YAML file.
87    * @param string $tag
88    *   Tag that triggered the callback.
89    * @param int $flags
90    *   Scalar entity style flags.
91    *
92    * @return string|bool
93    *   FALSE, false, TRUE and true are returned as booleans, everything else is
94    *   returned as a string.
95    */
96   public static function applyBooleanCallbacks($value, $tag, $flags) {
97     // YAML 1.1 spec dictates that 'Y', 'N', 'y' and 'n' are booleans. But, we
98     // want the 1.2 behavior, so we only consider 'false', 'FALSE', 'true' and
99     // 'TRUE' as booleans.
100     if (!in_array(strtolower($value), ['false', 'true'], TRUE)) {
101       return $value;
102     }
103     $map = [
104       'false' => FALSE,
105       'true' => TRUE,
106     ];
107     return $map[strtolower($value)];
108   }
109
110 }