You are here

views_plugin_style_rss_fields.inc in Views RSS 6

Same filename and directory in other branches
  1. 7 views/views_plugin_style_rss_fields.inc

File

views/views_plugin_style_rss_fields.inc
View source
<?php

/**
 * Extend the view_plugin_style class to provide an RSS view style.
 */
class views_plugin_style_rss_fields extends views_plugin_style {

  /**
   * Attach this view to another display as a feed.
   *
   * Provide basic functionality for all export style views like attaching a
   * feed image link.
   */
  function attach_to($display_id, $path, $title) {
    $display = $this->view->display[$display_id]->handler;
    $url_options = array();
    $input = $this->view
      ->get_exposed_input();
    if ($input) {
      $url_options['query'] = $input;
    }
    $url = url($this->view
      ->get_url(NULL, $path), $url_options);
    if ($display
      ->has_path() && !$this->options['feed_settings']['feed_in_links']) {
      if (empty($this->preview)) {
        drupal_add_feed($url, $title);
      }
    }
    else {
      if (empty($this->view->feed_icon)) {
        $this->view->feed_icon = '';
      }
      $this->view->feed_icon .= theme('feed_icon', $url, $title);
      drupal_add_link(array(
        'rel' => 'alternate',
        'type' => 'application/rss+xml',
        'title' => $title,
        'href' => $url,
      ));
    }
  }
  function option_definition() {
    $options = parent::option_definition();
    $options['description'] = array(
      'contains' => array(
        'feed_description' => array(
          'default' => '',
        ),
      ),
    );
    $field_options = array();
    foreach ($this
      ->xml_fields() as $k => $option) {
      $field_options[$k] = array(
        'default' => '',
      );
    }
    $options['fields'] = array(
      'contains' => $field_options,
    );
    $options['georss'] = array(
      'contains' => array(
        'lat' => array(
          'default' => '',
        ),
        'lon' => array(
          'default' => '',
        ),
        'featureName' => array(
          'default' => '',
        ),
      ),
    );
    return $options;
  }

  /**
   * Provide a form for setting options.
   *
   * @param array $form
   * @param array $form_state
   */
  function options_form(&$form, &$form_state) {
    parent::options_form($form, $form_state);
    $handlers = $this->display->handler
      ->get_handlers('field');
    if (empty($handlers)) {
      $form['error_markup'] = array(
        '#value' => t('You need at least one field before you can configure your field settings'),
        '#prefix' => '<div class="error form-item description">',
        '#suffix' => '</div>',
      );
    }
    else {

      // Feed Description
      $form['feed_settings'] = array(
        '#type' => 'fieldset',
        '#title' => t('Feed settings'),
        '#collapsible' => TRUE,
        '#collapsed' => TRUE,
        '#weight' => -5,
      );

      // Legacy setting: previously Feed Description fieldset name was different.
      // Should probably rather go to hook_update_N()...
      if (isset($this->options['description']['feed_description']) && $this->options['description']['feed_description']) {
        $this->options['feed_settings']['feed_description'] = $this->options['description']['feed_description'];
      }
      $form['feed_settings']['feed_description'] = array(
        '#title' => t('Feed description'),
        '#type' => 'textarea',
        '#default_value' => isset($this->options['feed_settings']['feed_description']) ? $this->options['feed_settings']['feed_description'] : '',
        '#description' => t('Description for this feed. If left blank, the default site mission will be used.'),
      );

      // Namespaces
      $form['feed_settings']['namespaces'] = array(
        '#type' => 'fieldset',
        '#title' => t('XML namespace definitions'),
        '#collapsible' => TRUE,
        '#collapsed' => TRUE,
      );

      // Loop through all available fields (both predefined by this module
      // as well as those coming from hook_views_rss_item_fields_alter()
      // implementations by other modules) and check if there are any other
      // namespaces that should be added to configuration form.
      $predefined_namespaces = $this
        ->xml_namespaces();
      foreach (array_keys($this
        ->xml_fields()) as $field_name) {
        if (strstr($field_name, ':')) {
          list($namespace, $field) = explode(':', $field_name);

          // Namespaces predefined by this module should be excluded.
          if (!in_array($namespace, array_keys($predefined_namespaces))) {
            $form['feed_settings']['namespaces'][$namespace] = array(
              '#title' => t('URI reference for "%namespace" namespace', array(
                '%namespace' => $namespace,
              )),
              '#type' => 'textfield',
              '#default_value' => isset($this->options['feed_settings']['namespaces'][$namespace]) ? $this->options['feed_settings']['namespaces'][$namespace] : NULL,
              '#description' => t("Example: <em>http://base.google.com/ns/1.0</em>"),
            );
          }
        }
      }
      $form['feed_settings']['feed_in_links'] = array(
        '#type' => 'checkbox',
        '#default_value' => !empty($this->options['feed_settings']['feed_in_links']),
        '#title' => t('Display feed icon in the links attached to the view.'),
        '#weight' => 10,
      );

      // Field Chooser
      $field_names = array(
        '' => '--',
      );
      foreach ($handlers as $field => $handler) {
        if ($label = $handler
          ->label()) {
          $field_names[$field] = $label;
        }
        else {
          $field_names[$field] = $handler
            ->ui_name();
        }
      }
      $form['fields'] = array(
        '#type' => 'fieldset',
        '#title' => 'Field settings',
        '#description' => t('Select the fields that relevant data for each element of the feed. See <a href="@guide_url">Views RSS configuration guide</a> for more information.', array(
          '@guide_url' => url('http://drupal.org/node/1344136'),
        )),
        '#collapsible' => TRUE,
        '#collapsed' => TRUE,
        '#weight' => 0,
      );
      foreach ($this
        ->xml_fields() as $k => $option) {
        $form['fields'][$k] = array(
          '#type' => 'select',
          '#title' => $option['title'],
          '#description' => isset($option['description']) ? $option['description'] : '',
          '#options' => $field_names,
          '#default_value' => $this->options['fields'][$k],
        );
      }

      // GeoRSS
      $form['georss'] = array(
        '#type' => 'fieldset',
        '#title' => t('GeoRSS field settings'),
        '#description' => t('Select fields that provide the latitude and longitude values for feed items.'),
        '#collapsible' => TRUE,
        '#collapsed' => TRUE,
        '#weight' => 5,
      );
      $form['georss']['lat'] = array(
        '#type' => 'select',
        '#title' => t('Latitude'),
        '#options' => $field_names,
        '#default_value' => $this->options['georss']['lat'],
      );
      $form['georss']['lon'] = array(
        '#type' => 'select',
        '#title' => t('Longitude'),
        '#options' => $field_names,
        '#default_value' => $this->options['georss']['lon'],
      );
      $form['georss']['featureName'] = array(
        '#type' => 'select',
        '#title' => t('Feature Name'),
        '#options' => $field_names,
        '#default_value' => $this->options['georss']['featureName'],
      );
    }
  }

  /**
   * Map views row result to an RSS item.
   */
  function map_rows($rows) {

    // Fields must be rendered in order as of Views 2.3, so we will pre-render everything.
    $renders = array();
    $keys = array_keys($this->view->field);
    foreach ($rows as $count => $row) {
      foreach ($keys as $id) {
        $renders[$count][$id] = $this->view->field[$id]
          ->theme($row);
      }
    }
    $items = $this
      ->process_fields($renders);
    return $items;
  }
  function process_fields($rows) {
    $items = array();
    foreach ($rows as $id => $row) {
      $item = array();
      foreach (array_merge($this->options['fields'], $this->options['georss']) as $key => $val) {
        if (!isset($this->view->field[$val])) {
          continue;
        }
        switch ($key) {
          case 'description':
            $item[$key] = check_plain(htmlspecialchars_decode($row[$val], ENT_QUOTES));
            break;
          case 'category':
            $item[$key] = array_map('trim', explode(',', strip_tags($row[$val])));
            break;
          case 'lat':
          case 'lon':
            if (isset($row['lat']) && is_numeric($row['lat']) && isset($row['lon']) && is_numeric($row['lon'])) {
              $item['georss:point'] = $row['lat'] . ' ' . $row['lon'];
            }
            break;
          case 'featureName':
            $item['georss:' . $key] = $row[$val];
            break;
          default:
            $item[$key] = $row[$val];
        }
      }
      $item['source'] = theme('views_rss_feed_item_source', $this->view);
      $items[] = $item;
    }
    return $items;
  }

  /**
   * An array of available XML fields to map to.
   */
  function xml_fields() {
    $fields = array(
      'title' => array(
        'title' => t('Title'),
        'description' => t('RSS 2.0 title element.'),
      ),
      'link' => array(
        'title' => t('Link'),
        'description' => t('RSS 2.0 link element.'),
      ),
      'description' => array(
        'title' => t('Description'),
        'description' => t('RSS 2.0 description element.'),
      ),
      'author' => array(
        'title' => t('Author e-mail'),
        'description' => t('RSS 2.0 author element.'),
      ),
      'dc:creator' => array(
        'title' => t('Author name'),
        'description' => t('Dublin core creator element.'),
      ),
      'category' => array(
        'title' => t('Category'),
        'description' => t('RSS 2.0 category element.'),
      ),
      'comments' => array(
        'title' => t('Comments'),
        'description' => t('RSS 2.0 comments element.'),
      ),
      'enclosure' => array(
        'title' => t('Enclosure'),
        'description' => t('RSS 2.0 enclosure element.'),
      ),
      'guid' => array(
        'title' => t('guid'),
        'description' => t('RSS 2.0 guid element.'),
      ),
      'pubDate' => array(
        'title' => t('pubDate'),
        'description' => t('RSS 2.0 pubDate element.'),
      ),
    );
    drupal_alter('views_rss_item_elements', $fields);
    return $fields;
  }

  /**
   * Return an array of all known XML namespaces.
   */
  function xml_namespaces() {
    return array(
      'dc' => 'http://purl.org/dc/elements/1.1/',
      'georss' => 'http://www.georss.org/georss',
    );
  }

  /**
   * Convenience method: return an XML Namespace for a given element.
   *
   * @param $elem
   *   An XML element like 'title' or 'dc:creator'
   *
   * @return
   *   An array where with a local and a global namespace identifier. Returns
   *   FALSE if no corresponding namespace could be found.
   */
  function xml_namespace($elem) {
    $e = explode(':', $elem);
    if (is_array($e)) {
      $local = array_shift($e);
      $namespaces = $this
        ->xml_namespaces($local);
      if (isset($namespaces[$local])) {
        return array(
          'local' => $local,
          'namespace' => $namespaces[$local],
        );
      }
    }
    return FALSE;
  }

}

Classes

Namesort descending Description
views_plugin_style_rss_fields Extend the view_plugin_style class to provide an RSS view style.