Js.php 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. <?php
  2. namespace Illuminate\Support;
  3. use Illuminate\Contracts\Support\Arrayable;
  4. use Illuminate\Contracts\Support\Htmlable;
  5. use Illuminate\Contracts\Support\Jsonable;
  6. use JsonSerializable;
  7. class Js implements Htmlable
  8. {
  9. /**
  10. * The JavaScript string.
  11. *
  12. * @var string
  13. */
  14. protected $js;
  15. /**
  16. * Flags that should be used when encoding to JSON.
  17. *
  18. * @var int
  19. */
  20. protected const REQUIRED_FLAGS = JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT | JSON_THROW_ON_ERROR;
  21. /**
  22. * Create a new class instance.
  23. *
  24. * @param mixed $data
  25. * @param int|null $flags
  26. * @param int $depth
  27. * @return void
  28. *
  29. * @throws \JsonException
  30. */
  31. public function __construct($data, $flags = 0, $depth = 512)
  32. {
  33. $this->js = $this->convertDataToJavaScriptExpression($data, $flags, $depth);
  34. }
  35. /**
  36. * Create a new JavaScript string from the given data.
  37. *
  38. * @param mixed $data
  39. * @param int $flags
  40. * @param int $depth
  41. * @return static
  42. *
  43. * @throws \JsonException
  44. */
  45. public static function from($data, $flags = 0, $depth = 512)
  46. {
  47. return new static($data, $flags, $depth);
  48. }
  49. /**
  50. * Convert the given data to a JavaScript expression.
  51. *
  52. * @param mixed $data
  53. * @param int $flags
  54. * @param int $depth
  55. * @return string
  56. *
  57. * @throws \JsonException
  58. */
  59. protected function convertDataToJavaScriptExpression($data, $flags = 0, $depth = 512)
  60. {
  61. if ($data instanceof self) {
  62. return $data->toHtml();
  63. }
  64. $json = $this->jsonEncode($data, $flags, $depth);
  65. if (is_string($data)) {
  66. return "'".substr($json, 1, -1)."'";
  67. }
  68. return $this->convertJsonToJavaScriptExpression($json, $flags);
  69. }
  70. /**
  71. * Encode the given data as JSON.
  72. *
  73. * @param mixed $data
  74. * @param int $flags
  75. * @param int $depth
  76. * @return string
  77. *
  78. * @throws \JsonException
  79. */
  80. protected function jsonEncode($data, $flags = 0, $depth = 512)
  81. {
  82. if ($data instanceof Jsonable) {
  83. return $data->toJson($flags | static::REQUIRED_FLAGS);
  84. }
  85. if ($data instanceof Arrayable && ! ($data instanceof JsonSerializable)) {
  86. $data = $data->toArray();
  87. }
  88. return json_encode($data, $flags | static::REQUIRED_FLAGS, $depth);
  89. }
  90. /**
  91. * Convert the given JSON to a JavaScript expression.
  92. *
  93. * @param string $json
  94. * @param int $flags
  95. * @return string
  96. *
  97. * @throws \JsonException
  98. */
  99. protected function convertJsonToJavaScriptExpression($json, $flags = 0)
  100. {
  101. if ('[]' === $json || '{}' === $json) {
  102. return $json;
  103. }
  104. if (Str::startsWith($json, ['"', '{', '['])) {
  105. return "JSON.parse('".substr(json_encode($json, $flags | static::REQUIRED_FLAGS), 1, -1)."')";
  106. }
  107. return $json;
  108. }
  109. /**
  110. * Get the string representation of the data for use in HTML.
  111. *
  112. * @return string
  113. */
  114. public function toHtml()
  115. {
  116. return $this->js;
  117. }
  118. /**
  119. * Get the string representation of the data for use in HTML.
  120. *
  121. * @return string
  122. */
  123. public function __toString()
  124. {
  125. return $this->toHtml();
  126. }
  127. }