|
@@ -207,7 +207,7 @@ function link_field_instance_settings_form($field, $instance) {
|
|
|
$form['attributes']['class'] = array(
|
|
|
'#type' => 'textfield',
|
|
|
'#title' => t('Additional CSS Class'),
|
|
|
- '#description' => t('When output, this link will have this class attribute. Multiple classes should be separated by spaces.'),
|
|
|
+ '#description' => t('When output, this link will have this class attribute. Multiple classes should be separated by spaces. Only alphanumeric characters and hyphens are allowed'),
|
|
|
'#default_value' => empty($instance['settings']['attributes']['class']) ? '' : $instance['settings']['attributes']['class'],
|
|
|
);
|
|
|
$form['attributes']['configurable_title'] = array(
|
|
@@ -291,7 +291,7 @@ function link_field_validate($entity_type, $entity, $field, $instance, $langcode
|
|
|
*/
|
|
|
function link_field_insert($entity_type, $entity, $field, $instance, $langcode, &$items) {
|
|
|
foreach ($items as $delta => $value) {
|
|
|
- _link_process($items[$delta], $delta, $field, $entity);
|
|
|
+ _link_process($items[$delta], $delta, $field, $entity, $instance);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -300,7 +300,7 @@ function link_field_insert($entity_type, $entity, $field, $instance, $langcode,
|
|
|
*/
|
|
|
function link_field_update($entity_type, $entity, $field, $instance, $langcode, &$items) {
|
|
|
foreach ($items as $delta => $value) {
|
|
|
- _link_process($items[$delta], $delta, $field, $entity);
|
|
|
+ _link_process($items[$delta], $delta, $field, $entity, $instance);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -371,8 +371,24 @@ function _link_load($field, $item, $instance) {
|
|
|
|
|
|
/**
|
|
|
* Prepares the item attributes and url for storage.
|
|
|
+ *
|
|
|
+ * @param $item
|
|
|
+ * Link field values.
|
|
|
+ *
|
|
|
+ * @param $delta
|
|
|
+ * The sequence number for current values.
|
|
|
+ *
|
|
|
+ * @param $field
|
|
|
+ * The field structure array.
|
|
|
+ *
|
|
|
+ * @param $entity
|
|
|
+ * Entity object.
|
|
|
+ *
|
|
|
+ * @param $instance
|
|
|
+ * The instance structure for $field on $entity's bundle.
|
|
|
+ *
|
|
|
*/
|
|
|
-function _link_process(&$item, $delta, $field, $entity) {
|
|
|
+function _link_process(&$item, $delta, $field, $entity, $instance) {
|
|
|
// Trim whitespace from URL.
|
|
|
if (!empty($item['url'])) {
|
|
|
$item['url'] = trim($item['url']);
|
|
@@ -391,7 +407,8 @@ function _link_process(&$item, $delta, $field, $entity) {
|
|
|
|
|
|
// Don't save an invalid default value (e.g. 'http://').
|
|
|
if ((isset($field['widget']['default_value'][$delta]['url']) && $item['url'] == $field['widget']['default_value'][$delta]['url']) && is_object($entity)) {
|
|
|
- if (!link_validate_url($item['url'])) {
|
|
|
+ $langcode = !empty($entity) ? field_language($instance['entity_type'], $entity, $instance['field_name']) : LANGUAGE_NONE;
|
|
|
+ if (!link_validate_url($item['url'], $langcode)) {
|
|
|
unset($item['url']);
|
|
|
}
|
|
|
}
|
|
@@ -403,7 +420,7 @@ function _link_process(&$item, $delta, $field, $entity) {
|
|
|
function _link_validate(&$item, $delta, $field, $entity, $instance, $langcode, &$optional_field_found, &$errors) {
|
|
|
if ($item['url'] && !(isset($instance['default_value'][$delta]['url']) && $item['url'] === $instance['default_value'][$delta]['url'] && !$instance['required'])) {
|
|
|
// Validate the link.
|
|
|
- if (link_validate_url(trim($item['url'])) == FALSE) {
|
|
|
+ if (!link_validate_url(trim($item['url']), $langcode)) {
|
|
|
$errors[$field['field_name']][$langcode][$delta][] = array(
|
|
|
'error' => 'link_required',
|
|
|
'message' => t('The value %value provided for %field is not a valid URL.', array(
|
|
@@ -474,19 +491,21 @@ function _link_sanitize(&$item, $delta, &$field, $instance, &$entity) {
|
|
|
$entity_type == 'taxonomy_term' || $entity_type == 'taxonomy_vocabulary' ? str_replace('taxonomy_', '', $entity_type) : $entity_type
|
|
|
);
|
|
|
if (isset($instance['settings']['enable_tokens']) && $instance['settings']['enable_tokens']) {
|
|
|
- global $user;
|
|
|
- // Load the entity if necessary for entities in views.
|
|
|
- if (isset($entity->{$property_id})) {
|
|
|
- $entity_loaded = entity_load($entity_type, array($entity->{$property_id}));
|
|
|
- $entity_loaded = array_pop($entity_loaded);
|
|
|
- }
|
|
|
- else {
|
|
|
- $entity_loaded = $entity;
|
|
|
+ $text_tokens = token_scan($item['url']);
|
|
|
+ if (!empty($text_tokens)) {
|
|
|
+ // Load the entity if necessary for entities in views.
|
|
|
+ if (isset($entity->{$property_id})) {
|
|
|
+ $entity_loaded = entity_load($entity_type, array($entity->{$property_id}));
|
|
|
+ $entity_loaded = array_pop($entity_loaded);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ $entity_loaded = $entity;
|
|
|
+ }
|
|
|
+ $item['url'] = token_replace($item['url'], array($entity_token_type => $entity_loaded));
|
|
|
}
|
|
|
- $item['url'] = token_replace($item['url'], array($entity_token_type => $entity_loaded));
|
|
|
}
|
|
|
|
|
|
- $type = link_validate_url($item['url']);
|
|
|
+ $type = link_url_type($item['url']);
|
|
|
// If the type of the URL cannot be determined and URL validation is disabled,
|
|
|
// then assume LINK_EXTERNAL for later processing.
|
|
|
if ($type == FALSE && $instance['settings']['validate_url'] === 0) {
|
|
@@ -496,12 +515,12 @@ function _link_sanitize(&$item, $delta, &$field, $instance, &$entity) {
|
|
|
$url_parts = _link_parse_url($url);
|
|
|
|
|
|
if (!empty($url_parts['url'])) {
|
|
|
- $item['url'] = $url_parts['url'];
|
|
|
- $item += array(
|
|
|
- 'query' => isset($url_parts['query']) ? $url_parts['query'] : NULL,
|
|
|
+ $item['url'] = url($url_parts['url'],
|
|
|
+ array('query' => isset($url_parts['query']) ? $url_parts['query'] : NULL,
|
|
|
'fragment' => isset($url_parts['fragment']) ? $url_parts['fragment'] : NULL,
|
|
|
'absolute' => !empty($instance['settings']['absolute_url']),
|
|
|
'html' => TRUE,
|
|
|
+ )
|
|
|
);
|
|
|
}
|
|
|
|
|
@@ -541,15 +560,18 @@ function _link_sanitize(&$item, $delta, &$field, $instance, &$entity) {
|
|
|
|
|
|
// Replace title tokens.
|
|
|
if ($title && ($instance['settings']['title'] == 'value' || $instance['settings']['enable_tokens'])) {
|
|
|
- // Load the entity if necessary for entities in views.
|
|
|
- if (isset($entity->{$property_id})) {
|
|
|
- $entity_loaded = entity_load($entity_type, array($entity->{$property_id}));
|
|
|
- $entity_loaded = array_pop($entity_loaded);
|
|
|
- }
|
|
|
- else {
|
|
|
- $entity_loaded = $entity;
|
|
|
+ $text_tokens = token_scan($title);
|
|
|
+ if (!empty($text_tokens)) {
|
|
|
+ // Load the entity if necessary for entities in views.
|
|
|
+ if (isset($entity->{$property_id})) {
|
|
|
+ $entity_loaded = entity_load($entity_type, array($entity->{$property_id}));
|
|
|
+ $entity_loaded = array_pop($entity_loaded);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ $entity_loaded = $entity;
|
|
|
+ }
|
|
|
+ $title = token_replace($title, array($entity_token_type => $entity_loaded));
|
|
|
}
|
|
|
- $title = token_replace($title, array($entity_token_type => $entity_loaded));
|
|
|
$title = filter_xss($title, array('b', 'br', 'code', 'em', 'i', 'img', 'span', 'strong', 'sub', 'sup', 'tt', 'u'));
|
|
|
$item['html'] = TRUE;
|
|
|
}
|
|
@@ -599,22 +621,25 @@ function _link_sanitize(&$item, $delta, &$field, $instance, &$entity) {
|
|
|
|
|
|
// Handle "title" link attribute.
|
|
|
if (!empty($item['attributes']['title']) && module_exists('token')) {
|
|
|
- // Load the entity (necessary for entities in views).
|
|
|
- if (isset($entity->{$property_id})) {
|
|
|
- $entity_loaded = entity_load($entity_type, array($entity->{$property_id}));
|
|
|
- $entity_loaded = array_pop($entity_loaded);
|
|
|
- }
|
|
|
- else {
|
|
|
- $entity_loaded = $entity;
|
|
|
+ $text_tokens = token_scan($item['attributes']['title']);
|
|
|
+ if (!empty($text_tokens)) {
|
|
|
+ // Load the entity (necessary for entities in views).
|
|
|
+ if (isset($entity->{$property_id})) {
|
|
|
+ $entity_loaded = entity_load($entity_type, array($entity->{$property_id}));
|
|
|
+ $entity_loaded = array_pop($entity_loaded);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ $entity_loaded = $entity;
|
|
|
+ }
|
|
|
+ $item['attributes']['title'] = token_replace($item['attributes']['title'], array($entity_token_type => $entity_loaded));
|
|
|
}
|
|
|
- $item['attributes']['title'] = token_replace($item['attributes']['title'], array($entity_token_type => $entity_loaded));
|
|
|
$item['attributes']['title'] = filter_xss($item['attributes']['title'], array('b', 'br', 'code', 'em', 'i', 'img', 'span', 'strong', 'sub', 'sup', 'tt', 'u'));
|
|
|
}
|
|
|
// Handle attribute classes.
|
|
|
if (!empty($item['attributes']['class'])) {
|
|
|
$classes = explode(' ', $item['attributes']['class']);
|
|
|
foreach ($classes as &$class) {
|
|
|
- $class = drupal_html_class($class);
|
|
|
+ $class = drupal_clean_css_identifier($class);
|
|
|
}
|
|
|
$item['attributes']['class'] = implode(' ', $classes);
|
|
|
}
|
|
@@ -660,7 +685,7 @@ function _link_parse_url($url) {
|
|
|
* Replaces the PHP parse_str() function.
|
|
|
*
|
|
|
* Because parse_str replaces the following characters in query parameters name
|
|
|
- * in order to maintain compability with deprecated register_globals directive:
|
|
|
+ * in order to maintain compatibility with deprecated register_globals directive:
|
|
|
*
|
|
|
* - chr(32) ( ) (space)
|
|
|
* - chr(46) (.) (dot)
|
|
@@ -700,6 +725,9 @@ function link_theme() {
|
|
|
'link_formatter_link_plain' => array(
|
|
|
'variables' => array('element' => NULL, 'field' => NULL),
|
|
|
),
|
|
|
+ 'link_formatter_link_host' => array(
|
|
|
+ 'variables' => array('element' => NULL),
|
|
|
+ ),
|
|
|
'link_formatter_link_absolute' => array(
|
|
|
'variables' => array('element' => NULL, 'field' => NULL),
|
|
|
),
|
|
@@ -859,7 +887,7 @@ function link_field_process($element, $form_state, $complete_form) {
|
|
|
);
|
|
|
}
|
|
|
|
|
|
- // If the title field is avaliable or there are field accepts multiple values
|
|
|
+ // If the title field is available or there are field accepts multiple values
|
|
|
// then allow the individual field items display the required asterisk if needed.
|
|
|
if (isset($element['title']) || isset($element['_weight'])) {
|
|
|
// To prevent an extra required indicator, disable the required flag on the
|
|
@@ -885,6 +913,11 @@ function link_field_formatter_info() {
|
|
|
'field types' => array('link_field'),
|
|
|
'multiple values' => FIELD_BEHAVIOR_DEFAULT,
|
|
|
),
|
|
|
+ 'link_host' => array(
|
|
|
+ 'label' => t('Host, as plain text'),
|
|
|
+ 'field types' => array('link_field'),
|
|
|
+ 'multiple values' => FIELD_BEHAVIOR_DEFAULT,
|
|
|
+ ),
|
|
|
'link_url' => array(
|
|
|
'label' => t('URL, as link'),
|
|
|
'field types' => array('link_field'),
|
|
@@ -1015,6 +1048,14 @@ function theme_link_formatter_link_plain($vars) {
|
|
|
return empty($vars['element']['url']) ? check_plain($vars['element']['title']) : url($vars['element']['url'], $link_options);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * Theme function for 'host' text field formatter.
|
|
|
+ */
|
|
|
+function theme_link_formatter_link_host($vars) {
|
|
|
+ $host = @parse_url($vars['element']['url']);
|
|
|
+ return isset($host['host']) ? check_plain($host['host']) : '';
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* Formats a link as an absolute URL.
|
|
|
*/
|
|
@@ -1142,7 +1183,7 @@ function link_views_api() {
|
|
|
|
|
|
/**
|
|
|
* Forms a valid URL if possible from an entered address.
|
|
|
- *
|
|
|
+ *
|
|
|
* Trims whitespace and automatically adds an http:// to addresses without a
|
|
|
* protocol specified
|
|
|
*
|
|
@@ -1153,7 +1194,7 @@ function link_views_api() {
|
|
|
*/
|
|
|
function link_cleanup_url($url, $protocol = 'http') {
|
|
|
$url = trim($url);
|
|
|
- $type = link_validate_url($url);
|
|
|
+ $type = link_url_type($url);
|
|
|
|
|
|
if ($type === LINK_EXTERNAL) {
|
|
|
// Check if there is no protocol specified.
|
|
@@ -1173,18 +1214,59 @@ function link_cleanup_url($url, $protocol = 'http') {
|
|
|
|
|
|
/**
|
|
|
* Validates a URL.
|
|
|
- *
|
|
|
+ *
|
|
|
+ * @param $text
|
|
|
+ * Url to be validated.
|
|
|
+ *
|
|
|
+ * @param $langcode
|
|
|
+ * An optional language code to look up the path in.
|
|
|
+ *
|
|
|
+ * @return boolean
|
|
|
+ * True if a valid link, FALSE otherwise.
|
|
|
+ */
|
|
|
+function link_validate_url($text, $langcode = NULL) {
|
|
|
+ $text = link_cleanup_url($text);
|
|
|
+ $type = link_url_type($text);
|
|
|
+
|
|
|
+ if ($type && ($type == LINK_INTERNAL || $type == LINK_EXTERNAL)) {
|
|
|
+ $flag = valid_url($text, TRUE);
|
|
|
+ if (!$flag) {
|
|
|
+ $normal_path = drupal_get_normal_path($text, $langcode);
|
|
|
+ $parsed_link = parse_url($normal_path, PHP_URL_PATH);
|
|
|
+ if ($normal_path != $parsed_link) {
|
|
|
+ $normal_path = $parsed_link;
|
|
|
+ }
|
|
|
+ $flag = drupal_valid_path($normal_path);
|
|
|
+ }
|
|
|
+ if (!$flag) {
|
|
|
+ $flag = file_exists($normal_path);
|
|
|
+ }
|
|
|
+ if (!$flag) {
|
|
|
+ $uri = file_build_uri($normal_path);
|
|
|
+ $flag = file_exists($uri);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ $flag = (bool) $type;
|
|
|
+ }
|
|
|
+
|
|
|
+ return $flag;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Type check a URL.
|
|
|
+ *
|
|
|
* Accepts all URLs following RFC 1738 standard for URL formation and all e-mail
|
|
|
* addresses following the RFC 2368 standard for mailto address formation.
|
|
|
*
|
|
|
* @param string $text
|
|
|
- * Url to be validated.
|
|
|
+ * Url to be checked.
|
|
|
*
|
|
|
* @return mixed
|
|
|
* Returns boolean FALSE if the URL is not valid. On success, returns one of
|
|
|
* the LINK_(linktype) constants.
|
|
|
*/
|
|
|
-function link_validate_url($text) {
|
|
|
+function link_url_type($text) {
|
|
|
// @TODO Complete letters.
|
|
|
$LINK_ICHARS_DOMAIN = (string) html_entity_decode(implode("", array(
|
|
|
"æ", // æ
|