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