AssetHelper.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  1. <?php
  2. /*
  3. * This file is part of the symfony package.
  4. * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
  5. * (c) 2004 David Heinemeier Hansson
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. /**
  11. * AssetHelper.
  12. *
  13. * @package symfony
  14. * @subpackage helper
  15. * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  16. * @author David Heinemeier Hansson
  17. * @version SVN: $Id: AssetHelper.php 13476 2008-11-29 03:00:16Z dwhittle $
  18. */
  19. /**
  20. * Returns a <link> tag that browsers and news readers
  21. * can use to auto-detect a RSS or ATOM feed for the current page,
  22. * to be included in the <head> section of a HTML document.
  23. *
  24. * <b>Options:</b>
  25. * - rel - defaults to 'alternate'
  26. * - type - defaults to 'application/rss+xml'
  27. * - title - defaults to the feed type in upper case
  28. *
  29. * <b>Examples:</b>
  30. * <code>
  31. * echo auto_discovery_link_tag('rss', 'module/feed');
  32. * => <link rel="alternate" type="application/rss+xml" title="RSS" href="http://www.curenthost.com/module/feed" />
  33. * echo auto_discovery_link_tag('rss', 'module/feed', array('title' => 'My RSS'));
  34. * => <link rel="alternate" type="application/rss+xml" title="My RSS" href="http://www.curenthost.com/module/feed" />
  35. * </code>
  36. *
  37. * @param string $type feed type ('rss', 'atom')
  38. * @param string $url 'module/action' or '@rule' of the feed
  39. * @param array $tag_options additional HTML compliant <link> tag parameters
  40. *
  41. * @return string XHTML compliant <link> tag
  42. */
  43. function auto_discovery_link_tag($type = 'rss', $url = '', $tag_options = array())
  44. {
  45. return tag('link', array(
  46. 'rel' => isset($tag_options['rel']) ? $tag_options['rel'] : 'alternate',
  47. 'type' => isset($tag_options['type']) ? $tag_options['type'] : 'application/'.$type.'+xml',
  48. 'title' => isset($tag_options['title']) ? $tag_options['title'] : ucfirst($type),
  49. 'href' => url_for($url, true)
  50. ));
  51. }
  52. /**
  53. * Returns the path to a JavaScript asset.
  54. *
  55. * <b>Example:</b>
  56. * <code>
  57. * echo javascript_path('myscript');
  58. * => /js/myscript.js
  59. * </code>
  60. *
  61. * <b>Note:</b> The asset name can be supplied as a...
  62. * - full path, like "/my_js/myscript.css"
  63. * - file name, like "myscript.js", that gets expanded to "/js/myscript.js"
  64. * - file name without extension, like "myscript", that gets expanded to "/js/myscript.js"
  65. *
  66. * @param string $source asset name
  67. * @param bool $absolute return absolute path ?
  68. *
  69. * @return string file path to the JavaScript file
  70. * @see javascript_include_tag
  71. */
  72. function javascript_path($source, $absolute = false)
  73. {
  74. return _compute_public_path($source, 'js', 'js', $absolute);
  75. }
  76. /**
  77. * Returns a <script> include tag per source given as argument.
  78. *
  79. * <b>Examples:</b>
  80. * <code>
  81. * echo javascript_include_tag('xmlhr');
  82. * => <script language="JavaScript" type="text/javascript" src="/js/xmlhr.js"></script>
  83. * echo javascript_include_tag('common.javascript', '/elsewhere/cools');
  84. * => <script language="JavaScript" type="text/javascript" src="/js/common.javascript"></script>
  85. * <script language="JavaScript" type="text/javascript" src="/elsewhere/cools.js"></script>
  86. * </code>
  87. *
  88. * @param string asset names
  89. * @param array additional HTML compliant <link> tag parameters
  90. *
  91. * @return string XHTML compliant <script> tag(s)
  92. * @see javascript_path
  93. */
  94. function javascript_include_tag()
  95. {
  96. $sources = func_get_args();
  97. $sourceOptions = (func_num_args() > 1 && is_array($sources[func_num_args() - 1])) ? array_pop($sources) : array();
  98. $html = '';
  99. foreach ($sources as $source)
  100. {
  101. $absolute = false;
  102. if (isset($sourceOptions['absolute']))
  103. {
  104. unset($sourceOptions['absolute']);
  105. $absolute = true;
  106. }
  107. $condition = null;
  108. if (isset($sourceOptions['condition']))
  109. {
  110. $condition = $sourceOptions['condition'];
  111. unset($sourceOptions['condition']);
  112. }
  113. if (!isset($sourceOptions['raw_name']))
  114. {
  115. $source = javascript_path($source, $absolute);
  116. }
  117. else
  118. {
  119. unset($sourceOptions['raw_name']);
  120. }
  121. $options = array_merge(array('type' => 'text/javascript', 'src' => $source), $sourceOptions);
  122. $tag = content_tag('script', '', $options);
  123. if (!is_null($condition))
  124. {
  125. $tag = comment_as_conditional($condition, $tag);
  126. }
  127. $html .= $tag."\n";
  128. }
  129. return $html;
  130. }
  131. /**
  132. * Returns the path to a stylesheet asset.
  133. *
  134. * <b>Example:</b>
  135. * <code>
  136. * echo stylesheet_path('style');
  137. * => /css/style.css
  138. * </code>
  139. *
  140. * <b>Note:</b> The asset name can be supplied as a...
  141. * - full path, like "/my_css/style.css"
  142. * - file name, like "style.css", that gets expanded to "/css/style.css"
  143. * - file name without extension, like "style", that gets expanded to "/css/style.css"
  144. *
  145. * @param string $source asset name
  146. * @param bool $absolute return absolute path ?
  147. *
  148. * @return string file path to the stylesheet file
  149. * @see stylesheet_tag
  150. */
  151. function stylesheet_path($source, $absolute = false)
  152. {
  153. return _compute_public_path($source, 'css', 'css', $absolute);
  154. }
  155. /**
  156. * Returns a css <link> tag per source given as argument,
  157. * to be included in the <head> section of a HTML document.
  158. *
  159. * <b>Options:</b>
  160. * - rel - defaults to 'stylesheet'
  161. * - type - defaults to 'text/css'
  162. * - media - defaults to 'screen'
  163. *
  164. * <b>Examples:</b>
  165. * <code>
  166. * echo stylesheet_tag('style');
  167. * => <link href="/stylesheets/style.css" media="screen" rel="stylesheet" type="text/css" />
  168. * echo stylesheet_tag('style', array('media' => 'all'));
  169. * => <link href="/stylesheets/style.css" media="all" rel="stylesheet" type="text/css" />
  170. * echo stylesheet_tag('style', array('raw_name' => true));
  171. * => <link href="style" media="all" rel="stylesheet" type="text/css" />
  172. * echo stylesheet_tag('random.styles', '/css/stylish');
  173. * => <link href="/stylesheets/random.styles" media="screen" rel="stylesheet" type="text/css" />
  174. * <link href="/css/stylish.css" media="screen" rel="stylesheet" type="text/css" />
  175. * </code>
  176. *
  177. * @param string asset names
  178. * @param array additional HTML compliant <link> tag parameters
  179. *
  180. * @return string XHTML compliant <link> tag(s)
  181. * @see stylesheet_path
  182. */
  183. function stylesheet_tag()
  184. {
  185. $sources = func_get_args();
  186. $sourceOptions = (func_num_args() > 1 && is_array($sources[func_num_args() - 1])) ? array_pop($sources) : array();
  187. $html = '';
  188. foreach ($sources as $source)
  189. {
  190. $absolute = false;
  191. if (isset($sourceOptions['absolute']))
  192. {
  193. unset($sourceOptions['absolute']);
  194. $absolute = true;
  195. }
  196. $condition = null;
  197. if (isset($sourceOptions['condition']))
  198. {
  199. $condition = $sourceOptions['condition'];
  200. unset($sourceOptions['condition']);
  201. }
  202. if (!isset($sourceOptions['raw_name']))
  203. {
  204. $source = stylesheet_path($source, $absolute);
  205. }
  206. else
  207. {
  208. unset($sourceOptions['raw_name']);
  209. }
  210. $options = array_merge(array('rel' => 'stylesheet', 'type' => 'text/css', 'media' => 'screen', 'href' => $source), $sourceOptions);
  211. $tag = tag('link', $options);
  212. if (!is_null($condition))
  213. {
  214. $tag = comment_as_conditional($condition, $tag);
  215. }
  216. $html .= $tag."\n";
  217. }
  218. return $html;
  219. }
  220. /**
  221. * Adds a stylesheet to the response object.
  222. *
  223. * @see sfResponse->addStylesheet()
  224. */
  225. function use_stylesheet($css, $position = '', $options = array())
  226. {
  227. sfContext::getInstance()->getResponse()->addStylesheet($css, $position, $options);
  228. }
  229. /**
  230. * Adds a javascript to the response object.
  231. *
  232. * @see sfResponse->addJavascript()
  233. */
  234. function use_javascript($js, $position = '', $options = array())
  235. {
  236. sfContext::getInstance()->getResponse()->addJavascript($js, $position, $options);
  237. }
  238. /**
  239. * Decorates the current template with a given layout.
  240. *
  241. * @param mixed $layout The layout name or path or false to disable the layout
  242. */
  243. function decorate_with($layout)
  244. {
  245. if (false === $layout)
  246. {
  247. sfContext::getInstance()->get('view_instance')->setDecorator(false);
  248. }
  249. else
  250. {
  251. sfContext::getInstance()->get('view_instance')->setDecoratorTemplate($layout);
  252. }
  253. }
  254. /**
  255. * Returns the path to an image asset.
  256. *
  257. * <b>Example:</b>
  258. * <code>
  259. * echo image_path('foobar');
  260. * => /images/foobar.png
  261. * </code>
  262. *
  263. * <b>Note:</b> The asset name can be supplied as a...
  264. * - full path, like "/my_images/image.gif"
  265. * - file name, like "rss.gif", that gets expanded to "/images/rss.gif"
  266. * - file name without extension, like "logo", that gets expanded to "/images/logo.png"
  267. *
  268. * @param string $source asset name
  269. * @param bool $absolute return absolute path ?
  270. *
  271. * @return string file path to the image file
  272. * @see image_tag
  273. */
  274. function image_path($source, $absolute = false)
  275. {
  276. return _compute_public_path($source, 'images', 'png', $absolute);
  277. }
  278. /**
  279. * Returns an <img> image tag for the asset given as argument.
  280. *
  281. * <b>Options:</b>
  282. * - 'absolute' - to output absolute file paths, useful for embedded images in emails
  283. * - 'alt' - defaults to the file name part of the asset (capitalized and without the extension)
  284. * - 'size' - Supplied as "XxY", so "30x45" becomes width="30" and height="45"
  285. *
  286. * <b>Examples:</b>
  287. * <code>
  288. * echo image_tag('foobar');
  289. * => <img src="images/foobar.png" alt="Foobar" />
  290. * echo image_tag('/my_images/image.gif', array('alt' => 'Alternative text', 'size' => '100x200'));
  291. * => <img src="/my_images/image.gif" alt="Alternative text" width="100" height="200" />
  292. * </code>
  293. *
  294. * @param string $source image asset name
  295. * @param array $options additional HTML compliant <img> tag parameters
  296. *
  297. * @return string XHTML compliant <img> tag
  298. * @see image_path
  299. */
  300. function image_tag($source, $options = array())
  301. {
  302. if (!$source)
  303. {
  304. return '';
  305. }
  306. $options = _parse_attributes($options);
  307. $absolute = false;
  308. if (isset($options['absolute']))
  309. {
  310. unset($options['absolute']);
  311. $absolute = true;
  312. }
  313. if (!isset($options['raw_name']))
  314. {
  315. $options['src'] = image_path($source, $absolute);
  316. }
  317. else
  318. {
  319. $options['src'] = $source;
  320. unset($options['raw_name']);
  321. }
  322. if (isset($options['alt_title']))
  323. {
  324. // set as alt and title but do not overwrite explicitly set
  325. if (!isset($options['alt']))
  326. {
  327. $options['alt'] = $options['alt_title'];
  328. }
  329. if (!isset($options['title']))
  330. {
  331. $options['title'] = $options['alt_title'];
  332. }
  333. unset($options['alt_title']);
  334. }
  335. if (!isset($options['alt']) && sfConfig::get('sf_compat_10'))
  336. {
  337. $path_pos = strrpos($source, '/');
  338. $dot_pos = strrpos($source, '.');
  339. $begin = $path_pos ? $path_pos + 1 : 0;
  340. $nb_str = ($dot_pos ? $dot_pos : strlen($source)) - $begin;
  341. $options['alt'] = ucfirst(substr($source, $begin, $nb_str));
  342. }
  343. if (isset($options['size']))
  344. {
  345. list($options['width'], $options['height']) = explode('x', $options['size'], 2);
  346. unset($options['size']);
  347. }
  348. return tag('img', $options);
  349. }
  350. function _compute_public_path($source, $dir, $ext, $absolute = false)
  351. {
  352. if (strpos($source, '://'))
  353. {
  354. return $source;
  355. }
  356. $request = sfContext::getInstance()->getRequest();
  357. $sf_relative_url_root = $request->getRelativeUrlRoot();
  358. if (0 !== strpos($source, '/'))
  359. {
  360. $source = $sf_relative_url_root.'/'.$dir.'/'.$source;
  361. }
  362. $query_string = '';
  363. if (false !== $pos = strpos($source, '?'))
  364. {
  365. $query_string = substr($source, $pos);
  366. $source = substr($source, 0, $pos);
  367. }
  368. if (false === strpos(basename($source), '.'))
  369. {
  370. $source .= '.'.$ext;
  371. }
  372. if ($sf_relative_url_root && 0 !== strpos($source, $sf_relative_url_root))
  373. {
  374. $source = $sf_relative_url_root.$source;
  375. }
  376. if ($absolute)
  377. {
  378. $source = 'http'.($request->isSecure() ? 's' : '').'://'.$request->getHost().$source;
  379. }
  380. return $source.$query_string;
  381. }
  382. /**
  383. * Prints a set of <meta> tags according to the response attributes,
  384. * to be included in the <head> section of a HTML document.
  385. *
  386. * <b>Examples:</b>
  387. * <code>
  388. * include_metas();
  389. * => <meta name="title" content="symfony - open-source PHP5 web framework" />
  390. * <meta name="robots" content="index, follow" />
  391. * <meta name="description" content="symfony - open-source PHP5 web framework" />
  392. * <meta name="keywords" content="symfony, project, framework, php, php5, open-source, mit, symphony" />
  393. * <meta name="language" content="en" /><link href="/stylesheets/style.css" media="screen" rel="stylesheet" type="text/css" />
  394. * </code>
  395. *
  396. * <b>Note:</b> Modify the view.yml or use sfWebResponse::addMeta() to change, add or remove metas.
  397. *
  398. * @return string XHTML compliant <meta> tag(s)
  399. * @see include_http_metas
  400. * @see sfWebResponse::addMeta()
  401. */
  402. function include_metas()
  403. {
  404. $context = sfContext::getInstance();
  405. $i18n = sfConfig::get('sf_i18n') ? $context->getI18N() : null;
  406. foreach ($context->getResponse()->getMetas() as $name => $content)
  407. {
  408. echo tag('meta', array('name' => $name, 'content' => is_null($i18n) ? $content : $i18n->__($content)))."\n";
  409. }
  410. }
  411. /**
  412. * Returns a set of <meta http-equiv> tags according to the response attributes,
  413. * to be included in the <head> section of a HTML document.
  414. *
  415. * <b>Examples:</b>
  416. * <code>
  417. * include_http_metas();
  418. * => <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  419. * </code>
  420. *
  421. * <b>Note:</b> Modify the view.yml or use sfWebResponse::addMeta() to change, add or remove HTTP metas.
  422. *
  423. * @return string XHTML compliant <meta> tag(s)
  424. * @see include_metas
  425. * @see sfWebResponse::addHttpMeta()
  426. */
  427. function include_http_metas()
  428. {
  429. foreach (sfContext::getInstance()->getResponse()->getHttpMetas() as $httpequiv => $value)
  430. {
  431. echo tag('meta', array('http-equiv' => $httpequiv, 'content' => $value))."\n";
  432. }
  433. }
  434. /**
  435. * Returns the title of the current page according to the response attributes,
  436. * to be included in the <title> section of a HTML document.
  437. *
  438. * <b>Note:</b> Modify the sfResponse object or the view.yml to modify the title of a page.
  439. *
  440. * @return string page title
  441. */
  442. function include_title()
  443. {
  444. $title = sfContext::getInstance()->getResponse()->getTitle();
  445. echo content_tag('title', $title)."\n";
  446. }
  447. /**
  448. * Returns <script> tags for all javascripts configured in view.yml or added to the response object.
  449. *
  450. * You can use this helper to decide the location of javascripts in pages.
  451. * By default, if you don't call this helper, symfony will automatically include javascripts before </head>.
  452. * Calling this helper disables this behavior.
  453. *
  454. * @return string <script> tags
  455. */
  456. function get_javascripts()
  457. {
  458. $response = sfContext::getInstance()->getResponse();
  459. sfConfig::set('symfony.asset.javascripts_included', true);
  460. $html = '';
  461. foreach ($response->getJavascripts() as $file => $options)
  462. {
  463. $html .= javascript_include_tag($file, $options);
  464. }
  465. return $html;
  466. }
  467. /**
  468. * Prints <script> tags for all javascripts configured in view.yml or added to the response object.
  469. *
  470. * @see get_javascripts()
  471. */
  472. function include_javascripts()
  473. {
  474. echo get_javascripts();
  475. }
  476. /**
  477. * Returns <link> tags for all stylesheets configured in view.yml or added to the response object.
  478. *
  479. * You can use this helper to decide the location of stylesheets in pages.
  480. * By default, if you don't call this helper, symfony will automatically include stylesheets before </head>.
  481. * Calling this helper disables this behavior.
  482. *
  483. * @return string <link> tags
  484. */
  485. function get_stylesheets()
  486. {
  487. $response = sfContext::getInstance()->getResponse();
  488. sfConfig::set('symfony.asset.stylesheets_included', true);
  489. $html = '';
  490. foreach ($response->getStylesheets() as $file => $options)
  491. {
  492. $html .= stylesheet_tag($file, $options);
  493. }
  494. return $html;
  495. }
  496. /**
  497. * Prints <link> tags for all stylesheets configured in view.yml or added to the response object.
  498. *
  499. * @see get_stylesheets()
  500. */
  501. function include_stylesheets()
  502. {
  503. echo get_stylesheets();
  504. }
  505. /**
  506. * Returns a <script> include tag for the given internal URI.
  507. *
  508. * The helper automatically adds the sf_format to the internal URI, so you don't have to.
  509. *
  510. * @param string $uri The internal URI for the dynamic javascript
  511. * @param bool $absolute Whether to generate an absolute URL
  512. * @param array $options An array of options
  513. *
  514. * @return string XHTML compliant <script> tag(s)
  515. * @see javascript_include_tag
  516. */
  517. function dynamic_javascript_include_tag($uri, $absolute = false, $options = array())
  518. {
  519. $options['raw_name'] = true;
  520. return javascript_include_tag(_dynamic_path($uri, 'js', $absolute), $options);
  521. }
  522. /**
  523. * Adds a dynamic javascript to the response object.
  524. *
  525. * The first argument is an internal URI.
  526. * The helper automatically adds the sf_format to the internal URI, so you don't have to.
  527. *
  528. * @see sfResponse->addJavascript()
  529. */
  530. function use_dynamic_javascript($js, $position = '', $options = array())
  531. {
  532. $options['raw_name'] = true;
  533. return use_javascript(_dynamic_path($js, 'js'), $position, $options);
  534. }
  535. /**
  536. * Adds a dynamic stylesheet to the response object.
  537. *
  538. * The first argument is an internal URI.
  539. * The helper automatically adds the sf_format to the internal URI, so you don't have to.
  540. *
  541. * @see sfResponse->addStylesheet()
  542. */
  543. function use_dynamic_stylesheet($css, $position = '', $options = array())
  544. {
  545. $options['raw_name'] = true;
  546. return use_stylesheet(_dynamic_path($css, 'css'), $position, $options);
  547. }
  548. function _dynamic_path($uri, $format, $absolute = false)
  549. {
  550. return url_for($uri.(false === strpos($uri, '?') ? '?' : '&').'sf_format='.$format, $absolute);
  551. }
  552. /**
  553. * Returns <script> tags for all javascripts associated with the given form.
  554. *
  555. * @return string <script> tags
  556. */
  557. function get_javascripts_for_form(sfForm $form)
  558. {
  559. $html = '';
  560. foreach ($form->getJavascripts() as $file)
  561. {
  562. $html .= javascript_include_tag($file);
  563. }
  564. return $html;
  565. }
  566. /**
  567. * Prints <script> tags for all javascripts associated with the given form.
  568. *
  569. * @see get_javascripts_for_form()
  570. */
  571. function include_javascripts_for_form(sfForm $form)
  572. {
  573. echo get_javascripts_for_form($form);
  574. }
  575. /**
  576. * Returns <link> tags for all stylesheets associated with the given form.
  577. *
  578. * @return string <link> tags
  579. */
  580. function get_stylesheets_for_form(sfForm $form)
  581. {
  582. $html = '';
  583. foreach ($form->getStylesheets() as $file => $media)
  584. {
  585. $html .= stylesheet_tag($file, array('media' => $media));
  586. }
  587. return $html;
  588. }
  589. /**
  590. * Prints <link> tags for all stylesheets associated with the given form.
  591. *
  592. * @see get_stylesheets_for_form()
  593. */
  594. function include_stylesheets_for_form(sfForm $form)
  595. {
  596. echo get_stylesheets_for_form($form);
  597. }