PageRenderTime 43ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/system/library/PEAR/HTML/QuickForm2/JavascriptBuilder.php

https://bitbucket.org/spekkionu/passworddb
PHP | 373 lines | 170 code | 32 blank | 171 comment | 27 complexity | 01cbe2523110d98be5e2b014d67ff135 MD5 | raw file
Possible License(s): BSD-2-Clause
  1. <?php
  2. /**
  3. * Javascript aggregator and builder class
  4. *
  5. * PHP version 5
  6. *
  7. * LICENSE:
  8. *
  9. * Copyright (c) 2006-2012, Alexey Borzov <avb@php.net>,
  10. * Bertrand Mansion <golgote@mamasam.com>
  11. * All rights reserved.
  12. *
  13. * Redistribution and use in source and binary forms, with or without
  14. * modification, are permitted provided that the following conditions
  15. * are met:
  16. *
  17. * * Redistributions of source code must retain the above copyright
  18. * notice, this list of conditions and the following disclaimer.
  19. * * Redistributions in binary form must reproduce the above copyright
  20. * notice, this list of conditions and the following disclaimer in the
  21. * documentation and/or other materials provided with the distribution.
  22. * * The names of the authors may not be used to endorse or promote products
  23. * derived from this software without specific prior written permission.
  24. *
  25. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  26. * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  27. * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  28. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  29. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  30. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  31. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  32. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  33. * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  34. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  35. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  36. *
  37. * @category HTML
  38. * @package HTML_QuickForm2
  39. * @author Alexey Borzov <avb@php.net>
  40. * @author Bertrand Mansion <golgote@mamasam.com>
  41. * @license http://opensource.org/licenses/bsd-license.php New BSD License
  42. * @version SVN: $Id: JavascriptBuilder.php 325158 2012-04-13 21:04:26Z avb $
  43. * @link http://pear.php.net/package/HTML_QuickForm2
  44. */
  45. /**
  46. * Exception classes for HTML_QuickForm2
  47. */
  48. require_once 'HTML/QuickForm2/Exception.php';
  49. /**
  50. * Javascript aggregator and builder class
  51. *
  52. * @category HTML
  53. * @package HTML_QuickForm2
  54. * @author Alexey Borzov <avb@php.net>
  55. * @author Bertrand Mansion <golgote@mamasam.com>
  56. * @license http://opensource.org/licenses/bsd-license.php New BSD License
  57. * @version Release: @package_version@
  58. * @link http://pear.php.net/package/HTML_QuickForm2
  59. */
  60. class HTML_QuickForm2_JavascriptBuilder
  61. {
  62. /**
  63. * Client-side rules
  64. * @var array
  65. */
  66. protected $rules = array();
  67. /**
  68. * Elements' setup code
  69. * @var array
  70. */
  71. protected $scripts = array();
  72. /**
  73. * Javascript libraries
  74. * @var array
  75. */
  76. protected $libraries = array(
  77. 'base' => array('file' => 'quickform.js')
  78. );
  79. /**
  80. * Default web path to JS library files
  81. * @var string
  82. */
  83. protected $defaultWebPath;
  84. /**
  85. * Default filesystem path to JS library files
  86. * @var string
  87. */
  88. protected $defaultAbsPath;
  89. /**
  90. * Current form ID
  91. * @var string
  92. */
  93. protected $formId = null;
  94. /**
  95. * Constructor, sets default web path to JS library files and default filesystem path
  96. *
  97. * @param string $defaultWebPath default web path to JS library files
  98. * (to use in <script src="...">)
  99. * @param string $defaultAbsPath default filesystem path to JS library files
  100. * (to inline these files into the page), this is set to a package
  101. * subdirectory of PEAR data_dir if not given
  102. */
  103. public function __construct($defaultWebPath = 'js/', $defaultAbsPath = null)
  104. {
  105. $this->defaultWebPath = $defaultWebPath;
  106. if (null === $defaultAbsPath) {
  107. $defaultAbsPath = '@data_dir@' . DIRECTORY_SEPARATOR . 'HTML_QuickForm2'
  108. . DIRECTORY_SEPARATOR . 'js' . DIRECTORY_SEPARATOR;
  109. // package was probably not installed, use relative path
  110. if (0 === strpos($defaultAbsPath, '@' . 'data_dir@')) {
  111. $defaultAbsPath = realpath(
  112. dirname(dirname(dirname(__FILE__)))
  113. . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'js'
  114. ) . DIRECTORY_SEPARATOR;
  115. }
  116. }
  117. $this->defaultAbsPath = $defaultAbsPath;
  118. }
  119. /**
  120. * Adds a Javascript library file to the list
  121. *
  122. * @param string $name name to reference the library by
  123. * @param string $fileName file name, without path
  124. * @param string $webPath path relative to web root to reference in <script src="">,
  125. * $defaultWebPath will be used if not given
  126. * @param string $absPath filesystem path where the file resides, used when inlining
  127. * libraries, $defaultAbsPath will be used if not given
  128. */
  129. public function addLibrary($name, $fileName, $webPath = null, $absPath = null)
  130. {
  131. $this->libraries[strtolower($name)] = array(
  132. 'file' => $fileName, 'webPath' => $webPath, 'absPath' => $absPath
  133. );
  134. }
  135. /**
  136. * Returns Javascript libraries
  137. *
  138. * @param bool $inline whether to return a list of library file names
  139. * or contents of files
  140. * @param bool $addScriptTags whether to enclose the results in <script> tags
  141. *
  142. * @return string|array
  143. */
  144. public function getLibraries($inline = false, $addScriptTags = true)
  145. {
  146. $ret = $inline? '': array();
  147. foreach ($this->libraries as $name => $library) {
  148. if ($inline) {
  149. $path = !empty($library['absPath'])? $library['absPath']: $this->defaultAbsPath;
  150. if (DIRECTORY_SEPARATOR != substr($path, -1)) {
  151. $path .= DIRECTORY_SEPARATOR;
  152. }
  153. if (false === ($file = @file_get_contents($path . $library['file']))) {
  154. throw new HTML_QuickForm2_NotFoundException(
  155. "File '{$library['file']}' for JS library '{$name}' not found at '{$path}'"
  156. );
  157. }
  158. $ret .= ('' == $ret? '': "\n") . $file;
  159. } else {
  160. $path = !empty($library['webPath'])? $library['webPath']: $this->defaultWebPath;
  161. if ('/' != substr($path, -1)) {
  162. $path .= '/';
  163. }
  164. $ret[$name] = $addScriptTags
  165. ? "<script type=\"text/javascript\" src=\"{$path}{$library['file']}\"></script>"
  166. : $path . $library['file'];
  167. }
  168. }
  169. return ($inline && $addScriptTags) ? $this->wrapScript($ret) : $ret;
  170. }
  171. /**
  172. * Sets ID of the form currently being processed
  173. *
  174. * All subsequent calls to addRule() and addElementJavascript() will store
  175. * the scripts for that form
  176. *
  177. * @param string $formId
  178. */
  179. public function setFormId($formId)
  180. {
  181. $this->formId = $formId;
  182. $this->rules[$this->formId] = array();
  183. $this->scripts[$this->formId] = array();
  184. }
  185. /**
  186. * Adds the Rule javascript to the list of current form Rules
  187. *
  188. * @param HTML_QuickForm2_Rule $rule Rule instance
  189. * @param bool $triggers Whether rule code should contain
  190. * "triggers" for live validation
  191. */
  192. public function addRule(HTML_QuickForm2_Rule $rule, $triggers = false)
  193. {
  194. $this->rules[$this->formId][] = $rule->getJavascript($triggers);
  195. }
  196. /**
  197. * Adds element's setup code to form's Javascript
  198. *
  199. * @param string $script
  200. */
  201. public function addElementJavascript($script)
  202. {
  203. $this->scripts[$this->formId][] = $script;
  204. }
  205. /**
  206. * Returns per-form javascript (client-side validation and elements' setup)
  207. *
  208. * @param string $formId form ID, if empty returns code for all forms
  209. * @param boolean $addScriptTags whether to enclose code in <script> tags
  210. *
  211. * @return string
  212. */
  213. public function getFormJavascript($formId = null, $addScriptTags = true)
  214. {
  215. $js = $this->getValidator($formId, false);
  216. $js .= ('' == $js ? '' : "\n") . $this->getSetupCode($formId, false);
  217. return $addScriptTags ? $this->wrapScript($js) : $js;
  218. }
  219. /**
  220. * Returns setup code for form elements
  221. *
  222. * @param string $formId form ID, if empty returns code for all forms
  223. * @param bool $addScriptTags whether to enclose code in <script> tags
  224. *
  225. * @return string
  226. */
  227. public function getSetupCode($formId = null, $addScriptTags = false)
  228. {
  229. $js = '';
  230. foreach ($this->scripts as $id => $scripts) {
  231. if ((null === $formId || $id == $formId) && !empty($scripts)) {
  232. $js .= ('' == $js? '': "\n") . implode("\n", $scripts);
  233. }
  234. }
  235. return $addScriptTags ? $this->wrapScript($js) : $js;
  236. }
  237. /**
  238. * Returns client-side validation code
  239. *
  240. * @param string $formId form ID, if empty returns code for all forms
  241. * @param bool $addScriptTags whether to enclose code in <script> tags
  242. *
  243. * @return string
  244. */
  245. public function getValidator($formId = null, $addScriptTags = false)
  246. {
  247. $js = '';
  248. foreach ($this->rules as $id => $rules) {
  249. if ((null === $formId || $id == $formId) && !empty($rules)) {
  250. $js .= ('' == $js ? '' : "\n")
  251. . "new qf.Validator(document.getElementById('{$id}'), [\n"
  252. . implode(",\n", $rules) . "\n]);";
  253. }
  254. }
  255. return $addScriptTags ? $this->wrapScript($js) : $js;
  256. }
  257. /**
  258. * Wraps the given Javascript code in <script> tags
  259. *
  260. * @param string $js Javascript code
  261. *
  262. * @return string code wrapped in <script></script> tags,
  263. * empty string if $js is empty
  264. */
  265. protected function wrapScript($js)
  266. {
  267. if ('' != $js) {
  268. $js = "<script type=\"text/javascript\">\n//<![CDATA[\n"
  269. . $js . "\n//]]>\n</script>";
  270. }
  271. return $js;
  272. }
  273. /**
  274. * Encodes a value for use as Javascript literal
  275. *
  276. * NB: unlike json_encode() we do not enforce UTF-8 charset here
  277. *
  278. * @param mixed $value
  279. *
  280. * @return string value as Javascript literal
  281. */
  282. public static function encode($value)
  283. {
  284. if (is_null($value)) {
  285. return 'null';
  286. } elseif (is_bool($value)) {
  287. return $value? 'true': 'false';
  288. } elseif (is_int($value) || is_float($value)) {
  289. return $value;
  290. } elseif (is_string($value)) {
  291. return '"' . strtr($value, array(
  292. "\r" => '\r',
  293. "\n" => '\n',
  294. "\t" => '\t',
  295. "'" => "\\'",
  296. '"' => '\"',
  297. '\\' => '\\\\'
  298. )) . '"';
  299. } elseif (is_array($value)) {
  300. // associative array, encoding as JS object
  301. if (count($value) && array_keys($value) !== range(0, count($value) - 1)) {
  302. return '{' . implode(',', array_map(
  303. array('HTML_QuickForm2_JavascriptBuilder', 'encodeNameValue'),
  304. array_keys($value), array_values($value)
  305. )) . '}';
  306. }
  307. return '[' . implode(',', array_map(
  308. array('HTML_QuickForm2_JavascriptBuilder', 'encode'),
  309. $value
  310. )) . ']';
  311. } elseif (is_object($value)) {
  312. $vars = get_object_vars($value);
  313. return '{' . implode(',', array_map(
  314. array('HTML_QuickForm2_JavascriptBuilder', 'encodeNameValue'),
  315. array_keys($vars), array_values($vars)
  316. )) . '}';
  317. } else {
  318. throw new HTML_QuickForm2_InvalidArgumentException(
  319. 'Cannot encode ' . gettype($value) . ' as Javascript value'
  320. );
  321. }
  322. }
  323. /**
  324. * Callback for array_map used to generate name-value pairs
  325. *
  326. * @param mixed $name
  327. * @param mixed $value
  328. *
  329. * @return string
  330. */
  331. protected static function encodeNameValue($name, $value)
  332. {
  333. return self::encode((string)$name) . ':' . self::encode($value);
  334. }
  335. }
  336. ?>