* * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /** * UrlHelper. * * @package symfony * @subpackage helper * @author Fabien Potencier * @version SVN: $Id: UrlHelper.php 27597 2010-02-05 16:37:22Z FabianLange $ */ function link_to2($name, $routeName, $params, $options = array()) { $params = array_merge(array('sf_route' => $routeName), is_object($params) ? array('sf_subject' => $params) : $params); return link_to1($name, $params, $options); } function link_to1($name, $internal_uri, $options = array()) { $html_options = _parse_attributes($options); $html_options = _convert_options_to_javascript($html_options); $absolute = false; if (isset($html_options['absolute_url'])) { $html_options['absolute'] = $html_options['absolute_url']; unset($html_options['absolute_url']); } if (isset($html_options['absolute'])) { $absolute = (boolean) $html_options['absolute']; unset($html_options['absolute']); } $html_options['href'] = url_for($internal_uri, $absolute); if (isset($html_options['query_string'])) { $html_options['href'] .= '?'.$html_options['query_string']; unset($html_options['query_string']); } if (isset($html_options['anchor'])) { $html_options['href'] .= '#'.$html_options['anchor']; unset($html_options['anchor']); } if (is_object($name)) { if (method_exists($name, '__toString')) { $name = $name->__toString(); } else { throw new sfException(sprintf('Object of class "%s" cannot be converted to string (Please create a __toString() method).', get_class($name))); } } if (!strlen($name)) { $name = $html_options['href']; } return content_tag('a', $name, $html_options); } function url_for2($routeName, $params = array(), $absolute = false) { $params = array_merge(array('sf_route' => $routeName), is_object($params) ? array('sf_subject' => $params) : $params); return url_for1($params, $absolute); } function url_for1($internal_uri, $absolute = false) { return sfContext::getInstance()->getController()->genUrl($internal_uri, $absolute); } /** * Returns a routed URL based on the module/action passed as argument * and the routing configuration. * * Examples: * * echo url_for('my_module/my_action'); * => /path/to/my/action * echo url_for('@my_rule'); * => /path/to/my/action * echo url_for('@my_rule', true); * => http://myapp.example.com/path/to/my/action * * * @param string $internal_uri 'module/action' or '@rule' of the action * @param bool $absolute return absolute path? * @return string routed URL */ function url_for() { // for BC with 1.1 $arguments = func_get_args(); if (is_array($arguments[0]) || '@' == substr($arguments[0], 0, 1) || false !== strpos($arguments[0], '/')) { return call_user_func_array('url_for1', $arguments); } else { return call_user_func_array('url_for2', $arguments); } } /** * Creates a link tag of the given name using a routed URL * based on the module/action passed as argument and the routing configuration. * It's also possible to pass a string instead of a module/action pair to * get a link tag that just points without consideration. * If null is passed as a name, the link itself will become the name. * If an object is passed as a name, the object string representation is used. * One of the options serves for for creating javascript confirm alerts where * if you pass 'confirm' => 'Are you sure?', the link will be guarded * with a JS popup asking that question. If the user accepts, the link is processed, * otherwise not. * * Options: * - 'absolute' - if set to true, the helper outputs an absolute URL * - 'query_string' - to append a query string (starting by ?) to the routed url * - 'anchor' - to append an anchor (starting by #) to the routed url * - 'confirm' - displays a javascript confirmation alert when the link is clicked * - 'popup' - if set to true, the link opens a new browser window * - 'post' - if set to true, the link submits a POST request instead of GET (caution: do not use inside a form) * - 'method' - if set to post, delete, or put, the link submits a request with the given HTTP method instead of GET (caution: do not use inside a form) * * Note: The 'popup', 'post', and 'method' options are not compatible with each other. * * Examples: * * echo link_to('Delete this page', 'my_module/my_action'); * => Delete this page * echo link_to('Visit Hoogle', 'http://www.hoogle.com'); * => Visit Hoogle * echo link_to('Delete this page', 'my_module/my_action', array('id' => 'myid', 'confirm' => 'Are you sure?', 'absolute' => true)); * => Delete this page * * * @param string $name name of the link, i.e. string to appear between the tags * @param string $internal_uri 'module/action' or '@rule' of the action * @param array $options additional HTML compliant tag parameters * @return string XHTML compliant tag * @see url_for */ function link_to() { // for BC with 1.1 $arguments = func_get_args(); if (empty($arguments[1]) || is_array($arguments[1]) || '@' == substr($arguments[1], 0, 1) || false !== strpos($arguments[1], '/')) { return call_user_func_array('link_to1', $arguments); } else { if (!array_key_exists(2, $arguments)) { $arguments[2] = array(); } return call_user_func_array('link_to2', $arguments); } } function url_for_form(sfForm $form, $routePrefix) { $format = '%s/%s'; if ('@' == $routePrefix[0]) { $format = '%s_%s'; $routePrefix = substr($routePrefix, 1); } $uri = sprintf($format, $routePrefix, $form->getObject()->isNew() ? 'create' : 'update'); return url_for($uri, $form->getObject()); } function form_tag_for(sfForm $form, $routePrefix, $attributes = array()) { return $form->renderFormTag(url_for_form($form, $routePrefix), $attributes); } /** * If the condition passed as first argument is true, * creates a link tag of the given name using a routed URL * based on the module/action passed as argument and the routing configuration. * If the condition is false, the given name is returned between tags * * Options: * - 'tag' - the HTML tag that must enclose the name if the condition is false, defaults to * - 'absolute' - if set to true, the helper outputs an absolute URL * - 'query_string' - to append a query string (starting by ?) to the routed url * - 'anchor' - to append an anchor (starting by #) to the routed url * - 'confirm' - displays a javascript confirmation alert when the link is clicked * - 'popup' - if set to true, the link opens a new browser window * - 'post' - if set to true, the link submits a POST request instead of GET (caution: do not use inside a form) * * Examples: * * echo link_to_if($user->isAdministrator(), 'Delete this page', 'my_module/my_action'); * => Delete this page * echo link_to_if(!$user->isAdministrator(), 'Delete this page', 'my_module/my_action'); * => Delete this page * * * @param bool $condition condition * @param string $name name of the link, i.e. string to appear between the tags * @param string $internal_uri 'module/action' or '@rule' of the action * @param array $options additional HTML compliant tag parameters * @return string XHTML compliant tag or name * @see link_to */ function link_to_if($condition, $name = '', $internal_uri = '', $options = array()) { $html_options = _parse_attributes($options); if ($condition) { unset($html_options['tag']); return link_to($name, $internal_uri, $html_options); } else { unset($html_options['query_string']); unset($html_options['absolute_url']); unset($html_options['absolute']); $tag = _get_option($html_options, 'tag', 'span'); return content_tag($tag, $name, $html_options); } } /** * If the condition passed as first argument is false, * creates a link tag of the given name using a routed URL * based on the module/action passed as argument and the routing configuration. * If the condition is true, the given name is returned between tags * * Options: * - 'tag' - the HTML tag that must enclose the name if the condition is true, defaults to * - 'absolute' - if set to true, the helper outputs an absolute URL * - 'query_string' - to append a query string (starting by ?) to the routed url * - 'anchor' - to append an anchor (starting by #) to the routed url * - 'confirm' - displays a javascript confirmation alert when the link is clicked * - 'popup' - if set to true, the link opens a new browser window * - 'post' - if set to true, the link submits a POST request instead of GET (caution: do not use inside a form) * * Examples: * * echo link_to_unless($user->isAdministrator(), 'Delete this page', 'my_module/my_action'); * => Delete this page * echo link_to_unless(!$user->isAdministrator(), 'Delete this page', 'my_module/my_action'); * => Delete this page * * * @param bool $condition condition * @param string $name name of the link, i.e. string to appear between the tags * @param string $internal_uri 'module/action' or '@rule' of the action * @param array $options additional HTML compliant tag parameters * @return string XHTML compliant tag or name * @see link_to */ function link_to_unless($condition, $name = '', $internal_uri = '', $options = array()) { return link_to_if(!$condition, $name, $internal_uri, $options); } /** * Returns a URL rooted at the web root * * @param string $path The route to append * @param bool $absolute If true, an absolute path is returned (optional) * @return The web URL root */ function public_path($path, $absolute = false) { $request = sfContext::getInstance()->getRequest(); $root = $request->getRelativeUrlRoot(); if ($absolute) { $source = 'http'; if ($request->isSecure()) { $source .= 's'; } $source .='://'.$request->getHost().$root; } else { $source = $root; } if (substr($path, 0, 1) != '/') { $path = '/'.$path; } return $source.$path; } /** * Creates an button tag of the given name pointing to a routed URL * based on the module/action passed as argument and the routing configuration. * The syntax is similar to the one of link_to. * * Options: * - 'absolute' - if set to true, the helper outputs an absolute URL * - 'query_string' - to append a query string (starting by ?) to the routed url * - 'anchor' - to append an anchor (starting by #) to the routed url * - 'confirm' - displays a javascript confirmation alert when the button is clicked * - 'popup' - if set to true, the button opens a new browser window * - 'post' - if set to true, the button submits a POST request instead of GET (caution: do not use inside a form) * * Examples: * * echo button_to('Delete this page', 'my_module/my_action'); * => * * * @param string $name name of the button * @param string $internal_uri 'module/action' or '@rule' of the action * @param array $options additional HTML compliant tag parameters * @return string XHTML compliant tag * @see url_for, link_to */ function button_to($name, $internal_uri, $options = array()) { $html_options = _parse_attributes($options); $html_options['value'] = $name; if (isset($html_options['post']) && $html_options['post']) { if (isset($html_options['popup'])) { throw new sfConfigurationException('You can\'t use "popup" and "post" together.'); } $html_options['type'] = 'submit'; unset($html_options['post']); $html_options = _convert_options_to_javascript($html_options); return form_tag($internal_uri, array('method' => 'post', 'class' => 'button_to')).content_tag('div', tag('input', $html_options)).''; } $url = url_for($internal_uri); if (isset($html_options['query_string'])) { $url = $url.'?'.$html_options['query_string']; unset($html_options['query_string']); } if (isset($html_options['anchor'])) { $url = $url.'#'.$html_options['anchor']; unset($html_options['anchor']); } $url = "'".$url."'"; $html_options['type'] = 'button'; if (isset($html_options['popup'])) { $html_options = _convert_options_to_javascript($html_options, $url); unset($html_options['popup']); } else { $html_options['onclick'] = "document.location.href=".$url.";"; $html_options = _convert_options_to_javascript($html_options); } return tag('input', $html_options); } /** * Creates a link tag to the given email (with href="mailto:..."). * If null is passed as a name, the email itself will become the name. * * Options: * - 'encode' - if set to true, the email address appears with various random encoding for each letter. * The mail link still works when encoded, but the address doesn't appear in clear * in the source. Use it to prevent spam (efficiency not guaranteed). * * Examples: * * echo mail_to('webmaster@example.com'); * => webmaster@example.com * echo mail_to('webmaster@example.com', 'send us an email'); * => send us an email * echo mail_to('webmaster@example.com', 'send us an email', array('encode' => true)); * => send us an email * * * @param string $email target email * @param string $name name of the link, i.e. string to appear between the tags * @param array $options additional HTML compliant tag parameters * @param array $default_value * @return string XHTML compliant tag * @see link_to */ function mail_to($email, $name = '', $options = array(), $default_value = array()) { $html_options = _parse_attributes($options); $html_options = _convert_options_to_javascript($html_options); $default_tmp = _parse_attributes($default_value); $default = array(); foreach ($default_tmp as $key => $value) { $default[] = urlencode($key).'='.urlencode($value); } $options = count($default) ? '?'.implode('&', $default) : ''; if (isset($html_options['encode']) && $html_options['encode']) { unset($html_options['encode']); $html_options['href'] = _encodeText('mailto:'.$email.$options); if (!$name) { $name = _encodeText($email); } } else { $html_options['href'] = 'mailto:'.$email.$options; if (!$name) { $name = $email; } } return content_tag('a', $name, $html_options); } function _convert_options_to_javascript($html_options, $url = 'this.href') { // confirm $confirm = isset($html_options['confirm']) ? $html_options['confirm'] : ''; unset($html_options['confirm']); // popup $popup = isset($html_options['popup']) ? $html_options['popup'] : ''; unset($html_options['popup']); // method $method = isset($html_options['method']) ? $html_options['method'] : (isset($html_options['post']) && $html_options['post'] ? 'post' : false); unset($html_options['post'], $html_options['method']); $onclick = isset($html_options['onclick']) ? $html_options['onclick'] : ''; if ($popup && $method) { throw new sfConfigurationException('You can\'t use "popup", "method" and "post" in the same link.'); } else if ($confirm && $popup) { $html_options['onclick'] = $onclick.'if ('._confirm_javascript_function($confirm).') { '._popup_javascript_function($popup, $url).' };return false;'; } else if ($confirm && $method) { $html_options['onclick'] = $onclick.'if ('._confirm_javascript_function($confirm).') { '._method_javascript_function($method).' };return false;'; } else if ($confirm) { if ($onclick) { $html_options['onclick'] = 'if ('._confirm_javascript_function($confirm).') { return '.$onclick.'} else return false;'; } else { $html_options['onclick'] = 'return '._confirm_javascript_function($confirm).';'; } } else if ($method) { $html_options['onclick'] = $onclick._method_javascript_function($method).'return false;'; } else if ($popup) { $html_options['onclick'] = $onclick._popup_javascript_function($popup, $url).'return false;'; } return $html_options; } function _confirm_javascript_function($confirm) { return "confirm('".escape_javascript($confirm)."')"; } function _popup_javascript_function($popup, $url = '') { if (is_array($popup)) { if (isset($popup[1])) { return "var w=window.open(".$url.",'".$popup[0]."','".$popup[1]."');w.focus();"; } else { return "var w=window.open(".$url.",'".$popup[0]."');w.focus();"; } } else { return "var w=window.open(".$url.");w.focus();"; } } function _post_javascript_function() { return _method_javascript_function('POST'); } function _method_javascript_function($method) { $function = "var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'post'; f.action = this.href;"; if ('post' != strtolower($method)) { $function .= "var m = document.createElement('input'); m.setAttribute('type', 'hidden'); "; $function .= sprintf("m.setAttribute('name', 'sf_method'); m.setAttribute('value', '%s'); f.appendChild(m);", strtolower($method)); } // CSRF protection $form = new sfForm(); if ($form->isCSRFProtected()) { $function .= "var m = document.createElement('input'); m.setAttribute('type', 'hidden'); "; $function .= sprintf("m.setAttribute('name', '%s'); m.setAttribute('value', '%s'); f.appendChild(m);", $form->getCSRFFieldName(), $form->getCSRFToken()); } $function .= "f.submit();"; return $function; } function _encodeText($text) { $encoded_text = ''; for ($i = 0; $i < strlen($text); $i++) { $char = $text{$i}; $r = rand(0, 100); # roughly 10% raw, 45% hex, 45% dec # '@' *must* be encoded. I insist. if ($r > 90 && $char != '@') { $encoded_text .= $char; } else if ($r < 45) { $encoded_text .= '&#x'.dechex(ord($char)).';'; } else { $encoded_text .= '&#'.ord($char).';'; } } return $encoded_text; }