Serializer.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. <?php
  2. /*
  3. * Copyright 2012 Facebook, Inc.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. /**
  18. * This helper is based on code from Facebook's Phabricator project
  19. *
  20. * https://github.com/facebook/phabricator
  21. *
  22. * Specifically, it is an adaptation of the PhutilReadableSerializer class.
  23. *
  24. * @package raven
  25. */
  26. class Raven_Serializer
  27. {
  28. /*
  29. * The default mb detect order
  30. *
  31. * @see http://php.net/manual/en/function.mb-detect-encoding.php
  32. */
  33. const DEFAULT_MB_DETECT_ORDER = 'auto';
  34. /*
  35. * Suggested detect order for western countries
  36. */
  37. const WESTERN_MB_DETECT_ORDER = 'UTF-8, ASCII, ISO-8859-1, ISO-8859-2, ISO-8859-3, ISO-8859-4, ISO-8859-5, ISO-8859-6, ISO-8859-7, ISO-8859-8, ISO-8859-9, ISO-8859-10, ISO-8859-13, ISO-8859-14, ISO-8859-15, ISO-8859-16, Windows-1251, Windows-1252, Windows-1254';
  38. /**
  39. * This is the default mb detect order for the detection of encoding
  40. *
  41. * @var string
  42. */
  43. protected $mb_detect_order = self::DEFAULT_MB_DETECT_ORDER;
  44. /**
  45. * The default maximum message lengths. Longer strings will be truncated
  46. *
  47. * @var int
  48. */
  49. protected $message_limit = Raven_Client::MESSAGE_LIMIT;
  50. /**
  51. * @param null|string $mb_detect_order
  52. * @param null|int $message_limit
  53. */
  54. public function __construct($mb_detect_order = null, $message_limit = null)
  55. {
  56. if ($mb_detect_order != null) {
  57. $this->mb_detect_order = $mb_detect_order;
  58. }
  59. if ($message_limit != null) {
  60. $this->message_limit = (int) $message_limit;
  61. }
  62. }
  63. /**
  64. * Serialize an object (recursively) into something safe for data
  65. * sanitization and encoding.
  66. *
  67. * @param mixed $value
  68. * @param int $max_depth
  69. * @param int $_depth
  70. * @return string|bool|double|int|null|object|array
  71. */
  72. public function serialize($value, $max_depth = 3, $_depth = 0)
  73. {
  74. $className = is_object($value) ? get_class($value) : null;
  75. $toArray = is_array($value) || $className === 'stdClass';
  76. if ($toArray && $_depth < $max_depth) {
  77. $new = array();
  78. foreach ($value as $k => $v) {
  79. $new[$this->serializeValue($k)] = $this->serialize($v, $max_depth, $_depth + 1);
  80. }
  81. return $new;
  82. }
  83. return $this->serializeValue($value);
  84. }
  85. protected function serializeString($value)
  86. {
  87. $value = (string) $value;
  88. if (function_exists('mb_detect_encoding')
  89. && function_exists('mb_convert_encoding')
  90. ) {
  91. // we always guarantee this is coerced, even if we can't detect encoding
  92. if ($currentEncoding = mb_detect_encoding($value, $this->mb_detect_order)) {
  93. $value = mb_convert_encoding($value, 'UTF-8', $currentEncoding);
  94. } else {
  95. $value = mb_convert_encoding($value, 'UTF-8');
  96. }
  97. }
  98. if (strlen($value) > $this->message_limit) {
  99. $value = substr($value, 0, $this->message_limit - 10) . ' {clipped}';
  100. }
  101. return $value;
  102. }
  103. /**
  104. * @param mixed $value
  105. * @return string|bool|double|int|null
  106. */
  107. protected function serializeValue($value)
  108. {
  109. if (is_null($value) || is_bool($value) || is_float($value) || is_integer($value)) {
  110. return $value;
  111. } elseif (is_object($value) || gettype($value) == 'object') {
  112. return 'Object '.get_class($value);
  113. } elseif (is_resource($value)) {
  114. return 'Resource '.get_resource_type($value);
  115. } elseif (is_array($value)) {
  116. return 'Array of length ' . count($value);
  117. } else {
  118. return $this->serializeString($value);
  119. }
  120. }
  121. /**
  122. * @return string
  123. * @codeCoverageIgnore
  124. */
  125. public function getMbDetectOrder()
  126. {
  127. return $this->mb_detect_order;
  128. }
  129. /**
  130. * @param string $mb_detect_order
  131. *
  132. * @return Raven_Serializer
  133. * @codeCoverageIgnore
  134. */
  135. public function setMbDetectOrder($mb_detect_order)
  136. {
  137. $this->mb_detect_order = $mb_detect_order;
  138. return $this;
  139. }
  140. /**
  141. * @return int
  142. * @codeCoverageIgnore
  143. */
  144. public function getMessageLimit()
  145. {
  146. return $this->message_limit;
  147. }
  148. /**
  149. * @param int $message_limit
  150. * @codeCoverageIgnore
  151. */
  152. public function setMessageLimit($message_limit)
  153. {
  154. $this->message_limit = (int)$message_limit;
  155. }
  156. }