/Front_End/vendor/laracasts/utilities/src/PHPToJavaScriptTransformer.php

https://gitlab.com/Sigpot/AirSpot · PHP · 248 lines · 115 code · 31 blank · 102 comment · 17 complexity · 86098e8b3ee5f58b5d5e1f893b8ea70e MD5 · raw file

  1. <?php
  2. namespace Laracasts\Utilities\JavaScript;
  3. use stdClass;
  4. use Exception;
  5. use JsonSerializable;
  6. class PHPToJavaScriptTransformer
  7. {
  8. /**
  9. * The namespace to nest JS vars under.
  10. *
  11. * @var string
  12. */
  13. protected $namespace;
  14. /**
  15. * What binds the variables to the views.
  16. *
  17. * @var ViewBinder
  18. */
  19. protected $viewBinder;
  20. /**
  21. * All transformable types.
  22. *
  23. * @var array
  24. */
  25. protected $types = [
  26. 'String',
  27. 'Array',
  28. 'Object',
  29. 'Numeric',
  30. 'Boolean',
  31. 'Null'
  32. ];
  33. /**
  34. * Create a new JS transformer instance.
  35. *
  36. * @param ViewBinder $viewBinder
  37. * @param string $namespace
  38. */
  39. function __construct(ViewBinder $viewBinder, $namespace = 'window')
  40. {
  41. $this->viewBinder = $viewBinder;
  42. $this->namespace = $namespace;
  43. }
  44. /**
  45. * Bind the given array of variables to the view.
  46. *
  47. */
  48. public function put()
  49. {
  50. $arguments = func_get_args();
  51. if (is_array($arguments[0])) {
  52. $variables = $arguments[0];
  53. } elseif (count($arguments) == 2) {
  54. $variables = [$arguments[0] => $arguments[1]];
  55. } else {
  56. throw new Exception('Try JavaScript::put(["foo" => "bar"]');
  57. }
  58. // First, we have to translate the variables
  59. // to something JS-friendly.
  60. $js = $this->buildJavaScriptSyntax($variables);
  61. // And then we'll actually bind those
  62. // variables to the view.
  63. $this->viewBinder->bind($js);
  64. return $js;
  65. }
  66. /**
  67. * Translate the array of PHP vars to
  68. * the expected JavaScript syntax.
  69. *
  70. * @param array $vars
  71. * @return array
  72. */
  73. public function buildJavaScriptSyntax(array $vars)
  74. {
  75. $js = $this->buildNamespaceDeclaration();
  76. foreach ($vars as $key => $value) {
  77. $js .= $this->buildVariableInitialization($key, $value);
  78. }
  79. return $js;
  80. }
  81. /**
  82. * Create the namespace to which all vars are nested.
  83. *
  84. * @return string
  85. */
  86. protected function buildNamespaceDeclaration()
  87. {
  88. if ($this->namespace == 'window') {
  89. return '';
  90. }
  91. return "window.{$this->namespace} = window.{$this->namespace} || {};";
  92. }
  93. /**
  94. * Translate a single PHP var to JS.
  95. *
  96. * @param string $key
  97. * @param string $value
  98. * @return string
  99. */
  100. protected function buildVariableInitialization($key, $value)
  101. {
  102. return "{$this->namespace}.{$key} = {$this->optimizeValueForJavaScript($value)};";
  103. }
  104. /**
  105. * Format a value for JavaScript.
  106. *
  107. * @param string $value
  108. * @throws Exception
  109. * @return string
  110. */
  111. protected function optimizeValueForJavaScript($value)
  112. {
  113. // For every transformable type, let's see if
  114. // it needs to be transformed for JS-use.
  115. foreach ($this->types as $transformer) {
  116. $js = $this->{"transform{$transformer}"}($value);
  117. if ( ! is_null($js)) {
  118. return $js;
  119. }
  120. }
  121. }
  122. /**
  123. * Transform a string.
  124. *
  125. * @param string $value
  126. * @return string
  127. */
  128. protected function transformString($value)
  129. {
  130. if (is_string($value)) {
  131. return "'{$this->escape($value)}'";
  132. }
  133. }
  134. /**
  135. * Transform an array.
  136. *
  137. * @param array $value
  138. * @return string
  139. */
  140. protected function transformArray($value)
  141. {
  142. if (is_array($value)) {
  143. return json_encode($value);
  144. }
  145. }
  146. /**
  147. * Transform a numeric value.
  148. *
  149. * @param mixed $value
  150. * @return mixed
  151. */
  152. protected function transformNumeric($value)
  153. {
  154. if (is_numeric($value)) {
  155. return $value;
  156. }
  157. }
  158. /**
  159. * Transform a boolean.
  160. *
  161. * @param boolean $value
  162. * @return string
  163. */
  164. protected function transformBoolean($value)
  165. {
  166. if (is_bool($value)) {
  167. return $value ? 'true' : 'false';
  168. }
  169. }
  170. /**
  171. * @param object $value
  172. * @return string
  173. * @throws Exception
  174. */
  175. protected function transformObject($value)
  176. {
  177. if ( ! is_object($value)) {
  178. return;
  179. }
  180. if ($value instanceof JsonSerializable || $value instanceof StdClass) {
  181. return json_encode($value);
  182. }
  183. // If a toJson() method exists, we'll assume that
  184. // the object can cast itself automatically.
  185. if (method_exists($value, 'toJson')) {
  186. return $value;
  187. }
  188. // Otherwise, if the object doesn't even have a
  189. // __toString() method, we can't proceed.
  190. if ( ! method_exists($value, '__toString')) {
  191. throw new Exception('Cannot transform this object to JavaScript.');
  192. }
  193. return "'{$value}'";
  194. }
  195. /**
  196. * Transform "null."
  197. *
  198. * @param mixed $value
  199. * @return string
  200. */
  201. protected function transformNull($value)
  202. {
  203. if (is_null($value)) {
  204. return 'null';
  205. }
  206. }
  207. /**
  208. * Escape any single quotes.
  209. *
  210. * @param string $value
  211. * @return string
  212. */
  213. protected function escape($value)
  214. {
  215. return str_replace(["\\", "'"], ["\\\\", "\'"], $value);
  216. }
  217. }