Commit b85607b2 authored by Nathan Haug's avatar Nathan Haug
Browse files

Signficantly enhancing views support. Now supports argument handling and...

Signficantly enhancing views support. Now supports argument handling and filtering by link title, url, targets and protocols. Issue #134674.
parent 2c084a68
......@@ -10,6 +10,7 @@ define('LINK_EXTERNAL', 'external');
define('LINK_INTERNAL', 'internal');
define('LINK_FRONT', 'front');
define('LINK_EMAIL', 'email');
define('LINK_DOMAINS', 'aero|arpa|biz|com|cat|coop|edu|gov|info|int|jobs|mil|museum|name|nato|net|org|pro|travel|mobi');
/**
* Implementation of hook_help().
......@@ -38,7 +39,7 @@ function link_field_settings($op, $field) {
case 'form':
$form = array();
$title_options = array (
$title_options = array(
'optional' => t('Optional Title'),
'required' => t('Required Title'),
'none' => t('No Title'),
......@@ -108,8 +109,37 @@ function link_field_settings($op, $field) {
case 'filters':
return array(
'default' => array(
'name' => t('URL'),
'operator' => 'views_handler_operator_like',
'handler' => 'views_handler_filter_like',
'handler' => 'views_handler_operator_like',
),
'title' => array(
'name' => t('Title'),
'operator' => 'views_handler_operator_like',
'handler' => 'views_handler_operator_like',
),
'protocol' => array(
'name' => t('Protocol'),
'list' => drupal_map_assoc(variable_get('filter_allowed_protocols', array('http', 'https', 'ftp', 'news', 'nntp', 'telnet', 'mailto', 'irc', 'ssh', 'sftp', 'webcal'))),
'operator' => 'views_handler_operator_or',
'handler' => 'link_views_protocol_filter_handler',
),
);
case 'arguments':
return array(
'content: '. $field['field_name'] .'_url' => array(
'name' => t('Link URL') .': '. $field['widget']['label'] .' ('. $field['field_name'] .')',
'handler' => 'link_views_argument_handler',
),
'content: '. $field['field_name'] .'_title' => array(
'name' => t('Link Title') .': '. $field['widget']['label'] .' ('. $field['field_name'] .')',
'handler' => 'link_views_argument_handler',
),
'content: '. $field['field_name'] .'_target' => array(
'name' => t('Link Target') .': '. $field['widget']['label'] .' ('. $field['field_name'] .')',
'handler' => 'link_views_argument_handler',
),
);
......@@ -492,11 +522,115 @@ function link_field_formatter($field, $item, $formatter, $node) {
if ($field['display']['url_cutoff'] && strlen($display_url) > $field['display']['url_cutoff']) {
$display_url = substr($display_url, 0, $field['display']['url_cutoff']) . "...";
}
$output = l($display_url, $url, $attributes, $query, $fragment, array('class' => $field['attributes']['class']));
$output = l($display_url, $url, $attributes, $query, $fragment);
}
return $output;
}
/**
* Views module argument handler for link fields
*/
function link_views_argument_handler($op, &$query, $argtype, $arg = '') {
if ($op == 'filter') {
$field_name = substr($argtype['type'], 9, strrpos($argtype['type'], '_') - 9);
$column = substr($argtype['type'], strrpos($argtype['type'], '_') + 1);
}
else {
$field_name = substr($argtype, 9, strrpos($argtype, '_') - 9);
$column = substr($argtype, strrpos($argtype, '_') + 1);
}
// Right now the only attribute we support in views in 'target', but
// other attributes of the href tag could be added later
if ($column == 'target') {
$attribute = $column;
$column = 'attributes';
}
$field = content_fields($field_name);
$db_info = content_database_info($field);
$main_column = $db_info['columns'][$column];
// The table name used here is the Views alias for the table, not the actual
// table name.
$table = 'node_data_'. $field['field_name'];
switch ($op) {
case 'summary':
$query->ensure_table($table);
$query->add_field($main_column['column'], $table);
return array('field' => $table .'.'. $main_column['column']);
break;
case 'filter':
$query->ensure_table($table);
if ($column == 'attributes') {
// Because attributes are stored serialized, our only option is to also
// serialize the data we're searching for and use LIKE to find similar data
$query->add_where($table .'.'. $main_column['column'] ." LIKE '%%%s%'", serialize($attribute) . serialize($arg));
}
else {
$query->add_where($table .'.'. $main_column['column'] ." = '%s'", $arg);
}
break;
case 'link':
$item = array();
foreach ($db_info['columns'] as $column => $attributes) {
$view_column_name = $attributes['column'];
$item[$column] = $query->$view_column_name;
}
return l(content_format($field, $item, 'plain'), $arg .'/'. $query->$main_column['column'], array(), NULL, NULL, FALSE, TRUE);
case 'sort':
break;
case 'title':
$item = array(key($db_info['columns']) => $query);
return content_format($field, $item);
break;
}
}
/**
* Views modules filter handler for link protocol filtering
*/
function link_views_protocol_filter_handler($op, $filter, $filterinfo, &$query) {
global $db_type;
$protocols = $filter['value'];
$field = $filterinfo['field'];
// $table is not the real table name but the views alias
$table = 'node_data_'. $filterinfo['content_field']['field_name'];
foreach ($protocols as $protocol) {
// Simple case, the URL begins with the specified protocol
$condition = $table .'.'. $field .' LIKE \''. $protocol .'%\'';
// More complex case, no protocol specified but is automatically cleaned up
// by link_cleanup_url(). RegEx is required for this search operation.
if ($protocol == 'http') {
if ($db_type == 'pgsql') {
// PostGreSQL code has NOT been tested. Please report any problems to the link issue queue.
// pgSQL requires all slashes to be double escaped in regular expressions.
// See http://www.postgresql.org/docs/8.1/static/functions-matching.html#FUNCTIONS-POSIX-REGEXP
$condition .= ' OR '. $table .'.'. $field .' ~* \''. '^(([a-z0-9]([a-z0-9\\-_]*\\.)+)('. LINK_DOMAINS .'|[a-z][a-z]))' .'\'';
}
else {
// mySQL requires backslashes to be double (triple?) escaped within character classes.
// See http://dev.mysql.com/doc/refman/5.0/en/string-comparison-functions.html#operator_regexp
$condition .= ' OR '. $table .'.'. $field .' REGEXP \''. '^(([a-z0-9]([a-z0-9\\\-_]*\.)+)('. LINK_DOMAINS .'|[a-z][a-z]))' .'\'';
}
}
$where_conditions[] = $condition;
}
$query->ensure_table($table);
$query->add_where(implode(' '. $filter['operator'] .' ', $where_conditions));
}
/**
* Forms a valid URL if possible from an entered address.
* Trims whitespace and automatically adds an http:// to addresses without a protocol specified
......@@ -512,7 +646,7 @@ function link_cleanup_url($url, $protocol = "http") {
$protocol_match = preg_match("/^([a-z0-9][a-z0-9\.\-_]*:\/\/)/i",$url);
if (empty($protocol_match)) {
// But should there be? Add an automatic http:// if it starts with a domain name
$domain_match = preg_match('/^(([a-z0-9]([a-z0-9\-_]*\.)+)(aero|arpa|biz|com|cat|coop|edu|gov|info|int|jobs|mil|museum|name|nato|net|org|pro|travel|mobi|[a-z]{2}))/i',$url);
$domain_match = preg_match('/^(([a-z0-9]([a-z0-9\-_]*\.)+)('. LINK_DOMAINS .'|[a-z]{2}))/i',$url);
if (!empty($domain_match)) {
$url = $protocol."://".$url;
}
......@@ -536,7 +670,7 @@ function link_validate_url($text) {
$allowed_protocols = variable_get('filter_allowed_protocols', array('http', 'https', 'ftp', 'news', 'nntp', 'telnet', 'mailto', 'irc', 'ssh', 'sftp', 'webcal'));
$protocol = '((' . implode("|", $allowed_protocols) . '):\/\/)';
$domain = '(([a-z0-9]([a-z0-9\-_]*\.)+)(aero|arpa|biz|com|cat|coop|edu|gov|info|int|jobs|mil|museum|name|nato|net|org|pro|travel|mobi|[a-z]{2}))';
$domain = '(([a-z0-9]([a-z0-9\-_]*\.)+)('. LINK_DOMAINS .'|[a-z]{2}))';
$ipv4 = '([0-9]{1,3}(\.[0-9]{1,3}){3})';
$ipv6 = '([0-9a-fA-F]{1,4}(\:[0-9a-fA-F]{1,4}){7})';
$port = '(:([0-9]{1,4}))';
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment