PageRenderTime 27ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/libraries/joomla/html/html.php

https://bitbucket.org/pastor399/newcastleunifc
PHP | 1007 lines | 553 code | 101 blank | 353 comment | 69 complexity | 81a783323a1a4f516c10b2843501ca8f MD5 | raw file
  1. <?php
  2. /**
  3. * @package Joomla.Platform
  4. * @subpackage HTML
  5. *
  6. * @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
  7. * @license GNU General Public License version 2 or later; see LICENSE
  8. */
  9. defined('JPATH_PLATFORM') or die;
  10. jimport('joomla.environment.browser');
  11. jimport('joomla.filesystem.file');
  12. jimport('joomla.filesystem.path');
  13. /**
  14. * Utility class for all HTML drawing classes
  15. *
  16. * @package Joomla.Platform
  17. * @subpackage HTML
  18. * @since 11.1
  19. */
  20. abstract class JHtml
  21. {
  22. /**
  23. * Option values related to the generation of HTML output. Recognized
  24. * options are:
  25. * fmtDepth, integer. The current indent depth.
  26. * fmtEol, string. The end of line string, default is linefeed.
  27. * fmtIndent, string. The string to use for indentation, default is
  28. * tab.
  29. *
  30. * @var array
  31. * @since 11.1
  32. */
  33. public static $formatOptions = array('format.depth' => 0, 'format.eol' => "\n", 'format.indent' => "\t");
  34. /**
  35. * An array to hold included paths
  36. *
  37. * @var array
  38. * @since 11.1
  39. */
  40. protected static $includePaths = array();
  41. /**
  42. * An array to hold method references
  43. *
  44. * @var array
  45. * @since 11.1
  46. */
  47. protected static $registry = array();
  48. /**
  49. * Method to extract a key
  50. *
  51. * @param string $key The name of helper method to load, (prefix).(class).function
  52. * prefix and class are optional and can be used to load custom html helpers.
  53. *
  54. * @return array Contains lowercase key, prefix, file, function.
  55. *
  56. * @since 11.1
  57. */
  58. protected static function extract($key)
  59. {
  60. $key = preg_replace('#[^A-Z0-9_\.]#i', '', $key);
  61. // Check to see whether we need to load a helper file
  62. $parts = explode('.', $key);
  63. $prefix = (count($parts) == 3 ? array_shift($parts) : 'JHtml');
  64. $file = (count($parts) == 2 ? array_shift($parts) : '');
  65. $func = array_shift($parts);
  66. return array(strtolower($prefix . '.' . $file . '.' . $func), $prefix, $file, $func);
  67. }
  68. /**
  69. * Class loader method
  70. *
  71. * Additional arguments may be supplied and are passed to the sub-class.
  72. * Additional include paths are also able to be specified for third-party use
  73. *
  74. * @param string $key The name of helper method to load, (prefix).(class).function
  75. * prefix and class are optional and can be used to load custom
  76. * html helpers.
  77. *
  78. * @return mixed JHtml::call($function, $args) or False on error
  79. *
  80. * @since 11.1
  81. * @throws InvalidArgumentException
  82. */
  83. public static function _($key)
  84. {
  85. list($key, $prefix, $file, $func) = self::extract($key);
  86. if (array_key_exists($key, self::$registry))
  87. {
  88. $function = self::$registry[$key];
  89. $args = func_get_args();
  90. // Remove function name from arguments
  91. array_shift($args);
  92. return self::call($function, $args);
  93. }
  94. $className = $prefix . ucfirst($file);
  95. if (!class_exists($className))
  96. {
  97. $path = JPath::find(self::$includePaths, strtolower($file) . '.php');
  98. if ($path)
  99. {
  100. require_once $path;
  101. if (!class_exists($className))
  102. {
  103. throw new InvalidArgumentException(sprintf('%s not found.', $className), 500);
  104. }
  105. }
  106. else
  107. {
  108. throw new InvalidArgumentException(sprintf('%s %s not found.', $prefix, $file), 500);
  109. }
  110. }
  111. $toCall = array($className, $func);
  112. if (is_callable($toCall))
  113. {
  114. self::register($key, $toCall);
  115. $args = func_get_args();
  116. // Remove function name from arguments
  117. array_shift($args);
  118. return self::call($toCall, $args);
  119. }
  120. else
  121. {
  122. throw new InvalidArgumentException(sprintf('%s::%s not found.', $className, $func), 500);
  123. }
  124. }
  125. /**
  126. * Registers a function to be called with a specific key
  127. *
  128. * @param string $key The name of the key
  129. * @param string $function Function or method
  130. *
  131. * @return boolean True if the function is callable
  132. *
  133. * @since 11.1
  134. */
  135. public static function register($key, $function)
  136. {
  137. list($key) = self::extract($key);
  138. if (is_callable($function))
  139. {
  140. self::$registry[$key] = $function;
  141. return true;
  142. }
  143. return false;
  144. }
  145. /**
  146. * Removes a key for a method from registry.
  147. *
  148. * @param string $key The name of the key
  149. *
  150. * @return boolean True if a set key is unset
  151. *
  152. * @since 11.1
  153. */
  154. public static function unregister($key)
  155. {
  156. list($key) = self::extract($key);
  157. if (isset(self::$registry[$key]))
  158. {
  159. unset(self::$registry[$key]);
  160. return true;
  161. }
  162. return false;
  163. }
  164. /**
  165. * Test if the key is registered.
  166. *
  167. * @param string $key The name of the key
  168. *
  169. * @return boolean True if the key is registered.
  170. *
  171. * @since 11.1
  172. */
  173. public static function isRegistered($key)
  174. {
  175. list($key) = self::extract($key);
  176. return isset(self::$registry[$key]);
  177. }
  178. /**
  179. * Function caller method
  180. *
  181. * @param callable $function Function or method to call
  182. * @param array $args Arguments to be passed to function
  183. *
  184. * @return mixed Function result or false on error.
  185. *
  186. * @see http://php.net/manual/en/function.call-user-func-array.php
  187. * @since 11.1
  188. * @throws InvalidArgumentException
  189. */
  190. protected static function call($function, $args)
  191. {
  192. if (!is_callable($function))
  193. {
  194. throw new InvalidArgumentException('Function not supported', 500);
  195. }
  196. // PHP 5.3 workaround
  197. $temp = array();
  198. foreach ($args as &$arg)
  199. {
  200. $temp[] = &$arg;
  201. }
  202. return call_user_func_array($function, $temp);
  203. }
  204. /**
  205. * Write a <a></a> element
  206. *
  207. * @param string $url The relative URL to use for the href attribute
  208. * @param string $text The target attribute to use
  209. * @param array $attribs An associative array of attributes to add
  210. *
  211. * @return string <a></a> string
  212. *
  213. * @since 11.1
  214. */
  215. public static function link($url, $text, $attribs = null)
  216. {
  217. if (is_array($attribs))
  218. {
  219. $attribs = JArrayHelper::toString($attribs);
  220. }
  221. return '<a href="' . $url . '" ' . $attribs . '>' . $text . '</a>';
  222. }
  223. /**
  224. * Write a <iframe></iframe> element
  225. *
  226. * @param string $url The relative URL to use for the src attribute
  227. * @param string $name The target attribute to use
  228. * @param array $attribs An associative array of attributes to add
  229. * @param string $noFrames The message to display if the iframe tag is not supported
  230. *
  231. * @return string <iframe></iframe> element or message if not supported
  232. *
  233. * @since 11.1
  234. */
  235. public static function iframe($url, $name, $attribs = null, $noFrames = '')
  236. {
  237. if (is_array($attribs))
  238. {
  239. $attribs = JArrayHelper::toString($attribs);
  240. }
  241. return '<iframe src="' . $url . '" ' . $attribs . ' name="' . $name . '">' . $noFrames . '</iframe>';
  242. }
  243. /**
  244. * Compute the files to be included
  245. *
  246. * @param string $folder folder name to search into (images, css, js, ...)
  247. * @param string $file path to file
  248. * @param boolean $relative path to file is relative to /media folder (and searches in template)
  249. * @param boolean $detect_browser detect browser to include specific browser files
  250. * @param boolean $detect_debug detect debug to include compressed files if debug is on
  251. *
  252. * @return array files to be included
  253. *
  254. * @see JBrowser
  255. * @since 11.1
  256. */
  257. protected static function includeRelativeFiles($folder, $file, $relative, $detect_browser, $detect_debug)
  258. {
  259. // If http is present in filename
  260. if (strpos($file, 'http') === 0)
  261. {
  262. $includes = array($file);
  263. }
  264. else
  265. {
  266. // Extract extension and strip the file
  267. $strip = JFile::stripExt($file);
  268. $ext = JFile::getExt($file);
  269. // Prepare array of files
  270. $includes = array();
  271. // Detect browser and compute potential files
  272. if ($detect_browser)
  273. {
  274. $navigator = JBrowser::getInstance();
  275. $browser = $navigator->getBrowser();
  276. $major = $navigator->getMajor();
  277. $minor = $navigator->getMinor();
  278. // Try to include files named filename.ext, filename_browser.ext, filename_browser_major.ext, filename_browser_major_minor.ext
  279. // where major and minor are the browser version names
  280. $potential = array($strip, $strip . '_' . $browser, $strip . '_' . $browser . '_' . $major,
  281. $strip . '_' . $browser . '_' . $major . '_' . $minor);
  282. }
  283. else
  284. {
  285. $potential = array($strip);
  286. }
  287. // If relative search in template directory or media directory
  288. if ($relative)
  289. {
  290. // Get the template
  291. $app = JFactory::getApplication();
  292. $template = $app->getTemplate();
  293. // For each potential files
  294. foreach ($potential as $strip)
  295. {
  296. $files = array();
  297. // Detect debug mode
  298. if ($detect_debug && JFactory::getConfig()->get('debug'))
  299. {
  300. /*
  301. * Detect if we received a file in the format name.min.ext
  302. * If so, strip the .min part out, otherwise append -uncompressed
  303. */
  304. if (strrpos($strip, '.min', '-4'))
  305. {
  306. $position = strrpos($strip, '.min', '-4');
  307. $filename = str_replace('.min', '.', $strip, $position);
  308. $files[] = $filename . $ext;
  309. }
  310. else
  311. {
  312. $files[] = $strip . '-uncompressed.' . $ext;
  313. }
  314. }
  315. $files[] = $strip . '.' . $ext;
  316. /*
  317. * Loop on 1 or 2 files and break on first found.
  318. * Add the content of the MD5SUM file located in the same folder to url to ensure cache browser refresh
  319. * This MD5SUM file must represent the signature of the folder content
  320. */
  321. foreach ($files as $file)
  322. {
  323. // If the file is in the template folder
  324. $path = JPATH_THEMES . "/$template/$folder/$file";
  325. if (file_exists($path))
  326. {
  327. $md5 = dirname($path) . '/MD5SUM';
  328. $includes[] = JURI::base(true) . "/templates/$template/$folder/$file" .
  329. (file_exists($md5) ? ('?' . file_get_contents($md5)) : '');
  330. break;
  331. }
  332. else
  333. {
  334. // If the file contains any /: it can be in an media extension subfolder
  335. if (strpos($file, '/'))
  336. {
  337. // Divide the file extracting the extension as the first part before /
  338. list($extension, $file) = explode('/', $file, 2);
  339. // If the file yet contains any /: it can be a plugin
  340. if (strpos($file, '/'))
  341. {
  342. // Divide the file extracting the element as the first part before /
  343. list($element, $file) = explode('/', $file, 2);
  344. // Try to deal with plugins group in the media folder
  345. $path = JPATH_ROOT . "/media/$extension/$element/$folder/$file";
  346. if (file_exists($path))
  347. {
  348. $md5 = dirname($path) . '/MD5SUM';
  349. $includes[] = JURI::root(true) . "/media/$extension/$element/$folder/$file" .
  350. (file_exists($md5) ? ('?' . file_get_contents($md5)) : '');
  351. break;
  352. }
  353. // Try to deal with classical file in a a media subfolder called element
  354. $path = JPATH_ROOT . "/media/$extension/$folder/$element/$file";
  355. if (file_exists($path))
  356. {
  357. $md5 = dirname($path) . '/MD5SUM';
  358. $includes[] = JURI::root(true) . "/media/$extension/$folder/$element/$file" .
  359. (file_exists($md5) ? ('?' . file_get_contents($md5)) : '');
  360. break;
  361. }
  362. // Try to deal with system files in the template folder
  363. $path = JPATH_THEMES . "/$template/$folder/system/$element/$file";
  364. if (file_exists($path))
  365. {
  366. $md5 = dirname($path) . '/MD5SUM';
  367. $includes[] = JURI::root(true) . "/templates/$template/$folder/system/$element/$file" .
  368. (file_exists($md5) ? ('?' . file_get_contents($md5)) : '');
  369. break;
  370. }
  371. // Try to deal with system files in the media folder
  372. $path = JPATH_ROOT . "/media/system/$folder/$element/$file";
  373. if (file_exists($path))
  374. {
  375. $md5 = dirname($path) . '/MD5SUM';
  376. $includes[] = JURI::root(true) . "/media/system/$folder/$element/$file" .
  377. (file_exists($md5) ? ('?' . file_get_contents($md5)) : '');
  378. break;
  379. }
  380. }
  381. else
  382. {
  383. // Try to deals in the extension media folder
  384. $path = JPATH_ROOT . "/media/$extension/$folder/$file";
  385. if (file_exists($path))
  386. {
  387. $md5 = dirname($path) . '/MD5SUM';
  388. $includes[] = JURI::root(true) . "/media/$extension/$folder/$file" .
  389. (file_exists($md5) ? ('?' . file_get_contents($md5)) : '');
  390. break;
  391. }
  392. // Try to deal with system files in the template folder
  393. $path = JPATH_THEMES . "/$template/$folder/system/$file";
  394. if (file_exists($path))
  395. {
  396. $md5 = dirname($path) . '/MD5SUM';
  397. $includes[] = JURI::root(true) . "/templates/$template/$folder/system/$file" .
  398. (file_exists($md5) ? ('?' . file_get_contents($md5)) : '');
  399. break;
  400. }
  401. // Try to deal with system files in the media folder
  402. $path = JPATH_ROOT . "/media/system/$folder/$file";
  403. if (file_exists($path))
  404. {
  405. $md5 = dirname($path) . '/MD5SUM';
  406. $includes[] = JURI::root(true) . "/media/system/$folder/$file" .
  407. (file_exists($md5) ? ('?' . file_get_contents($md5)) : '');
  408. break;
  409. }
  410. }
  411. }
  412. // Try to deal with system files in the media folder
  413. else
  414. {
  415. $path = JPATH_ROOT . "/media/system/$folder/$file";
  416. if (file_exists($path))
  417. {
  418. $md5 = dirname($path) . '/MD5SUM';
  419. $includes[] = JURI::root(true) . "/media/system/$folder/$file" .
  420. (file_exists($md5) ? ('?' . file_get_contents($md5)) : '');
  421. break;
  422. }
  423. }
  424. }
  425. }
  426. }
  427. }
  428. // If not relative and http is not present in filename
  429. else
  430. {
  431. foreach ($potential as $strip)
  432. {
  433. $files = array();
  434. // Detect debug mode
  435. if ($detect_debug && JFactory::getConfig()->get('debug'))
  436. {
  437. /*
  438. * Detect if we received a file in the format name.min.ext
  439. * If so, strip the .min part out, otherwise append -uncompressed
  440. */
  441. if (strrpos($strip, '.min', '-4'))
  442. {
  443. $position = strrpos($strip, '.min', '-4');
  444. $filename = str_replace('.min', '.', $strip, $position);
  445. $files[] = $filename . $ext;
  446. }
  447. else
  448. {
  449. $files[] = $strip . '-uncompressed.' . $ext;
  450. }
  451. }
  452. $files[] = $strip . '.' . $ext;
  453. /*
  454. * Loop on 1 or 2 files and break on first found.
  455. * Add the content of the MD5SUM file located in the same folder to url to ensure cache browser refresh
  456. * This MD5SUM file must represent the signature of the folder content
  457. */
  458. foreach ($files as $file)
  459. {
  460. $path = JPATH_ROOT . "/$file";
  461. if (file_exists($path))
  462. {
  463. $md5 = dirname($path) . '/MD5SUM';
  464. $includes[] = JURI::root(true) . "/$file" .
  465. (file_exists($md5) ? ('?' . file_get_contents($md5)) : '');
  466. break;
  467. }
  468. }
  469. }
  470. }
  471. }
  472. return $includes;
  473. }
  474. /**
  475. * Write a <img></img> element
  476. *
  477. * @param string $file The relative or absolute URL to use for the src attribute
  478. * @param string $alt The alt text.
  479. * @param mixed $attribs String or associative array of attribute(s) to use
  480. * @param boolean $relative Path to file is relative to /media folder (and searches in template)
  481. * @param mixed $path_rel Return html tag without (-1) or with file computing(false). Return computed path only (true)
  482. *
  483. * @return string
  484. *
  485. * @since 11.1
  486. */
  487. public static function image($file, $alt, $attribs = null, $relative = false, $path_rel = false)
  488. {
  489. if ($path_rel !== -1)
  490. {
  491. $includes = self::includeRelativeFiles('images', $file, $relative, false, false);
  492. $file = count($includes) ? $includes[0] : null;
  493. }
  494. // If only path is required
  495. if ($path_rel)
  496. {
  497. return $file;
  498. }
  499. else
  500. {
  501. return '<img src="' . $file . '" alt="' . $alt . '" ' .
  502. (is_array($attribs) ? JArrayHelper::toString($attribs) : $attribs) .
  503. ' />';
  504. }
  505. }
  506. /**
  507. * Write a <link rel="stylesheet" style="text/css" /> element
  508. *
  509. * @param string $file path to file
  510. * @param array $attribs attributes to be added to the stylesheet
  511. * @param boolean $relative path to file is relative to /media folder
  512. * @param boolean $path_only return the path to the file only
  513. * @param boolean $detect_browser detect browser to include specific browser css files
  514. * will try to include file, file_*browser*, file_*browser*_*major*, file_*browser*_*major*_*minor*
  515. * <table>
  516. * <tr><th>Navigator</th> <th>browser</th> <th>major.minor</th></tr>
  517. *
  518. * <tr><td>Safari 3.0.x</td> <td>konqueror</td> <td>522.x</td></tr>
  519. * <tr><td>Safari 3.1.x and 3.2.x</td> <td>konqueror</td> <td>525.x</td></tr>
  520. * <tr><td>Safari 4.0 to 4.0.2</td> <td>konqueror</td> <td>530.x</td></tr>
  521. * <tr><td>Safari 4.0.3 to 4.0.4</td> <td>konqueror</td> <td>531.x</td></tr>
  522. * <tr><td>iOS 4.0 Safari</td> <td>konqueror</td> <td>532.x</td></tr>
  523. * <tr><td>Safari 5.0</td> <td>konqueror</td> <td>533.x</td></tr>
  524. *
  525. * <tr><td>Google Chrome 1.0</td> <td>konqueror</td> <td>528.x</td></tr>
  526. * <tr><td>Google Chrome 2.0</td> <td>konqueror</td> <td>530.x</td></tr>
  527. * <tr><td>Google Chrome 3.0 and 4.x</td> <td>konqueror</td> <td>532.x</td></tr>
  528. * <tr><td>Google Chrome 5.0</td> <td>konqueror</td> <td>533.x</td></tr>
  529. *
  530. * <tr><td>Internet Explorer 5.5</td> <td>msie</td> <td>5.5</td></tr>
  531. * <tr><td>Internet Explorer 6.x</td> <td>msie</td> <td>6.x</td></tr>
  532. * <tr><td>Internet Explorer 7.x</td> <td>msie</td> <td>7.x</td></tr>
  533. * <tr><td>Internet Explorer 8.x</td> <td>msie</td> <td>8.x</td></tr>
  534. *
  535. * <tr><td>Firefox</td> <td>mozilla</td> <td>5.0</td></tr>
  536. * </table>
  537. * a lot of others
  538. * @param boolean $detect_debug detect debug to search for compressed files if debug is on
  539. *
  540. * @return mixed nothing if $path_only is false, null, path or array of path if specific css browser files were detected
  541. *
  542. * @see JBrowser
  543. * @since 11.1
  544. */
  545. public static function stylesheet($file, $attribs = array(), $relative = false, $path_only = false, $detect_browser = true, $detect_debug = true)
  546. {
  547. $includes = self::includeRelativeFiles('css', $file, $relative, $detect_browser, $detect_debug);
  548. // If only path is required
  549. if ($path_only)
  550. {
  551. if (count($includes) == 0)
  552. {
  553. return null;
  554. }
  555. elseif (count($includes) == 1)
  556. {
  557. return $includes[0];
  558. }
  559. else
  560. {
  561. return $includes;
  562. }
  563. }
  564. // If inclusion is required
  565. else
  566. {
  567. $document = JFactory::getDocument();
  568. foreach ($includes as $include)
  569. {
  570. $document->addStylesheet($include, 'text/css', null, $attribs);
  571. }
  572. }
  573. }
  574. /**
  575. * Write a <script></script> element
  576. *
  577. * @param string $file path to file
  578. * @param boolean $framework load the JS framework
  579. * @param boolean $relative path to file is relative to /media folder
  580. * @param boolean $path_only return the path to the file only
  581. * @param boolean $detect_browser detect browser to include specific browser js files
  582. * @param boolean $detect_debug detect debug to search for compressed files if debug is on
  583. *
  584. * @return mixed nothing if $path_only is false, null, path or array of path if specific js browser files were detected
  585. *
  586. * @see JHtml::stylesheet
  587. * @since 11.1
  588. */
  589. public static function script($file, $framework = false, $relative = false, $path_only = false, $detect_browser = true, $detect_debug = true)
  590. {
  591. // Include MooTools framework
  592. if ($framework)
  593. {
  594. self::_('behavior.framework');
  595. }
  596. $includes = self::includeRelativeFiles('js', $file, $relative, $detect_browser, $detect_debug);
  597. // If only path is required
  598. if ($path_only)
  599. {
  600. if (count($includes) == 0)
  601. {
  602. return null;
  603. }
  604. elseif (count($includes) == 1)
  605. {
  606. return $includes[0];
  607. }
  608. else
  609. {
  610. return $includes;
  611. }
  612. }
  613. // If inclusion is required
  614. else
  615. {
  616. $document = JFactory::getDocument();
  617. foreach ($includes as $include)
  618. {
  619. $document->addScript($include);
  620. }
  621. }
  622. }
  623. /**
  624. * Set format related options.
  625. *
  626. * Updates the formatOptions array with all valid values in the passed
  627. * array. See {@see JHtml::$formatOptions} for details.
  628. *
  629. * @param array $options Option key/value pairs.
  630. *
  631. * @return void
  632. *
  633. * @since 11.1
  634. */
  635. public static function setFormatOptions($options)
  636. {
  637. foreach ($options as $key => $val)
  638. {
  639. if (isset(self::$formatOptions[$key]))
  640. {
  641. self::$formatOptions[$key] = $val;
  642. }
  643. }
  644. }
  645. /**
  646. * Returns formated date according to a given format and time zone.
  647. *
  648. * @param string $input String in a format accepted by date(), defaults to "now".
  649. * @param string $format The date format specification string (see {@link PHP_MANUAL#date})
  650. * @param mixed $tz Time zone to be used for the date. Special cases: boolean true for user
  651. * setting, boolean false for server setting.
  652. * @param boolean $gregorian True to use Gregorian calenar
  653. *
  654. * @return string A date translated by the given format and time zone.
  655. *
  656. * @see strftime
  657. * @since 11.1
  658. */
  659. public static function date($input = 'now', $format = null, $tz = true, $gregorian = false)
  660. {
  661. // Get some system objects.
  662. $config = JFactory::getConfig();
  663. $user = JFactory::getUser();
  664. // UTC date converted to user time zone.
  665. if ($tz === true)
  666. {
  667. // Get a date object based on UTC.
  668. $date = JFactory::getDate($input, 'UTC');
  669. // Set the correct time zone based on the user configuration.
  670. $date->setTimeZone(new DateTimeZone($user->getParam('timezone', $config->get('offset'))));
  671. }
  672. // UTC date converted to server time zone.
  673. elseif ($tz === false)
  674. {
  675. // Get a date object based on UTC.
  676. $date = JFactory::getDate($input, 'UTC');
  677. // Set the correct time zone based on the server configuration.
  678. $date->setTimeZone(new DateTimeZone($config->get('offset')));
  679. }
  680. // No date conversion.
  681. elseif ($tz === null)
  682. {
  683. $date = JFactory::getDate($input);
  684. }
  685. // UTC date converted to given time zone.
  686. else
  687. {
  688. // Get a date object based on UTC.
  689. $date = JFactory::getDate($input, 'UTC');
  690. // Set the correct time zone based on the server configuration.
  691. $date->setTimeZone(new DateTimeZone($tz));
  692. }
  693. // If no format is given use the default locale based format.
  694. if (!$format)
  695. {
  696. $format = JText::_('DATE_FORMAT_LC1');
  697. }
  698. // $format is an existing language key
  699. elseif (JFactory::getLanguage()->hasKey($format))
  700. {
  701. $format = JText::_($format);
  702. }
  703. if ($gregorian)
  704. {
  705. return $date->format($format, true);
  706. }
  707. else
  708. {
  709. return $date->calendar($format, true);
  710. }
  711. }
  712. /**
  713. * Creates a tooltip with an image as button
  714. *
  715. * @param string $tooltip The tip string
  716. * @param mixed $title The title of the tooltip or an associative array with keys contained in
  717. * {'title','image','text','href','alt'} and values corresponding to parameters of the same name.
  718. * @param string $image The image for the tip, if no text is provided
  719. * @param string $text The text for the tip
  720. * @param string $href An URL that will be used to create the link
  721. * @param string $alt The alt attribute for img tag
  722. * @param string $class CSS class for the tool tip
  723. *
  724. * @return string
  725. *
  726. * @since 11.1
  727. */
  728. public static function tooltip($tooltip, $title = '', $image = 'tooltip.png', $text = '', $href = '', $alt = 'Tooltip', $class = 'hasTip')
  729. {
  730. if (is_array($title))
  731. {
  732. foreach (array('image', 'text', 'href', 'alt', 'class') as $param)
  733. {
  734. if (isset($title[$param]))
  735. {
  736. $$param = $title[$param];
  737. }
  738. }
  739. if (isset($title['title']))
  740. {
  741. $title = $title['title'];
  742. }
  743. else
  744. {
  745. $title = '';
  746. }
  747. }
  748. $tooltip = htmlspecialchars($tooltip, ENT_COMPAT, 'UTF-8');
  749. $title = htmlspecialchars($title, ENT_COMPAT, 'UTF-8');
  750. $alt = htmlspecialchars($alt, ENT_COMPAT, 'UTF-8');
  751. if (!$text)
  752. {
  753. $text = self::image($image, $alt, null, true);
  754. }
  755. if ($href)
  756. {
  757. $tip = '<a href="' . $href . '">' . $text . '</a>';
  758. }
  759. else
  760. {
  761. $tip = $text;
  762. }
  763. if ($title)
  764. {
  765. $tooltip = $title . '::' . $tooltip;
  766. }
  767. return '<span class="' . $class . '" title="' . $tooltip . '">' . $tip . '</span>';
  768. }
  769. /**
  770. * Displays a calendar control field
  771. *
  772. * @param string $value The date value
  773. * @param string $name The name of the text field
  774. * @param string $id The id of the text field
  775. * @param string $format The date format
  776. * @param array $attribs Additional HTML attributes
  777. *
  778. * @return string HTML markup for a calendar field
  779. *
  780. * @since 11.1
  781. */
  782. public static function calendar($value, $name, $id, $format = '%Y-%m-%d', $attribs = null)
  783. {
  784. static $done;
  785. if ($done === null)
  786. {
  787. $done = array();
  788. }
  789. $readonly = isset($attribs['readonly']) && $attribs['readonly'] == 'readonly';
  790. $disabled = isset($attribs['disabled']) && $attribs['disabled'] == 'disabled';
  791. if (is_array($attribs))
  792. {
  793. $attribs = JArrayHelper::toString($attribs);
  794. }
  795. if (!$readonly && !$disabled)
  796. {
  797. // Load the calendar behavior
  798. self::_('behavior.calendar');
  799. self::_('behavior.tooltip');
  800. // Only display the triggers once for each control.
  801. if (!in_array($id, $done))
  802. {
  803. $document = JFactory::getDocument();
  804. $document
  805. ->addScriptDeclaration(
  806. 'window.addEvent(\'domready\', function() {Calendar.setup({
  807. // Id of the input field
  808. inputField: "' . $id . '",
  809. // Format of the input field
  810. ifFormat: "' . $format . '",
  811. // Trigger for the calendar (button ID)
  812. button: "' . $id . '_img",
  813. // Alignment (defaults to "Bl")
  814. align: "Tl",
  815. singleClick: true,
  816. firstDay: ' . JFactory::getLanguage()->getFirstDay() . '
  817. });});'
  818. );
  819. $done[] = $id;
  820. }
  821. return '<div class="input-append"><input type="text" title="' . (0 !== (int) $value ? self::_('date', $value, null, null) : '')
  822. . '" name="' . $name . '" id="' . $id . '" value="' . htmlspecialchars($value, ENT_COMPAT, 'UTF-8') . '" ' . $attribs . ' />'
  823. . '<button class="btn" id="' . $id . '_img"><i class="icon-calendar"></i></button></div>';
  824. }
  825. else
  826. {
  827. return '<input type="text" title="' . (0 !== (int) $value ? self::_('date', $value, null, null) : '')
  828. . '" value="' . (0 !== (int) $value ? self::_('date', $value, 'Y-m-d H:i:s', null) : '') . '" ' . $attribs
  829. . ' /><input type="hidden" name="' . $name . '" id="' . $id . '" value="' . htmlspecialchars($value, ENT_COMPAT, 'UTF-8') . '" />';
  830. }
  831. }
  832. /**
  833. * Add a directory where JHtml should search for helpers. You may
  834. * either pass a string or an array of directories.
  835. *
  836. * @param string $path A path to search.
  837. *
  838. * @return array An array with directory elements
  839. *
  840. * @since 11.1
  841. */
  842. public static function addIncludePath($path = '')
  843. {
  844. // Force path to array
  845. settype($path, 'array');
  846. // Loop through the path directories
  847. foreach ($path as $dir)
  848. {
  849. if (!empty($dir) && !in_array($dir, self::$includePaths))
  850. {
  851. jimport('joomla.filesystem.path');
  852. array_unshift(self::$includePaths, JPath::clean($dir));
  853. }
  854. }
  855. return self::$includePaths;
  856. }
  857. /**
  858. * Internal method to get a JavaScript object notation string from an array
  859. *
  860. * @param array $array The array to convert to JavaScript object notation
  861. *
  862. * @return string JavaScript object notation representation of the array
  863. *
  864. * @since 12.2
  865. */
  866. public static function getJSObject(array $array = array())
  867. {
  868. $elements = array();
  869. foreach ($array as $k => $v)
  870. {
  871. // Don't encode either of these types
  872. if (is_null($v) || is_resource($v))
  873. {
  874. continue;
  875. }
  876. // Safely encode as a Javascript string
  877. $key = json_encode((string) $k);
  878. if (is_bool($v))
  879. {
  880. $elements[] = $key . ': ' . ($v ? 'true' : 'false');
  881. }
  882. elseif (is_numeric($v))
  883. {
  884. $elements[] = $key . ': ' . ($v + 0);
  885. }
  886. elseif (is_string($v))
  887. {
  888. if (strpos($v, '\\') === 0)
  889. {
  890. // Items such as functions and JSON objects are prefixed with \, strip the prefix and don't encode them
  891. $elements[] = $key . ': ' . substr($v, 1);
  892. }
  893. else
  894. {
  895. // The safest way to insert a string
  896. $elements[] = $key . ': ' . json_encode((string) $v);
  897. }
  898. }
  899. else
  900. {
  901. $elements[] = $key . ': ' . self::getJSObject(is_object($v) ? get_object_vars($v) : $v);
  902. }
  903. }
  904. return '{' . implode(',', $elements) . '}';
  905. }
  906. }