comm-press: Your Drupal agency in Hamburg, Germany: Consulting, training, programming, service, webdesign and hosting

Knowledge . Eigene Plugins für Views schreiben

von Karsten Frohwein
am

Views verfügt über eine API, die es ermöglicht Plugins in Views einzubinden. Plugins sind sehr vielfältig und erst einmal schwer zu erfassen.

Die verschiedenen Möglichkeiten kann man views_discover_plugins() entnehmen.

Es gibt Plugins für:

  • Access / Zugriffsrechte
  • Argument default / Standardwerte für Argumente
  • Argument validator / Argumente überprüfen
  • Cache
  • Display / Anzeige-Art, wie Seite oder Block
  • Style / Darstellung des Views, z.B. als Liste, Tabelle oder RSS.

Man sieht schnell, dass es sehr unterschiedlich ist und sich im Einzelnen um sehr mächtige Bereiche handelt. Das Gute ist, dass – wenn man einmal begriffen hat, wie man einen Plug schreibt – Views sich recht einfach um wirklich komplexe Dinge erweitern lässt. So wird es ein Leichtes, eine eigene Ausgabe zu definieren, wo doch so viele auf das HTML von Views schimpfen. Oder man kann seine eigene Rechteschicht so aufbauen wie man möchte.

Plugins sollte man nicht mit Handlern verwechseln. Die Handler sind für die Datenanbindung zuständig und bauen die SQL-Abfrage zusammen. Plugins beschäftigen sich nur indirekt mit den Daten.

In unserem Fall musste ich eine spezielle Behandlung von zwei Argumenten erreichen, die ich nicht mit Panels oder Views erreichen konnte. Es sollten zwei Argumente aus der URL ausgewertet werden, um auf einen Node zu schließen und auf eine Term-ID aus diesen.

Um zu lernen, wie man ein Plugin schreibt, bietet Views selbst die besten Beispiele. Alles beginnt mit dem Aufruf von hook_views_api().

<?php
function hook_views_api() {
  return array(
    'api' => 2,
    'path' => drupal_get_path('module', 'example') . '/includes/views',
  );
}
?>

Damit macht man sein Modul mit Views bekannt und kann weitere Hooks verwenden. 'path' ist optional und dient der besseren Ordnung.

Danach kann man mit hook_views_plugins() weitermachen. Am besten schaut man sich den Hook in /includes/plugins.inc an. In meinem Fall ging es um Standard-Argumente.

<?php
function views_views_plugins() {
  $plugins = array(
    'argument default' => array(
      // This type of plugin does not conform to the standard and
      // uses 'fixed' as the parent rather than having a separate parent.
      'fixed' => array(
        'title' => t('Fixed entry'),
        'handler' => 'views_plugin_argument_default',
      ),
      'php' => array(
        'title' => t('PHP Code'),
        'handler' => 'views_plugin_argument_default_php',
        'parent' => 'fixed',
      ),
    ),
  );
}
?>

Man muss einfach den Teil des Arrays heraussuchen, den man verwenden will, und ihn entsprechend seinem Plugin-Namen abwandeln.

Ich denke, dass nur title und handler vonnöten sind. Das grundsätzliche Handling dieses Arrays sieht man in views_discover_plugins(). Der Handler ist der Name der Datei und der Klasse unseres Plugins. Dies kann man sich unter /plugins/views_plugin_argument_default.inc anschauen. Dort sind alle Dateien mit den Klassendefinitionen für die Plugins.

<?php
// $Id: views_plugin_argument_default.inc,v 1.2 2009/06/01 23:34:55 merlinofchaos Exp $
/**
 * @file
 * Contains the fixed argument default plugin.
 */

/**
 * @defgroup views_argument_default_plugins Views' argument default plugins
 * @{
 *
 * Allow specialized methods of filling in arguments when they aren't
 * provided.
 *
 * @see hook_views_plugins
 */

/**
 * The fixed argument default handler; also used as the base.
 */
class views_plugin_argument_default extends views_plugin {
  var $option_name = 'default_argument_fixed';
  /**
   * Initialize this plugin with the view and the argument
   * it is linked to.
   */
  function init(&$view, &$argument, $id = NULL) {
    $this->view = &$view;
    $this->argument = &$argument;
    $this->id = $id;
  }

  /**
   * Determine if the administrator has the privileges to use this
   * plugin
   */
  function access() { return TRUE; }

  function argument_form(&$form, &$form_state) {
    $form[$this->option_name] = array(
      '#type' => 'textfield',
      '#title' => t('Default argument'),
      '#default_value' => $this->get_argument(),
      '#process' => array('views_process_dependency'),
      '#dependency' => array(
        'radio:options[default_action]' => array('default'),
        'radio:options[default_argument_type]' => array($this->id)
      ),
      '#dependency_count' => 2,
    );

    // Only do this if using one simple standard form gadget
    $this->check_access($form);
  }

  /**
   * If we don't have access to the form but are showing it anyway, ensure that
   * the form is safe and cannot be changed from user input.
   */
  function check_access(&$form) {
    if (!$this->access()) {
      $form[$this->option_name]['#disabled'] = TRUE;
      $form[$this->option_name]['#value'] = $form[$this->option_name]['#default_value'];
      $form[$this->option_name]['#description'] .= ' ~markup10~';
    }
  }

  /**
   * Return the default argument.
   */
  function get_argument() {
    return isset($this->argument->options[$this->option_name]) ? $this->argument->options[$this->option_name] : '';
  }
}

/**
 * @}
 */
?>

Grundsätzlich ist unser Plugin eine Ableitung der Klasse views_plugin, die man im plugins.inc ab Zeile 349 findet. Diese baut auf dem views_object auf, das in base.inc ab Zeile 12 definiert ist.

Man kann als Dateinamen und als Namen der Klasse verwenden, was man möchte. Die Datei wird automatisch geladen und instanziiert. Verändere ich innerhalb dieser Klasse also die Methode get_argument(), kann ich schnell einen eigenen Wert zurückgeben.

Wenn man sich diese Dinge anschaut, wird man sicher eine Lösung finden, sein eigenes Plugin für Views zu schreiben.

Besten Dank an dereine für die Hilfe!