? views-generic-link-new.patch
? views-generic-link.patch
? views-generic-link_0.patch
Index: handlers/views_handler_field_link.inc
===================================================================
RCS file: handlers/views_handler_field_link.inc
diff -N handlers/views_handler_field_link.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ handlers/views_handler_field_link.inc	17 Jan 2009 20:27:46 -0000
@@ -0,0 +1,150 @@
+<?php
+// $Id$
+
+/**
+ * A handler to provide a customizable link field.
+ *
+ * @ingroup views_field_handlers
+ */
+
+class views_handler_field_link extends views_handler_field {
+  static protected $search;
+  function option_definition() {
+    $options = parent::option_definition();
+
+    $options['link_text'] = array('default' => '');
+    $options['link_path'] = array('default' => '');
+    $options['link_prefix'] = array('default' => '');
+    $options['link_suffix'] = array('default' => '');
+
+    return $options;
+  }
+
+  /**
+   * Set the options for this link. Note that if Path is left empty, this is a custom text field.
+   */
+  function options_form(&$form, &$form_state) {
+    parent::options_form($form, $form_state);
+    $form['link_text'] = array(
+      '#title' => t('Link text'),
+      '#type' => 'textfield',
+      '#default_value' => $this->options['link_text'],
+      '#description' => t('The text to display for this link. You may include HTML. You may also enter the view arguments, in the format <em>%1</em>, or database field names, in the format <em>[field_name]</em>. For a list of valid tokens, see the <em>Replacement patterns</em> listed below.'),
+    );
+    $form['link_prefix'] = array(
+      '#title' => t('Prefix text'),
+      '#type' => 'textfield',
+      '#default_value' => $this->options['link_prefix'],
+      '#description' => t('Any text to display before this link. You may include HTML.'),
+    );
+    $form['link_suffix'] = array(
+      '#title' => t('Suffix text'),
+      '#type' => 'textfield',
+      '#default_value' => $this->options['link_suffix'],
+      '#description' => t('Any text to display after this link. You may include HTML.'),
+    );
+    $form['link_path'] = array(
+      '#title' => t('Link path'),
+      '#type' => 'textfield',
+      '#default_value' => $this->options['link_path'],
+      '#description' => t('The Drupal path or absolute URL for this link. You may enter the view arguments, in the format <em>%1</em>, or database field names, in the format <em>[field_name]</em>. For a list of valid tokens, see the <em>Replacement patterns</em> listed below.'),
+    );
+    // Get a list of the available fields and arguments for token replacement.
+    $options = array();
+    foreach ($this->view->display_handler->get_handlers('field') as $field => $handler) {
+      // We cannot reference our own field.
+      if ($field != 'link_field') {
+        $options['fields']["[$field]"] = $handler->ui_name();
+      }
+    }
+    $count = 0; // This lets us prepare the key as we want it printed.
+    foreach ($this->view->display_handler->get_handlers('argument') as $arg => $handler) {
+      $options['arguments']['%'. ++$count] = $handler->ui_name();
+    }
+    // Default text.
+    $output = t('<p>You must add some additional fields to this display before using this field. These fields may be marked as <em>Exclude from display</em> if you prefer.</p>');
+    // We have some options, so make a list.
+    if (!empty($options)) {
+      $output = t('<p>The following substitution patterns are available for this display. Use the pattern shown on the left to display the value indicated on the right.</p>');
+      foreach (array('fields', 'arguments') as $type) {
+        if (!empty($options[$type])) {
+          $items = array();
+          $title = t(ucwords($type));
+          foreach ($options[$type] as $key => $value) {
+            $items[] = $key .' == '. $value;
+          }
+          $output .= theme('item_list', $items, $title);
+        }
+      }
+    }
+    $form['link_help'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Replacement patterns'),
+      '#collapsible' => TRUE,
+      '#collapsed' => TRUE,
+    );
+    $form['link_help']['text'] = array(
+      '#value' => $output,
+    );
+  }
+
+  function query() {
+    // We don't do anything here. But doing so avoids errors in trying to load a non-existent field.
+  }
+
+  /**
+   * Take the tokens and arguments and run the proper substitutions.
+   */
+  function render($value) {
+    $link_text = $this->options['link_text'];
+    $link_path = $this->options['link_path'];
+    $prefix = $this->options['link_prefix'];
+    $suffix = $this->options['link_suffix'];
+    // If we have arguments, then substitute them.
+    if (!empty($this->view->build_info['substitutions'])) {
+      foreach ($this->view->build_info['substitutions'] as $key => $arg) {
+        $link_text = str_replace($key, $arg, $link_text);
+        $link_path = str_replace($key, $arg, $link_path);
+      }
+    }
+    // Otherwise, we remove the argument handlers.
+    else {
+      for ($i = 0; $i <= 10; $i++) {
+        $subs[] = "%$i";
+      }
+      // A regex might be better here. And what about empty arguments?
+      $link_text = str_replace($subs, '', $link_text);
+      $link_path = str_replace($subs, '', $link_path);
+    }
+    $search = self::_get_search_array($this->view->query->fields);
+    // Now replace the tokens.
+    foreach ($value as $key => $val) {
+      $link_text = str_replace(self::$search[$key], $val, $link_text);
+      $link_path = str_replace(self::$search[$key], $val, $link_path);
+    }
+    $output = filter_xss_admin($prefix);
+    if (!empty($link_path)) {
+      $output .= l(filter_xss_admin($link_text), $link_path, array('html' => TRUE));
+    }
+    else {
+      $output .= filter_xss_admin($link_text);
+    }
+    $output .= filter_xss_admin($suffix);
+    return $output;
+  }
+  
+  /**
+   * Private function to calculate the search array.
+   */
+   protected function _get_search_array($fields) {
+     if (isset(self::$search)) {
+       return self::$search;
+     }
+     // Prepare the field tokens by finding the proper aliases used in this query.
+     self::$search = array();
+     foreach ($fields as $key => $token) {
+       self::$search[$key] = '['. $token['field'] .']';
+     }
+     return self::$search;
+   }
+}
Index: includes/handlers.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/views/includes/handlers.inc,v
retrieving revision 1.104
diff -u -p -r1.104 handlers.inc
--- includes/handlers.inc	7 Jan 2009 23:31:12 -0000	1.104
+++ includes/handlers.inc	17 Jan 2009 20:27:48 -0000
@@ -1062,6 +1062,12 @@ function views_views_handlers() {
       'views_handler_field_numeric' => array(
         'parent' => 'views_handler_field',
       ),
+      'views_handler_field_link' => array(
+        'parent' => 'views_handler_field',
+      ),
+      'views_handler_field_link' => array(
+        'parent' => 'views_handler_field',
+      ),
 
       // filter handlers
       'views_handler_filter' => array(
Index: includes/view.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/views/includes/view.inc,v
retrieving revision 1.146
diff -u -p -r1.146 view.inc
--- includes/view.inc	8 Jan 2009 00:29:54 -0000	1.146
+++ includes/view.inc	17 Jan 2009 20:27:50 -0000
@@ -504,6 +504,9 @@ class view extends views_db_object {
       $this->build_info['title'] = str_replace(array_keys($substitutions), $substitutions, $title);
     }
 
+    // Store the arguments for later use.
+    $this->build_info['substitutions'] = $substitutions;
+
     return $status;
   }
 
Index: modules/views.views.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/views/modules/views.views.inc,v
retrieving revision 1.5
diff -u -p -r1.5 views.views.inc
--- modules/views.views.inc	3 Sep 2008 19:21:29 -0000	1.5
+++ modules/views.views.inc	17 Jan 2009 20:27:50 -0000
@@ -34,6 +34,22 @@ function views_views_data() {
       'handler' => 'views_handler_argument_null',
     ),
   );
+
+  $data['views']['link_field'] = array(
+    'title' => t('Custom link field'),
+    'help' => t('Create a custom links field.'),
+    'field' => array(
+      'handler' => 'views_handler_field_link',
+    ),
+  );
+
+  $data['views']['link_field'] = array(
+    'title' => t('Custom link field'),
+    'help' => t('Create a custom links field.'),
+    'field' => array(
+      'handler' => 'views_handler_field_link',
+    ),
+  );
   return $data;
 }
 
