Code refactoring, added support for <category> and <enclosure> elements
authorMaciej Zgadzaj
Thu, 17 Nov 2011 00:37:10 +0000 (01:37 +0100)
committerMaciej Zgadzaj
Thu, 17 Nov 2011 00:37:10 +0000 (01:37 +0100)
views/views-rss-fields-item.tpl.php
views/views-view-views-rss-fields.tpl.php
views/views_plugin_style_rss_fields.inc
views/views_rss_views_fields.theme.inc
views_rss.module

index 47ca842..8c6ccae 100644 (file)
@@ -1,4 +1,3 @@
-<?php // $Id$ ?>
 <item>
   <?php print $row ?>
 </item>
index fb9ee1e..1fb854b 100644 (file)
@@ -1,4 +1,3 @@
-<?php // $Id$ ?>
 <?php print "<?xml"; ?> version="1.0" encoding="utf-8" <?php print "?>"; ?>
 
 <rss version="2.0" <?php print $namespaces ?>>
index 878901b..f857d94 100644 (file)
@@ -38,8 +38,8 @@ class views_plugin_style_rss_fields extends views_plugin_style {
       ));
     }
   }
-  
-  
+
+
   function option_definition() {
     $options = parent::option_definition();
 
@@ -48,16 +48,16 @@ class views_plugin_style_rss_fields extends views_plugin_style {
         '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' => ''),
@@ -65,7 +65,7 @@ class views_plugin_style_rss_fields extends views_plugin_style {
         'featureName' => array('default' => ''),
       ),
     );
-    
+
     return $options;
   }
 
@@ -114,7 +114,9 @@ class views_plugin_style_rss_fields extends views_plugin_style {
       $form['fields'] = array(
         '#type' => 'fieldset',
         '#title' => 'Field usage',
-        '#description' => t('Select the fields that relevant data for each element of the feed'),
+        '#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,
@@ -165,19 +167,41 @@ class views_plugin_style_rss_fields extends views_plugin_style {
     // 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 ($renders as $id => $row) {
+    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;
-        $item[$key] = $row[$val];
+        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];
+        }
       }
       $items[] = $item;
     }
@@ -191,16 +215,16 @@ class views_plugin_style_rss_fields extends views_plugin_style {
     return array(
       'title' => array(
         'title' => t('Title'),
-        'description' => t('RSS 2.0 title element'),
-      ),
-      'description' => array(
-        'title' => t('Description'),
-        'description' => t('RSS 2.0 description element'),
+        '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'),
@@ -210,9 +234,13 @@ class views_plugin_style_rss_fields extends views_plugin_style {
         'description' => t('Dublin core creator element'),
       ),
       'category' => array(
-        'title' => t('category'),
+        'title' => t('Category'),
         'description' => t('RSS 2.0 category 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'),
@@ -258,4 +286,4 @@ class views_plugin_style_rss_fields extends views_plugin_style {
     }
     return FALSE;
   }
-}
\ No newline at end of file
+}
index 93425b8..14b04cb 100644 (file)
@@ -35,16 +35,6 @@ function template_preprocess_views_view_views_rss_fields(&$vars) {
   $rows = '';
   $items = $view->style_plugin->map_rows($vars['rows']);
   foreach($items as $item) {
-    // Special handling for GeoRSS.
-    if (isset($item['lat']) && is_numeric($item['lat']) && isset($item['lon']) && is_numeric($item['lon'])) {
-      $item['georss:point'] = $item['lat'] .' '.  $item['lon'];
-    }
-    if(isset($item['featureName'])) {
-      $item['georss:featureName'] = $item['featureName'];
-    }
-    unset($item['lat']);
-    unset($item['lon']);
-    unset($item['featureName']);
     $rows .= theme('views_rss_fields_item', $item);
     foreach ($item as $k => $v) {
       $elements[$k] = $k;
@@ -66,16 +56,28 @@ function template_preprocess_views_view_views_rss_fields(&$vars) {
  * Template preprocessor for views-rss-fields-item.tpl.php.
  */
 function template_preprocess_views_rss_fields_item(&$vars) {
-  $item = $vars['item'];
-
-  // Loop through key=>value pairs
   $row = '';
-  foreach ($item as $key => $value) {
-    if ($value) {
-      $row .= "<$key>". check_plain(htmlspecialchars_decode($value, ENT_QUOTES)) ."</$key>\n";
+  foreach ($vars['item'] as $key => $values) {
+    if ($values) {
+      switch ($key) {
+        // <enclosure> element was already formatter before
+        // by selected field formatter.
+        case 'enclosure':
+          $row .= $vars['item']['enclosure'] . "\n";
+          break;
+        default:
+          // Some feed elements could contain multiple values (ie. 'Category'),
+          // therefore let's first make sure that EACH feed element is an array
+          // (even if it has one value only) and then loop through all of them.
+          if (!is_array($values)) {
+            $values = array($values);
+          }
+          foreach ($values as $value) {
+            $row .= "<$key>" . $value . "</$key>\n";
+          }
+      }
     }
   }
-
   $vars['row'] = $row;
 }
 
index 3c49f81..04165b4 100644 (file)
 function views_rss_views_api() {
   return array(
     'api' => 2,
-    'path' => drupal_get_path('module', 'views_rss') .'/views',
+    'path' => drupal_get_path('module', 'views_rss') . '/views',
   );
 }
 
 /**
+ * Implementation of hook_field_formatter_info().
+ */
+function views_rss_field_formatter_info() {
+  $formatters = array(
+    // Generic image formatter for <enclosure> element.
+    'views_rss_enclosure_image' => array(
+      'label' => t('RSS enclosure element: image: original size'),
+      'field types' => array('image', 'filefield'),
+    ),
+    // Generic file formatter for <enclosure> element.
+    'views_rss_enclosure_file' => array(
+      'label' => t('RSS enclosure element: file'),
+      'field types' => array('filefield'),
+    ),
+  );
+  // Additional formatters for imagecache module.
+  if (module_exists('imagecache')) {
+    foreach (imagecache_presets() as $preset) {
+      // Imagecache image formatter for <enclosure> element.
+      $formatters['views_rss_enclosure_image' . $preset['presetname']] = array(
+        'label' => t('RSS enclosure element: image: @preset', array('@preset' => $preset['presetname'])),
+        'field types' => array('image', 'filefield'),
+      );
+    }
+  }
+  return $formatters;
+}
+
+/**
  * Implementation of hook_theme().
  */
 function views_rss_theme() {
   $path = drupal_get_path('module', 'views_rss');
-  return array(
+  $theme = array(
     'views_rss_fields_item' => array(
       'arguments' => array('item' => array()),
       'file' => 'views_rss_views_fields.theme.inc',
       'template' => 'views-rss-fields-item',
       'path' => "$path/views",
     ),
-   'views_rss_feed_icon' => array(
+    'views_rss_feed_icon' => array(
       'arguments' => array('url', 'title', 'icon'),
       'file' => 'views_rss_views_fields.theme.inc',
       'path' => "$path/views",
     ),
     'views_rss_feed_description' => array(
-       'arguments' => array('description', 'view'),
-       'file' => 'views_rss_views_fields.theme.inc',
-       'path' => "$path/views",
-     ),
+      'arguments' => array('description', 'view'),
+      'file' => 'views_rss_views_fields.theme.inc',
+      'path' => "$path/views",
+    ),
+    // CCK field formatters.
+    'views_rss_formatter_views_rss_enclosure_image' => array(
+      'arguments' => array('element' => NULL),
+      'function' => 'theme_views_rss_formatter_enclosure_image',
+    ),
+    'views_rss_formatter_views_rss_enclosure_file' => array(
+      'arguments' => array('element' => NULL),
+      'function' => 'theme_views_rss_formatter_enclosure_file',
+    ),
   );
+  if (module_exists('imagecache')) {
+    foreach (imagecache_presets() as $preset) {
+      $theme['views_rss_formatter_views_rss_enclosure_image' . $preset['presetname']] = array(
+        'arguments' => array('element' => NULL),
+        'function' => 'theme_views_rss_formatter_enclosure_image',
+      );
+    }
+  }
+  return $theme;
+}
+
+
+/**
+ * Generic formatter for 'filefield' CCK fields
+ * added to RSS <enclosure> element.
+ */
+function theme_views_rss_formatter_enclosure_file($element) {
+  // Inside a view $element may contain NULL data. In that case, just return.
+  if (empty($element['#item']['fid'])) {
+    return;
+  }
+  // Return formatted XML element.
+  return strtr('<enclosure url="!url" length="!length" type="!type" />', array(
+    '!url'    => url($element['#item']['filepath'], array('absolute' => TRUE)),
+    '!length' => $element['#item']['filesize'],
+    '!type'   => $element['#item']['filemime'],
+  ));
+}
+
+/**
+ * Formatter for 'image' and 'filefield' CCK fields containing images
+ * added to RSS <enclosure> element. Besides default image size
+ * also provides option to use imagecache'd images.
+ */
+function theme_views_rss_formatter_enclosure_image($element) {
+  // Inside a view $element may contain NULL data. In that case, just return.
+  if (empty($element['#item']['fid'])) {
+    return;
+  }
+  // Generate simple array of imagecache presets.
+  $presets = array();
+  foreach (imagecache_presets() as $preset) {
+    $presets[] = $preset['presetname'];
+  }
+  // Get full image URL based on provided imagecache preset.
+  $preset_name = str_replace('views_rss_enclosure_image', '', $element['#formatter']);
+  if ($preset_name && in_array($preset_name, array_keys($presets))) {
+    $path = imagecache_create_url($preset_name, $element['#item']['filepath']);
+  }
+  else {
+    $path = $element['#item']['filepath'];
+  }
+  // Return formatted XML element.
+  return strtr('<enclosure url="!url" length="!length" type="!type" />', array(
+    '!url'    => url($path, array('absolute' => TRUE)),
+    '!length' => $element['#item']['filesize'],
+    '!type'   => $element['#item']['filemime'],
+  ));
 }