Browse Source

more module updates

Bachir Soussi Chiadmi 9 years ago
parent
commit
322dd995bf
25 changed files with 744 additions and 305 deletions
  1. 39 0
      sites/all/modules/contrib/dev/variable/variable.api.php
  2. 12 7
      sites/all/modules/contrib/dev/variable/variable.form.inc
  3. 3 3
      sites/all/modules/contrib/dev/variable/variable.info
  4. 41 5
      sites/all/modules/contrib/dev/variable/variable.module
  5. 4 1
      sites/all/modules/contrib/dev/variable/variable.variable.inc
  6. 3 3
      sites/all/modules/contrib/dev/variable/variable_admin/variable_admin.info
  7. 0 2
      sites/all/modules/contrib/dev/variable/variable_admin/variable_admin.module
  8. 0 11
      sites/all/modules/contrib/dev/variable/variable_advanced/variable_advanced.info
  9. 0 5
      sites/all/modules/contrib/dev/variable/variable_advanced/variable_advanced.module
  10. 0 73
      sites/all/modules/contrib/dev/variable/variable_advanced/variable_advanced.variable.inc
  11. 3 3
      sites/all/modules/contrib/dev/variable/variable_example/variable_example.info
  12. 6 0
      sites/all/modules/contrib/dev/variable/variable_realm/variable_realm.form.inc
  13. 3 3
      sites/all/modules/contrib/dev/variable/variable_realm/variable_realm.info
  14. 2 2
      sites/all/modules/contrib/dev/variable/variable_realm/variable_realm.module
  15. 3 3
      sites/all/modules/contrib/dev/variable/variable_store/variable_store.info
  16. 3 3
      sites/all/modules/contrib/dev/variable/variable_views/variable_views.info
  17. 205 14
      sites/all/modules/contrib/views/views_data_export/plugins/views_data_export_plugin_display_export.inc
  18. 53 30
      sites/all/modules/contrib/views/views_data_export/plugins/views_data_export_plugin_style_export.inc
  19. 13 8
      sites/all/modules/contrib/views/views_data_export/plugins/views_data_export_plugin_style_export_csv.inc
  20. 99 0
      sites/all/modules/contrib/views/views_data_export/plugins/views_data_export_plugin_style_export_xml.inc
  21. 78 41
      sites/all/modules/contrib/views/views_data_export/theme/views_data_export.theme.inc
  22. 38 6
      sites/all/modules/contrib/views/views_data_export/views_data_export.drush.inc
  23. 10 25
      sites/all/modules/contrib/views/views_data_export/views_data_export.info
  24. 74 14
      sites/all/modules/contrib/views/views_data_export/views_data_export.install
  25. 52 43
      sites/all/modules/contrib/views/views_data_export/views_data_export.module

+ 39 - 0
sites/all/modules/contrib/dev/variable/variable.api.php

@@ -84,6 +84,8 @@
  *   - "repeat": Array of variable properties for children variables.
  *   - "localize": Boolean value, TRUE for variables that should be localized. This may be used by other modules.
  *   - "validate callback": Callback to validate the variable value, it will be added to form element #validate.
+ *
+ * @see hook_variable_info_alter()
  */
 function hook_variable_info($options) {
   $variables['site_name'] = array(
@@ -102,6 +104,17 @@ function hook_variable_info($options) {
   return $variables;
 }
 
+/**
+ * Alter the variable definitions.
+ *
+ * @param $info
+ *   The variable info array, keyed by variable name.
+ *
+ * @see hook_variable_info()
+ */
+function hook_variable_info_alter(&$info) {
+}
+
 /**
  * Define types of variables or list of values used by a module.
  *
@@ -145,6 +158,8 @@ function hook_variable_info($options) {
  *
  *   A special attribute:
  *   - "type": Variable subtype, the properties for the subtype will be added to these ones.
+ *
+ * @see hook_variable_type_info_alter()
  */
 function hook_variable_type_info() {
   $type['mail_address'] = array(
@@ -162,6 +177,17 @@ function hook_variable_type_info() {
   return $type;
 }
 
+/**
+ * Alter the variable type definitions.
+ *
+ * @param $info
+ *   The variable type info array, keyed by variable type name.
+ *
+ * @see hook_variable_type_info()
+ */
+function hook_variable_type_info_alter(&$info) {
+}
+
 /**
  * Define groups of variables used by a module.
  *
@@ -181,6 +207,8 @@ function hook_variable_type_info() {
  *   - "description": The human readable description of the group. Must be localized.
  *   - "access": Permission required to edit group's variables. Will default to 'administer site configuration'.
  *   - "path": Array of administration paths where these variables can be accessed.
+ *
+ * @see hook_variable_group_info_alter()
  */
 function hook_variable_group_info() {
   $groups['system_site_information'] = array(
@@ -197,6 +225,17 @@ function hook_variable_group_info() {
   return $groups;
 }
 
+/**
+ * Alter the variable group definitions.
+ *
+ * @param $info
+ *   The variable type info array, keyed by variable group name.
+ *
+ * @see hook_variable_group_info()
+ */
+function hook_variable_group_info_alter(&$info) {
+}
+
 /**
  * Alter system settings forms.
  *

+ 12 - 7
sites/all/modules/contrib/dev/variable/variable.form.inc

@@ -154,14 +154,19 @@ function variable_form_element_options($variable, $options = array()) {
 }
 
 /**
- * Implement validate callback
+ * Execute submit callbacks for variables in form.
  */
-function variable_form_element_validate($element, &$form_state, $form) {
-  $variable = $element['#variable'];
-  variable_include($variable);
-  $variable['value'] = isset($element['#value']) ? $element['#value'] : NULL;
-  if ($error = call_user_func($variable['validate callback'], $variable)) {
-    form_error($element, $error);
+function variable_form_submit_callback($form, &$form_state) {
+  if (isset($form['#variable_edit_form'])) {
+    // This may contain some realm options.
+    $options = isset($form['#variable_options']) ? $form['#variable_options'] : array();
+    foreach ($form['#variable_edit_form'] as $name) {
+      $variable = variable_get_info($name);
+      if ($variable && isset($variable['submit callback'])) {
+        variable_include($variable);
+        $variable['submit callback']($variable, $options, $form, $form_state);
+      }
+    }
   }
 }
 

+ 3 - 3
sites/all/modules/contrib/dev/variable/variable.info

@@ -12,9 +12,9 @@ files[] = includes/taxonomy.variable.inc
 files[] = includes/translation.variable.inc
 files[] = includes/user.variable.inc
 files[] = variable.test
-; Information added by drupal.org packaging script on 2013-08-09
-version = "7.x-2.3"
+; Information added by Drupal.org packaging script on 2014-04-23
+version = "7.x-2.5"
 core = "7.x"
 project = "variable"
-datestamp = "1376034993"
+datestamp = "1398250128"
 

+ 41 - 5
sites/all/modules/contrib/dev/variable/variable.module

@@ -415,16 +415,35 @@ function variable_hook_info() {
  * Form for variable list
  *
  * @param $list
- *   Variable name or list of variable names
+ *   Variable name or list of variable names.
+ * @param $options
+ *   Optional array with variable options.
  */
-function variable_edit_form($form, $form_state, $list, $options = array()) {
-  // Pass on the values on the form for further reference.
-  $form['#variable_edit_form'] = $list;
-  form_load_include($form_state, 'form.inc', 'variable');
+function variable_edit_form($form, &$form_state, $list, $options = array()) {
+  $list = is_array($list) ? $list : array($list);
+  $form = variable_base_form($form, $form_state, $list, $options);
   $form += variable_edit_subform($list, $options);
   return variable_settings_form($form, $options);
 }
 
+/**
+ * Build base form for variable list without fields.
+ *
+ * @param $list
+ *   List of variable names.
+ * @param $options
+ *   Optional array with variable options.
+ */
+function variable_base_form($form, &$form_state, $list, $options = array()) {
+  form_load_include($form_state, 'form.inc', 'variable');
+  // Pass on the values on the form for further reference.
+  $form['#variable_edit_form'] = $list;
+  $form['#variable_options'] = $options;
+  // Run submit callback for variables in form.
+  $form['#submit'][] = 'variable_form_submit_callback';
+  return $form;
+}
+
 /**
  * Form elements for variable list.
  *
@@ -682,7 +701,23 @@ function variable_form_alter(&$form, &$form_state, $form_id) {
   }
 }
 
+/**
+ * Implement validate callback.
+ *
+ * This needs to be in the module as it may be needed by form ajax callbacks.
+ */
+function variable_form_element_validate($element, &$form_state, $form) {
+  $options = isset($form['#variable_options']) ? $form['#variable_options'] : array();
+  $variable = $element['#variable'];
+  variable_include($variable);
+  $variable['value'] = isset($element['#value']) ? $element['#value'] : NULL;
+
+  $error = $variable['validate callback']($variable, $options, $element, $form, $form_state);
 
+  if ($error) {
+    form_error($element, $error);
+  }
+}
 
 /**
  * Implements hook_module_implements_alter().
@@ -765,6 +800,7 @@ function variable_settings_form_submit($form, &$form_state) {
   form_state_values_clean($form_state);
   // This may contain some realm options.
   $options = isset($form['#variable_options']) ? $form['#variable_options'] : array();
+
   // Now run regular settings submission but using variable_set_value()
   foreach ($form_state['values'] as $key => $value) {
     if (is_array($value) && isset($form_state['values']['array_filter'])) {

+ 4 - 1
sites/all/modules/contrib/dev/variable/variable.variable.inc

@@ -376,7 +376,10 @@ function variable_format_multiple($variable, $options = array()) {
  * Validate numeric variable.
  */
 function variable_validate_number($variable) {
-  if (!is_numeric($variable['value'])) {
+  if (empty($variable['required']) && empty($variable['value'])) {
+    return;
+  }
+  elseif (!is_numeric($variable['value'])) {
     return t('The value is not a number.');
   }
 }

+ 3 - 3
sites/all/modules/contrib/dev/variable/variable_admin/variable_admin.info

@@ -3,9 +3,9 @@ description = Variable Administration UI
 dependencies[] = variable
 package = Variable
 core = 7.x
-; Information added by drupal.org packaging script on 2013-08-09
-version = "7.x-2.3"
+; Information added by Drupal.org packaging script on 2014-04-23
+version = "7.x-2.5"
 core = "7.x"
 project = "variable"
-datestamp = "1376034993"
+datestamp = "1398250128"
 

+ 0 - 2
sites/all/modules/contrib/dev/variable/variable_admin/variable_admin.module

@@ -105,5 +105,3 @@ function variable_admin_realm_title($realm) {
   $info = variable_realm_info($realm);
   return isset($info['title']) ? $info['title'] : $realm;
 }
-
-

+ 0 - 11
sites/all/modules/contrib/dev/variable/variable_advanced/variable_advanced.info

@@ -1,11 +0,0 @@
-name = Variable advanced
-description = Provides access to advanced low level variables. By using this you will be able to break your site badly.
-dependencies[] = variable
-package = Variable
-core = 7.x
-; Information added by drupal.org packaging script on 2013-08-09
-version = "7.x-2.3"
-core = "7.x"
-project = "variable"
-datestamp = "1376034993"
-

+ 0 - 5
sites/all/modules/contrib/dev/variable/variable_advanced/variable_advanced.module

@@ -1,5 +0,0 @@
-<?php
-/**
- * @file
- * Drupal module - Advanced variable otpions.
- */

+ 0 - 73
sites/all/modules/contrib/dev/variable/variable_advanced/variable_advanced.variable.inc

@@ -1,73 +0,0 @@
-<?php
-/**
- * @file
- * Advanced variables.
- */
-
-/**
- * Implements hook_variable_group_info().
- */
-function variable_advanced_variable_group_info() {
-  $groups['advanced'] = array(
-    'title' => t('Advanced options'),
-    'description' => t('Advanced settings not usually exposed. Changing these variables may seriously break your site so make sure you know what you do.'),
-  );
-  return $groups;
-}
-
-/**
- * Implements hook_variable_info().
- */
-function variable_advanced_variable_info($options) {
-  // Bootstrap caching options
-  $variables['page_cache_invoke_hooks'] = array(
-    'title' => t('Cache invoke hooks'),
-    'type' => 'enable',
-    'default' => 1,
-    'group' => 'advanced',
-    'description' => T('Invoke <em>boot</em> and <em>exit</em> hooks when the page is served from cache.'),
-  );
-  $variables['actions_max_stack'] = array(
-    'title' => t('Actions recursion level'),
-    'type' => 'number',
-    'default' => 35,
-    'group' => 'advanced',
-    'description' => t('Maximum recursion level for actions before the execution is aborted.', array(), $options),
-  ); 
-  // Bootstrap language variables.
-  $variables['language_count'] = array(
-    'title' => t('Language count'),
-    'type' => 'number',
-    'default' => 1,
-    'group' => 'advanced',
-    'description' => t('Number of enabled languages, used for quick bootstrap. Not to be changed manually.', array(), $options),
-  );
-  $variables['language_types'] = array(
-    'title' => t('Language types'),
-    'type' => 'array',
-    'default callback' => 'drupal_language_types',
-    'group' => 'advanced',
-    'description' => t('Available language types.'),
-  );  
-  // Bootstrap proxy configuration
-  $variables['reverse_proxy'] = array(
-    'title' => t('Reverse proxy'),
-    'type' => 'enable',
-    'default' => 0,
-    'group' => 'advanced',
-    'description' => t('If Drupal is behind a reverse proxy, we use the X-Forwarded-For header instead of $_SERVER[\'REMOTE_ADDR\'], which would be the IP address of the proxy server, and not the client\'s. The actual header name can be configured by the reverse_proxy_header variable.', array(), $options),
-  );
-  $variables['reverse_proxy_header'] = array(
-    'title' => t('Reverse proxy header'),
-    'default' => 'HTTP_X_FORWARDED_FOR',
-    'group' => 'advanced',
-  );
-  $variables['reverse_proxy_addresses'] = array(
-    'title' => t('Reverse proxy addresses'),
-    'type' => 'array',
-    'group' => 'advanced',
-    'default' => array(),
-    'description' => t('If an array of known reverse proxy IPs is provided, then trust the XFF header if request really comes from one of them.', array(), $options),
-  );  
-  return $variables;
-}

+ 3 - 3
sites/all/modules/contrib/dev/variable/variable_example/variable_example.info

@@ -6,9 +6,9 @@ package = Example modules
 core = 7.x
 files[] = variable_example.variable.inc
 
-; Information added by drupal.org packaging script on 2013-08-09
-version = "7.x-2.3"
+; Information added by Drupal.org packaging script on 2014-04-23
+version = "7.x-2.5"
 core = "7.x"
 project = "variable"
-datestamp = "1376034993"
+datestamp = "1398250128"
 

+ 6 - 0
sites/all/modules/contrib/dev/variable/variable_realm/variable_realm.form.inc

@@ -86,7 +86,13 @@ function variable_realm_edit_variables_form($form, &$form_state, $realm_name, $r
   $form['realm_name'] = array('#type' => 'value', '#value' => $realm_name);
   $form['realm_key'] = array('#type' => 'value', '#value' => $realm_key);
   $options['realm'] = variable_realm($realm_name, $realm_key);
+
   if ($variable_list = $controller->getEnabledVariables()) {
+    $form = variable_base_form($form, $form_state, $variable_list, $options);
+    // variable_base_form() adds its own submit handler overriding the default,
+    // so we need to add it as a explicit submit callback here.
+    $form['#submit'][] = 'variable_realm_edit_variables_form_submit';
+
     // Group variables by variable group for vertical tabls
     $group_list = array();
     foreach ($variable_list as $variable_name) {

+ 3 - 3
sites/all/modules/contrib/dev/variable/variable_realm/variable_realm.info

@@ -8,9 +8,9 @@ version = 7.x-2.x
 files[] = variable_realm.class.inc
 files[] = variable_realm_union.class.inc
 
-; Information added by drupal.org packaging script on 2013-08-09
-version = "7.x-2.3"
+; Information added by Drupal.org packaging script on 2014-04-23
+version = "7.x-2.5"
 core = "7.x"
 project = "variable"
-datestamp = "1376034993"
+datestamp = "1398250128"
 

+ 2 - 2
sites/all/modules/contrib/dev/variable/variable_realm/variable_realm.module

@@ -29,10 +29,10 @@ function variable_realm_boot() {
  * Implements hook_init()
  *
  * Let realms be overriden by query string parameters, but only for:
- * - Admin paths (not variable admin pages)
+ * - Admin paths (not variable realm admin pages)
  */
 function variable_realm_init() {
-  if (arg(0) == 'admin' && arg(3) != 'variable' && ($params = variable_realm_params()) && user_access('administer site configuration')) {
+  if (arg(0) == 'admin' && (arg(3) != 'variable' || arg(4) != 'realm') && ($params = variable_realm_params()) && user_access('administer site configuration')) {
     foreach ($params as $realm_name => $realm_key) {
       variable_realm_switch($realm_name, $realm_key, FALSE);
     }

+ 3 - 3
sites/all/modules/contrib/dev/variable/variable_store/variable_store.info

@@ -8,9 +8,9 @@ version = 7.x-2.x
 files[] = variable_store.class.inc
 files[] = variable_store.test
 
-; Information added by drupal.org packaging script on 2013-08-09
-version = "7.x-2.3"
+; Information added by Drupal.org packaging script on 2014-04-23
+version = "7.x-2.5"
 core = "7.x"
 project = "variable"
-datestamp = "1376034993"
+datestamp = "1398250128"
 

+ 3 - 3
sites/all/modules/contrib/dev/variable/variable_views/variable_views.info

@@ -9,9 +9,9 @@ files[] = includes/views_plugin_argument_default_variable.inc
 files[] = includes/views_handler_field_variable_title.inc
 files[] = includes/views_handler_field_variable_value.inc
 
-; Information added by drupal.org packaging script on 2013-08-09
-version = "7.x-2.3"
+; Information added by Drupal.org packaging script on 2014-04-23
+version = "7.x-2.5"
 core = "7.x"
 project = "variable"
-datestamp = "1376034993"
+datestamp = "1398250128"
 

+ 205 - 14
sites/all/modules/contrib/views/views_data_export/plugins/views_data_export_plugin_display_export.inc

@@ -63,8 +63,12 @@ class views_data_export_plugin_display_export extends views_plugin_display_feed
     $options = parent::option_definition();
     $options['use_batch'] = array('default' => 'no_batch');
     $options['items_per_page'] = array('default' => '0');
+    $options['return_path'] = array('default' => '');
     $options['style_plugin']['default'] = 'views_data_export_csv';
 
+    // This is the default size of a segment when doing a batched export.
+    $options['segment_size']['default'] = 100;
+
     if (isset($options['defaults']['default']['items_per_page'])) {
       $options['defaults']['default']['items_per_page'] = FALSE;
     }
@@ -113,6 +117,27 @@ class views_data_export_plugin_display_export extends views_plugin_display_feed
             'batch' => t('Export data in small segments to build a complete export. Recommended for large exports sets (1000+ rows)'),
           ),
         );
+        // Allow the administrator to configure the number of items exported per batch.
+        $form['segment_size'] = array(
+          '#type' => 'select',
+          '#title' => t('Segment size'),
+          '#description' => t('If each row of your export consumes a lot of memory to render, then reduce this value. Higher values will generally mean that the export completes in less time but will have a higher peak memory usage.'),
+          '#options' => drupal_map_assoc(range(1, 500)),
+          '#default_value' => $this->get_option('segment_size'),
+          '#process' => array('ctools_dependent_process'),
+          '#dependency' => array(
+            'radio:use_batch' => array('batch')
+          ),
+        );
+        $form['return_path'] = array(
+          '#title' => t('Return path'),
+          '#type' => 'textfield',
+          '#description' => t('Return path after the batched operation, leave empty for default. This path will only be used if the export URL is visited directly, and not by following a link when attached to another view display.'),
+          '#default_value' => $this->get_option('return_path'),
+          '#dependency' => array(
+            'radio:use_batch' => array('batch')
+          ),
+        );
         if (!$this->is_compatible()) {
           $form['use_batch']['#disabled'] = TRUE;
           $form['use_batch']['#default_value'] = 'no_batch';
@@ -123,7 +148,33 @@ class views_data_export_plugin_display_export extends views_plugin_display_feed
           );
         }
         break;
+
+      case 'cache':
+        // We're basically going to disable using cache plugins, by disabling
+        // the UI.
+        if (isset($form['cache']['type']['#options'])) {
+          foreach ($form['cache']['type']['#options'] as $id => $v) {
+            if ($id != 'none') {
+              unset($form['cache']['type']['#options'][$id]);
+            }
+            $form['cache']['type']['#description'] = t("Views data export isn't currently compatible with caching plugins.");
+          }
+        }
+        break;
+
+    }
+  }
+
+  function get_option($option) {
+    // Force people to never use caching with Views data export. Sorry folks,
+    // but it causes too many issues for our workflow. If you really want to add
+    // caching back, then you can subclass this display handler and override
+    // this method to add it back.
+    if ($option == 'cache') {
+      return array('type' => 'none');
     }
+
+    return parent::get_option($option);
   }
 
   /**
@@ -135,6 +186,8 @@ class views_data_export_plugin_display_export extends views_plugin_display_feed
     switch ($form_state['section']) {
       case 'use_batch':
         $this->set_option('use_batch', $form_state['values']['use_batch']);
+        $this->set_option('segment_size', $form_state['values']['segment_size']);
+        $this->set_option('return_path', $form_state['values']['return_path']);
         break;
     }
   }
@@ -253,17 +306,23 @@ class views_data_export_plugin_display_export extends views_plugin_display_feed
     // Build up our querystring for the final page callback.
     $querystring = array(
       'eid' => $this->batched_execution_state->eid,
+      'return-url' => NULL,
     );
-    // If we were attached to another view, grab that for the final URL.
-    if (!empty($_GET['attach']) && isset($this->view->display[$_GET['attach']])) {
+
+    // If we have a configured return path, use that.
+    if ($this->get_option('return_path')) {
+      $querystring['return-url'] = $this->get_option('return_path');
+    }
+    // Else if we were attached to another view, grab that for the final URL.
+    else if (!empty($_GET['attach']) && isset($this->view->display[$_GET['attach']])) {
       // Get the path of the attached display:
-      $querystring['return-url'] = $this->view->display[$_GET['attach']]->handler->get_path();
+      $querystring['return-url'] = $this->view->get_url(NULL, $this->view->display[$_GET['attach']]->handler->get_path());
     }
 
     //Set the batch off
     $batch = array(
       'operations' => array (
-        array('_views_data_export_batch_process', array($this->batched_execution_state->eid, $this->view->current_display)),
+        array('_views_data_export_batch_process', array($this->batched_execution_state->eid, $this->view->current_display,  $this->view->get_exposed_input())),
       ),
       'title' => t('Building export'),
       'init_message' => t('Export is starting up.'),
@@ -280,6 +339,7 @@ class views_data_export_plugin_display_export extends views_plugin_display_feed
     // e.g. Drush to grab this batch and yet execute it in
     // it's own special way
     $batch['view_name'] = $this->view->name;
+    $batch['exposed_filters'] = $this->view->get_exposed_input();
     $batch['display_id'] = $this->view->current_display;
     $batch['eid'] = $this->batched_execution_state->eid;
     $batch_redirect = array($final_destination, array('query' => $querystring));
@@ -433,7 +493,7 @@ class views_data_export_plugin_display_export extends views_plugin_display_feed
 
           // Grab our results from the index, and push them into the view result.
           // TODO: Handle external databases.
-          $result = db_query_range('SELECT * FROM {' . $this->index_tablename() . '} ORDER BY ' . $this->batched_execution_state->sandbox['weight_field_alias'] . ' ASC', 0, 100);
+          $result = db_query_range('SELECT * FROM {' . $this->index_tablename() . '} ORDER BY ' . $this->batched_execution_state->sandbox['weight_field_alias'] . ' ASC', 0, $this->get_option('segment_size'));
           $this->view->result = array();
           foreach ($result as $item_hashed) {
             $item = new stdClass();
@@ -493,7 +553,7 @@ class views_data_export_plugin_display_export extends views_plugin_display_feed
         // Change the items per page.
         $this->view->set_items_per_page(20);
         // Force a pager to be used.
-        $this->set_option('pager', array('type' => 'some'));
+        $this->set_option('pager', array('type' => 'some', 'options' => array()));
         return '<p>' . t('A maximum of 20 items will be shown here, all results will be shown on export.') . '</p><pre>' . check_plain($this->view->render()) . '</pre>';
       }
       return $this->view->render();
@@ -531,7 +591,16 @@ class views_data_export_plugin_display_export extends views_plugin_display_feed
     $view->build();
 
     // Change the query object to use our custom one.
-    $query = new views_data_export_plugin_query_default_batched();
+    switch ($this->_get_database_driver()) {
+      case 'pgsql':
+        $query_class = 'views_data_export_plugin_query_pgsql_batched';
+        break;
+
+      default:
+        $query_class = 'views_data_export_plugin_query_default_batched';
+        break;
+    }
+    $query = new $query_class();
     // Copy the query over:
     foreach ($view->query as $property => $value) {
       $query->$property = $value;
@@ -600,9 +669,14 @@ class views_data_export_plugin_display_export extends views_plugin_display_feed
    * Get the output file path.
    */
   function outputfile_path() {
-    if (empty($this->_output_file) && !empty($this->batched_execution_state->fid)) {
-      // Return the filename associated with this file.
-      $this->_output_file = $this->file_load($this->batched_execution_state->fid);
+    if (empty($this->_output_file)) {
+      if (!empty($this->batched_execution_state->fid)) {
+        // Return the filename associated with this file.
+        $this->_output_file = $this->file_load($this->batched_execution_state->fid);
+      }
+      else {
+        return NULL;
+      }
     }
     return $this->_output_file->uri;
   }
@@ -614,7 +688,7 @@ class views_data_export_plugin_display_export extends views_plugin_display_feed
    */
   protected function outputfile_create() {
 
-    $dir = 'temporary://views_plugin_display';
+    $dir = variable_get('views_data_export_directory', 'temporary://views_plugin_display');
 
     // Make sure the directory exists first.
     if (!file_prepare_directory($dir, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) {
@@ -675,7 +749,7 @@ class views_data_export_plugin_display_export extends views_plugin_display_feed
   *   An array containing the file information, or 0 in the event of an error.
   */
   function file_save_file($filepath) {
-    return file_save_data('', $filepath);
+    return file_save_data('', $filepath, FILE_EXISTS_REPLACE);
   }
 
   /**
@@ -704,7 +778,7 @@ class views_data_export_plugin_display_export extends views_plugin_display_feed
    */
   function is_compatible() {
     $incompatible_drivers = array (
-      'pgsql',
+      //'pgsql',
     );
     $db_driver = $this->_get_database_driver();
     return !in_array($db_driver, $incompatible_drivers);
@@ -713,7 +787,7 @@ class views_data_export_plugin_display_export extends views_plugin_display_feed
   function  _get_database_driver() {
     $name = !empty($this->view->base_database) ? $this->view->base_database : 'default';
     $conn_info = Database::getConnectionInfo($name);
-    return $conn_info[$name]['driver'];
+    return $conn_info['default']['driver'];
   }
 }
 
@@ -808,6 +882,123 @@ class views_data_export_plugin_query_default_batched extends views_plugin_query_
         db_query($insert_query, $args);
 
 
+        $view->result = array();
+
+        $this->pager->post_execute($view->result);
+
+        if ($this->pager->use_pager()) {
+          $view->total_rows = $this->pager->get_total_items();
+        }
+
+        // Now create an index for the weight field, otherwise the queries on the
+        // index will take a long time to execute.
+        db_add_unique_key($display_handler->index_tablename(), $display_handler->batched_execution_state->sandbox['weight_field_alias'], array($display_handler->batched_execution_state->sandbox['weight_field_alias']));
+      }
+      catch (Exception $e) {
+        $view->result = array();
+        debug('Exception: ' . $e->getMessage());
+      }
+
+    }
+    $view->execute_time = microtime(TRUE) - $start;
+  }
+}
+
+class views_data_export_plugin_query_pgsql_batched extends views_data_export_plugin_query_default_batched {
+
+
+  /**
+   * Executes the query and fills the associated view object with according
+   * values.
+   *
+   * Values to set: $view->result, $view->total_rows, $view->execute_time,
+   * $view->current_page.
+   */
+  function execute(&$view) {
+    $display_handler = &$view->display_handler;
+    $external = FALSE; // Whether this query will run against an external database.
+    $query = $view->build_info['query'];
+    $count_query = $view->build_info['count_query'];
+
+    $query->addMetaData('view', $view);
+    $count_query->addMetaData('view', $view);
+
+    if (empty($this->options['disable_sql_rewrite'])) {
+      $base_table_data = views_fetch_data($this->base_table);
+      if (isset($base_table_data['table']['base']['access query tag'])) {
+        $access_tag = $base_table_data['table']['base']['access query tag'];
+        $query->addTag($access_tag);
+        $count_query->addTag($access_tag);
+      }
+    }
+
+    $items = array();
+    if ($query) {
+      $additional_arguments = module_invoke_all('views_query_substitutions', $view);
+
+      // Count queries must be run through the preExecute() method.
+      // If not, then hook_query_node_access_alter() may munge the count by
+      // adding a distinct against an empty query string
+      // (e.g. COUNT DISTINCT(1) ...) and no pager will return.
+      // See pager.inc > PagerDefault::execute()
+      // http://api.drupal.org/api/drupal/includes--pager.inc/function/PagerDefault::execute/7
+      // See http://drupal.org/node/1046170.
+      $count_query->preExecute();
+
+      // Build the count query.
+      $count_query = $count_query->countQuery();
+
+      // Add additional arguments as a fake condition.
+      // XXX: this doesn't work... because PDO mandates that all bound arguments
+      // are used on the query. TODO: Find a better way to do this.
+      if (!empty($additional_arguments)) {
+        // $query->where('1 = 1', $additional_arguments);
+        // $count_query->where('1 = 1', $additional_arguments);
+      }
+
+      $start = microtime(TRUE);
+
+      if ($this->pager->use_count_query() || !empty($view->get_total_rows)) {
+        $this->pager->execute_count_query($count_query);
+      }
+
+      // Let the pager modify the query to add limits.
+      $this->pager->pre_execute($query);
+
+      if (!empty($this->limit) || !empty($this->offset)) {
+        // We can't have an offset without a limit, so provide a very large limit instead.
+        $limit  = intval(!empty($this->limit) ? $this->limit : 999999);
+        $offset = intval(!empty($this->offset) ? $this->offset : 0);
+        $query->range($offset, $limit);
+      }
+
+      try {
+        // The $query is final and ready to go, we are going to redirect it to
+        // become an insert into our table, sneaky!
+        // Our query will look like:
+        // CREATE TABLE {idx} SELECT @row := @row + 1 AS weight_alias, cl.* FROM
+        // (-query-) AS cl, (SELECT @row := 0) AS r
+        // We do some magic to get the row count.
+
+        $display_handler->batched_execution_state->sandbox['weight_field_alias'] = $display_handler->_weight_alias_create($view);
+
+        $display_handler->batched_execution_state->sandbox['field_aliases'] = $display_handler->field_aliases_create($view);
+        $select_aliases = array();
+        foreach ($display_handler->batched_execution_state->sandbox['field_aliases'] as $hash => $alias) {
+          $select_aliases[] = "cl.$alias AS $hash";
+        }
+
+        // TODO: this could probably be replaced with a query extender and new query type.
+        $query->preExecute();
+        $args = $query->getArguments();
+        // Create temporary sequence
+        $seq_name = $display_handler->index_tablename() . '_seq';
+        db_query('CREATE TEMP sequence ' . $seq_name);
+        // Query uses sequence to create row number
+        $insert_query = 'CREATE TABLE {' . $display_handler->index_tablename() . "} AS SELECT nextval('". $seq_name . "') AS " . $display_handler->batched_execution_state->sandbox['weight_field_alias'] . ', ' . implode(', ', $select_aliases) . ' FROM (' . (string)$query . ') AS cl';
+        db_query($insert_query, $args);
+
+
         $view->result = array();
 
         $this->pager->post_execute($view->result);

+ 53 - 30
sites/all/modules/contrib/views/views_data_export/plugins/views_data_export_plugin_style_export.inc

@@ -149,29 +149,33 @@ class views_data_export_plugin_style_export extends views_plugin_style {
    * feed image link.
    */
   function attach_to($display_id, $path, $title) {
-
-    $type = $this->definition['export feed type'];
-    $theme_pattern = array(
-      'views_data_export_feed_icon__' . $this->view->name . '__' . $display_id . '__' . $type,
-      'views_data_export_feed_icon__' . $this->view->name . '__' . $display_id,
-      'views_data_export_feed_icon__' . $this->view->name . '__' . $type,
-      'views_data_export_feed_icon__' . $display_id . '__' . $type,
-      'views_data_export_feed_icon__' . $display_id,
-      'views_data_export_feed_icon__' . $type,
-      'views_data_export_feed_icon',
-    );
-    $query = $this->view->get_exposed_input();
-    // Stash the display id we're coming form in the url so we can hijack it later.
-    if ($this->options['parent_sort']) {
-      $query['attach'] = $display_id;
+    if ($this->display->handler->access()) {
+      $type = $this->definition['export feed type'];
+      $theme_pattern = array(
+        'views_data_export_feed_icon__' . $this->view->name . '__' . $display_id . '__' . $type,
+        'views_data_export_feed_icon__' . $this->view->name . '__' . $display_id,
+        'views_data_export_feed_icon__' . $this->view->name . '__' . $type,
+        'views_data_export_feed_icon__' . $display_id . '__' . $type,
+        'views_data_export_feed_icon__' . $display_id,
+        'views_data_export_feed_icon__' . $type,
+        'views_data_export_feed_icon',
+      );
+      $query = $this->view->get_exposed_input();
+      // Stash the display id we're coming form in the url so we can hijack it later.
+      if ($this->options['parent_sort']) {
+        $query['attach'] = $display_id;
+      }
+      if (!isset($this->view->feed_icon)) {
+        $this->view->feed_icon = '';
+      }
+      $this->view->feed_icon .= theme($theme_pattern, array(
+          'image_path' => $this->definition['export feed icon'],
+          'url' => $this->view->get_url(NULL, $path),
+          'query' => $query,
+          'text' => $this->options['attach_text'],
+        )
+      );
     }
-    $this->view->feed_icon .= theme($theme_pattern, array(
-        'image_path' => $this->definition['export feed icon'],
-        'url' => $this->view->get_url(NULL, $path),
-        'query' => $query,
-        'text' => $this->options['attach_text'],
-      )
-    );
   }
 
   function build_sort() {
@@ -291,7 +295,6 @@ class views_data_export_plugin_style_export extends views_plugin_style {
    * Add any HTTP headers that this style plugin wants to.
    */
   function add_http_headers() {
-    $view = &$this->view;
 
     drupal_add_http_header('Cache-Control', 'max-age=60, must-revalidate');
 
@@ -301,6 +304,22 @@ class views_data_export_plugin_style_export extends views_plugin_style {
       }
     }
 
+    if (isset($this->options['filename']) && !empty($this->options['provide_file'])) {
+      $filename = $this->generate_filename();
+
+      if ($filename) {
+        drupal_add_http_header('Content-Disposition', 'attachment; filename="'. $filename .'"');
+      }
+    }
+  }
+
+  /**
+   * Generate the filename for the export.
+   */
+  function generate_filename() {
+    $view = $this->view;
+    $filename = '';
+
     if (isset($this->options['filename']) && !empty($this->options['provide_file'])) {
       // General tokens.
       $tokens = array(
@@ -311,7 +330,7 @@ class views_data_export_plugin_style_export extends views_plugin_style {
       $count = 0;
       foreach ($view->display_handler->get_handlers('argument') as $arg => $handler) {
         $token = '%' . ++$count;
-        $tokens[$token . '-title'] = check_plain($handler->title());
+        $tokens[$token . '-title'] = $handler->get_title();
         $tokens[$token . '-value'] = isset($view->args[$count - 1]) ? check_plain($view->args[$count - 1]) : '';
       }
 
@@ -322,7 +341,14 @@ class views_data_export_plugin_style_export extends views_plugin_style {
           continue;
         }
         if (!empty($view->exposed_input[$handler->options['expose']['identifier']])) {
-          $exposed[] = check_plain($handler->options['expose']['identifier']) . '_' . check_plain($view->exposed_input[$handler->options['expose']['identifier']]);
+          $identifier = $handler->options['expose']['identifier'];
+          $option = $view->exposed_input[$identifier];
+          // The option may be a string or an array, depending on whether the
+          // widget is a text box/area or a select box.
+          if (is_array($option)) {
+            $option = implode('--', $option);
+          }
+          $exposed[] = check_plain($identifier) . '_' . check_plain($option);
         }
       }
       if (!empty($exposed)) {
@@ -351,11 +377,8 @@ class views_data_export_plugin_style_export extends views_plugin_style {
       }
 
       $filename = strtr($this->options['filename'], $tokens);
-
-
-      if ($filename) {
-        drupal_add_http_header('Content-Disposition', 'attachment; filename="'. $filename .'"');
-      }
     }
+
+    return $filename;
   }
 }

+ 13 - 8
sites/all/modules/contrib/views/views_data_export/plugins/views_data_export_plugin_style_export_csv.inc

@@ -44,12 +44,15 @@ class views_data_export_plugin_style_export_csv extends views_data_export_plugin
       'default' => TRUE,
       'translatable' => FALSE,
     );
+    $options['keep_html'] = array(
+      'default' => FALSE,
+      'translatable' => FALSE,
+    );
     $options['encoding'] = array(
       'default' => '',
       'translatable' => FALSE,
     );
 
-
     return $options;
   }
 
@@ -93,7 +96,7 @@ class views_data_export_plugin_style_export_csv extends views_data_export_plugin
       '#type' => 'textfield',
       '#title' => t('Replacement'),
       '#default_value' => $this->options['newline_replacement'],
-      '#process' => array('form_process_checkboxes', 'ctools_dependent_process'),
+      '#process' => array('ctools_dependent_process'),
       '#dependency' => array('edit-style-options-replace-newlines' => array(TRUE)),
     );
     $form['header'] = array(
@@ -101,15 +104,17 @@ class views_data_export_plugin_style_export_csv extends views_data_export_plugin
       '#title' => t('Make first row a list of column headers.'),
       '#default_value' => !empty($this->options['header']),
     );
+    $form['keep_html'] = array(
+      '#type' => 'checkbox',
+      '#default_value' => !empty($this->options['keep_html']),
+      '#title' => t('Keep HTML tags.'),
+    );
     $form['encoding'] = array(
-      '#type' => 'select',
+      '#type' => 'textfield',
       '#default_value' => !empty($this->options['encoding']) ? $this->options['encoding'] : '',
       '#title' => t('Character encoding conversion'),
-      '#options' => array (
-        '' => t('No conversion'),
-        'ASCII' => t('ASCII'),
-      ),
-      '#description' => t('Optionally specify a character conversion that some CSV file readers need. Note, using an external tool is always preferred and you should only use this option as a last resort. This feature requires the "iconv" PHP extension.'),
+      '#description' => t('Optionally specify a character conversion that some CSV file readers need. Use "utf8_decode" for ISO-8859-1 via <a href="@utf8_decode">utf8_decode PHP function</a>, other values will be passed <a href="@iconv">iconv</a> (this requires the iconv PHP extension), empty or illegal values will leave the output as UTF-8.',
+        array('@iconv' => 'http://www.php.net/manual/en/function.iconv.php', '@utf8_decode' => 'http://www.php.net/manual/en/function.utf8-decode.php')),
     );
   }
 }

+ 99 - 0
sites/all/modules/contrib/views/views_data_export/plugins/views_data_export_plugin_style_export_xml.inc

@@ -11,6 +11,26 @@
  */
 class views_data_export_plugin_style_export_xml extends views_data_export_plugin_style_export {
 
+  /**
+   * Initialize a style plugin.
+   */
+  function init(&$view, &$display, $options = NULL) {
+    // View is not set in option_definition(), so we fill defaults here if
+    // options are empty.
+    if (empty($options['root_node']) || empty($options['item_node'])) {
+      $base_object_name = rtrim($view->base_table, 's');
+
+      if (empty($options['root_node'])) {
+        $options['root_node'] = $base_object_name . 's';
+      }
+      if (empty($options['item_node'])) {
+        $options['item_node'] = $base_object_name;
+      }
+    }
+
+    parent::init($view, $display, $options);
+  }
+
   /**
    * Set options fields and default values.
    *
@@ -28,6 +48,22 @@ class views_data_export_plugin_style_export_xml extends views_data_export_plugin
       'default' => 'dash',
       'translatable' => FALSE,
     );
+    $options['root_node'] = array(
+      'default' => '',
+      'translatable' => FALSE,
+    );
+    $options['item_node'] = array(
+      'default' => '',
+      'translatable' => FALSE,
+    );
+    $options['no_entity_encode'] = array(
+      'default' => array(),
+      'translatable' => FALSE,
+    );
+    $options['cdata_wrapper'] = array(
+      'default' => array(),
+      'translatable' => FALSE,
+    );
 
     return $options;
   }
@@ -66,5 +102,68 @@ class views_data_export_plugin_style_export_xml extends views_data_export_plugin
         'edit-style-options-transform' => array(TRUE),
       ),
     );
+    $form['root_node'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Root node'),
+      '#default_value' => $this->options['root_node'],
+      '#description' => t('The XML tag for the root node.'),
+    );
+    $form['item_node'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Item node'),
+      '#default_value' => $this->options['item_node'],
+      '#description' => t('The XML tag for an item node.'),
+    );
+
+    $field_labels = $this->display->handler->get_field_labels();
+
+    if (!empty($field_labels)) {
+      $options = $field_labels;
+      if (empty($this->options['no_entity_encode'])) {
+        $this->options['no_entity_encode'] = array();
+      }
+
+      $form['no_entity_encode'] = array(
+        '#type' => 'checkboxes',
+        '#title' => t('Disable encoding of XML entities for these fields'),
+        '#options' => $options,
+        '#default_value' => $this->options['no_entity_encode'],
+        '#description' => t('If checked field contents will be outputted '.
+                            '<em>without encoding</em> of XML entities. This is '.
+                            'useful when when used in conjunction with a field '.
+                            'formatter that outputs properly formatted and '.
+                            'encoded XML data.'),
+      );
+
+      if (empty($this->options['cdata_wrapper'])) {
+        $this->options['cdata_wrapper'] = array();
+      }
+
+      $form['cdata_wrapper'] = array(
+        '#type' => 'checkboxes',
+        '#title' => t('Fields value to wrapped using CDATA'),
+        '#options' => $options,
+        '#default_value' => $this->options['cdata_wrapper'],
+        '#description' => t('If checked the fields content will be wrapped using the CDATA tag.'),
+      );
+    }
+  }
+
+  /**
+   * Perform any necessary changes to the form values prior to storage.
+   * There is no need for this function to actually store the data.
+   *
+   * @param $form
+   * @param $form_state
+   */
+  function options_submit(&$form, &$form_state) {
+    if (isset($form_state['values']['style_options']['no_entity_encode'])) {
+      // Remove any options values set to 0
+      $form_state['values']['style_options']['no_entity_encode'] = array_filter($form_state['values']['style_options']['no_entity_encode']);
+    }
+    if (isset($form_state['values']['style_options']['cdata_wrapper'])) {
+      // Remove any options values set to 0
+      $form_state['values']['style_options']['cdata_wrapper'] = array_filter($form_state['values']['style_options']['cdata_wrapper']);
+    }
   }
 }

+ 78 - 41
sites/all/modules/contrib/views/views_data_export/theme/views_data_export.theme.inc

@@ -41,7 +41,7 @@ function theme_views_data_export_message($var) {
  */
 function theme_views_data_export_feed_icon($variables) {
   extract($variables, EXTR_SKIP);
-  $url_options = array('html' => true);
+  $url_options = array('html' => TRUE);
   if ($query) {
     $url_options['query'] = $query;
   }
@@ -58,7 +58,7 @@ function theme_views_data_export_feed_icon($variables) {
 function theme_views_data_export_complete_page($variables) {
   extract($variables, EXTR_SKIP);
   drupal_set_title(t('Data export successful'));
-  drupal_add_html_head(array('#tag' => 'meta', '#attributes' => array('http-equiv' =>"refresh", 'content' => '3;url='. $file)), 'views_data_export_download');
+  drupal_add_html_head(array('#tag' => 'meta', '#attributes' => array('http-equiv' =>"Refresh", 'content' => '3;url='. $file)), 'views_data_export_download');
   $output = '';
   $output .= '<p>';
   $output .= t('Your export has been created. View/download the file <a href="@link">here</a> (will automatically download in 3 seconds.)', array('@link' => $file));
@@ -105,21 +105,24 @@ function template_preprocess_views_data_export_csv_header(&$vars) {
 
   // Format header values.
   foreach ($vars['header'] as $key => $value) {
-    $output = decode_entities(strip_tags($value));
+    $output = decode_entities($value);
+    $output = (empty($vars['options']['keep_html'])) ? strip_tags($output) : $output;
     if (!empty($vars['options']['trim'])) {
       $output = trim($output);
     }
     if (!empty($vars['options']['encoding']) && function_exists('iconv')) {
-        switch($vars['options']['encoding']) {
-          case 'ASCII':
-            $converted = iconv("UTF-8", "ASCII//TRANSLIT", $output);
-            if ($converted !== FALSE) {
-              $output = $converted;
-            }
-            break;
-        }
+      switch($vars['options']['encoding']) {
+        case 'utf8_decode':
+          $converted = utf8_decode($output);
+          break;
+        default:
+          $converted = iconv("UTF-8", $vars['options']['encoding'], $output);
+          break;
+      }
+      if ($converted !== FALSE) {
+        $output = $converted;
       }
-      
+    }
     $vars['header'][$key] = $wrap . str_replace('"', $replace_value, $output) . $wrap;
   }
 }
@@ -148,19 +151,23 @@ function template_preprocess_views_data_export_csv_body(&$vars) {
   // Format row values.
   foreach ($vars['themed_rows'] as $i => $values) {
     foreach ($values as $j => $value) {
-      $output = decode_entities(strip_tags($value));
+      $output = decode_entities($value);
+      $output = (empty($vars['options']['keep_html'])) ? strip_tags($output) : $output;
       if (!empty($vars['options']['trim'])) {
         $output = trim($output);
       }
 
       if (!empty($vars['options']['encoding']) && function_exists('iconv')) {
         switch($vars['options']['encoding']) {
-          case 'ASCII':
-            $converted = iconv("UTF-8", "ASCII//TRANSLIT", $output);
-            if ($converted !== FALSE) {
-              $output = $converted;
-            }
+          case 'utf8_decode':
+            $converted = utf8_decode($output);
             break;
+          default:
+            $converted = iconv("UTF-8", $vars['options']['encoding'], $output);
+            break;
+        }
+        if ($converted !== FALSE) {
+          $output = $converted;
         }
       }
       if (!empty($vars['options']['replace_newlines'])) {
@@ -242,6 +249,8 @@ function template_preprocess_views_data_export_csv(&$vars) {
  */
 function template_preprocess_views_data_export_txt_body(&$vars) {
   _views_data_export_header_shared_preprocess($vars);
+  // We support not outputting fields when they are empty, so indicate so.
+  $vars['hide_empty_support'] = TRUE;
   _views_data_export_body_shared_preprocess($vars);
 }
 
@@ -346,24 +355,14 @@ function template_preprocess_views_data_export_msoffice_header(&$vars) {
  * Preprocess xml output template.
  */
 function template_preprocess_views_data_export_xml_header(&$vars) {
-  // Compute the root XML node, using the base table, and appending an 's' if needed.
-  $root_node = $vars['view']->base_table;
-  if (rtrim($root_node, 's') == $root_node) {
-    $root_node .= 's';
-  }
-  $vars['root_node'] = _views_data_export_xml_tag_clean($root_node);
+  $vars['root_node'] = _views_data_export_xml_tag_clean($vars['options']['root_node']);
 }
 
 /**
  * Preprocess xml output template.
  */
 function template_preprocess_views_data_export_xml_footer(&$vars) {
-  // Compute the root XML node, using the base table, and appending an 's' if needed.
-  $root_node = $vars['view']->base_table;
-  if (rtrim($root_node, 's') == $root_node) {
-    $root_node .= 's';
-  }
-  $vars['root_node'] = _views_data_export_xml_tag_clean($root_node);
+  $vars['root_node'] = _views_data_export_xml_tag_clean($vars['options']['root_node']);
 }
 
 /**
@@ -371,27 +370,50 @@ function template_preprocess_views_data_export_xml_footer(&$vars) {
  */
 function template_preprocess_views_data_export_xml_body(&$vars) {
   _views_data_export_header_shared_preprocess($vars);
+  // We support not outputting fields when they are empty, so indicate so.
+  $vars['hide_empty_support'] = TRUE;
   _views_data_export_body_shared_preprocess($vars);
 
-  // Compute the tag name based on the views base table, minus any trailing 's'.
-  $vars['item_node'] = _views_data_export_xml_tag_clean(rtrim($vars['view']->base_table, 's'));
+  $view = $vars['view'];
+  $style_options = $view->display_handler->get_option('style_options');
+
+  $no_encode = isset($style_options['no_entity_encode']) ? $style_options['no_entity_encode'] : array();
+
+  $cdata_wrapper = isset($style_options['cdata_wrapper']) ? $style_options['cdata_wrapper'] : array();
+
+  $vars['item_node'] = _views_data_export_xml_tag_clean($vars['options']['item_node']);
 
   foreach ($vars['themed_rows'] as $num => $row) {
     foreach ($row as $field => $content) {
-      // Prevent double encoding of the ampersand. Look for the entities produced by check_plain().
-      $content = preg_replace('/&(?!(amp|quot|#039|lt|gt);)/', '&amp;', $content);
-      // Convert < and > to HTML entities.
-      $content = str_replace(
-        array('<', '>'),
-        array('&lt;', '&gt;'),
-        $content);
+
+      // Perform xml entity encoding unless excluded by style options.
+      if (empty($no_encode[$field]) && empty($cdata_wrapper[$field])) {
+
+        // Prevent double encoding of the ampersand. Look for the entities produced by check_plain().
+        $content = preg_replace('/&(?!(amp|quot|#039|lt|gt);)/', '&amp;', $content);
+        // Convert < and > to HTML entities.
+        $content = str_replace(
+          array('<', '>'),
+          array('&lt;', '&gt;'),
+          $content);
+      }
+
+      // Perform wrapping the field data using the CDATA tag
+      // unless excluded by style options.
+      if (!empty($cdata_wrapper[$field])) {
+        // Escape CDATA end sequence only.
+        $content = '<![CDATA[' . str_replace(']]>', ']]]]><![CDATA[>', $content) . ']]>';
+      }
+
       $vars['themed_rows'][$num][$field] = $content;
     }
   }
 
   foreach ($vars['header'] as $field => $header) {
     // If there is no field label, use 'no name'.
-    $vars['xml_tag'][$field] = !empty($header) ? $header : 'no name';
+    if (empty($header)) {
+      $header = 'no name';
+    }
     if ($vars['options']['transform']) {
       switch ($vars['options']['transform_type']) {
         case 'dash':
@@ -438,6 +460,12 @@ function _views_data_export_xml_tag_clean($tag) {
   // Need to trim invalid characters from the start of the string:
   $tag = ltrim($tag, $invalid_start_chars);
 
+  // As a last line of defense, if we've stripped out everything, set it to
+  // something.
+  if (empty($tag)) {
+    $tag = 'invalid-tag-name';
+  }
+
   return $tag;
 }
 
@@ -463,6 +491,7 @@ function _views_data_export_header_shared_preprocess(&$vars) {
 function _views_data_export_body_shared_preprocess(&$vars) {
   $view     = $vars['view'];
   $fields   = &$view->field;
+  $hide_empty_support = !empty($vars['hide_empty_support']);
 
   $rows = $vars['rows'];
 
@@ -473,7 +502,15 @@ function _views_data_export_body_shared_preprocess(&$vars) {
 
     foreach ($keys as $id) {
       if (empty($fields[$id]->options['exclude'])) {
-        $vars['themed_rows'][$num][$id] = $view->style_plugin->rendered_fields[$num][$id];
+        $content = $view->style_plugin->rendered_fields[$num][$id];
+
+        if ($hide_empty_support && !empty($fields[$id]->options['hide_empty'])) {
+          if ($fields[$id]->is_value_empty($content, $fields[$id]->options['empty_zero'])) {
+            continue;
+          }
+        }
+
+        $vars['themed_rows'][$num][$id] = $content;
       }
     }
   }

+ 38 - 6
sites/all/modules/contrib/views/views_data_export/views_data_export.drush.inc

@@ -17,6 +17,7 @@ function views_data_export_drush_command() {
       'output_file' => 'The file to write the results to - will be overwritten if it already exists',
     ),
     'options' => array (
+      '--arguments' => 'Comma separated list of arguments to be passed to the view.',
       '--format' => 'csv,doc,txt,xls or xml. These options are ignored if the display_id passed is a "views_data_export" display.',
       '--separator' => 'csv only: What character separates the fields (default:,)',
       '--trim-whitespace' => 'csv only: Trim whitespace from either side of fields (default:1)',
@@ -111,7 +112,7 @@ function drush_views_data_export($view_name, $display_id, $output_file) {
     return;
   }
   $already_run = TRUE;
-  
+
   // Set the display to the one that we computed earlier.
   $display_id = drush_get_option('views_data_export_display_id', 'default');
 
@@ -158,11 +159,42 @@ function drush_views_data_export($view_name, $display_id, $output_file) {
   // We execute the view normally, and take advantage
   // of an alter function to interject later and batch it ourselves
 
-  $options = array (
-    'output_file' => realpath(drush_get_context('DRUSH_OLDCWD', getcwd())) . '/' . $output_file,
-  );
-  _drush_views_data_export_override_batch($view_name, $display_id, $options);
-  $view->execute_display($display_id);
+  $options = array();
+  // Let's see if the given $output_file is a absolute path.
+  if (strpos($output_file, '/') === 0) {
+    $options['output_file'] = $output_file;
+  }
+  else {
+    $options['output_file'] = realpath(drush_get_context('DRUSH_OLDCWD', getcwd())) . '/' . $output_file;
+  }
+
+
+  if ($view->display_handler->is_batched()) {
+    // This is a batched export, and needs to be handled as such.
+    _drush_views_data_export_override_batch($view_name, $display_id, $options);
+
+    $arguments = drush_get_option('arguments', '');
+    $arguments = explode(',', $arguments);
+    $view->execute_display($display_id, $arguments);
+  }
+  else {
+    // This export isn't batched.
+    ob_start();
+    $view->execute_display($display_id);
+    // Get the results, and clean the output buffer.
+    $result = ob_get_contents();
+    // Clean the buffer.
+    ob_end_clean();
+    // Save the results to file.
+    // Copy file over
+    if (file_put_contents($options['output_file'], $result)) {
+      drush_log("Data export saved to " . $options['output_file'], 'success');
+    }
+    else {
+      drush_set_error('VIEWS_DATA_EXPORT_COPY_ERROR', dt("The file could not be copied to the selected destination"));
+    }
+  }
+
 }
 
 

+ 10 - 25
sites/all/modules/contrib/views/views_data_export/views_data_export.info

@@ -4,40 +4,25 @@ description = "Plugin to export views data into various file formats"
 package = Views
 core = 7.x
 
-files[] = views_data_export.module
 dependencies[] = views
 
 ; Plugins
 files[] = plugins/views_data_export_plugin_display_export.inc
 files[] = plugins/views_data_export_plugin_style_export.inc
 files[] = plugins/views_data_export_plugin_style_export_csv.inc
-files[] = plugins/views_data_export_plugin_style_export_doc.inc
-files[] = plugins/views_data_export_plugin_style_export_txt.inc
-files[] = plugins/views_data_export_plugin_style_export_xls.inc
 files[] = plugins/views_data_export_plugin_style_export_xml.inc
 
-; Theme
-files[] = theme/views_data_export.theme.inc
-files[] = theme/views-data-export-csv-body.tpl.php
-files[] = theme/views-data-export-csv-footer.tpl.php
-files[] = theme/views-data-export-csv-header.tpl.php
-files[] = theme/views-data-export-doc-body.tpl.php
-files[] = theme/views-data-export-doc-footer.tpl.php
-files[] = theme/views-data-export-doc-header.tpl.php
-files[] = theme/views-data-export-txt-body.tpl.php
-files[] = theme/views-data-export-txt-footer.tpl.php
-files[] = theme/views-data-export-txt-header.tpl.php
-files[] = theme/views-data-export-xls-body.tpl.php
-files[] = theme/views-data-export-xls-footer.tpl.php
-files[] = theme/views-data-export-xls-header.tpl.php
-files[] = theme/views-data-export-xml-body.tpl.php
-files[] = theme/views-data-export-xml-footer.tpl.php
-files[] = theme/views-data-export-xml-header.tpl.php
-files[] = theme/views-data-export.tpl.php
+; Tests
+files[] = "tests/base.test"
+files[] = "tests/csv_export.test"
+files[] = "tests/doc_export.test"
+files[] = "tests/txt_export.test"
+files[] = "tests/xls_export.test"
+files[] = "tests/xml_export.test"
 
-; Information added by drupal.org packaging script on 2012-05-10
-version = "7.x-3.0-beta6"
+; Information added by Drupal.org packaging script on 2014-08-27
+version = "7.x-3.0-beta8"
 core = "7.x"
 project = "views_data_export"
-datestamp = "1336632688"
+datestamp = "1409118835"
 

+ 74 - 14
sites/all/modules/contrib/views/views_data_export/views_data_export.install

@@ -17,14 +17,14 @@ function views_data_export_schema() {
       ),
       'view_name' => array(
         'type' => 'varchar',
-        'length' => '32',
+        'length' => '128',
         'default' => '',
         'not null' => TRUE,
         'description' => 'The unique name of the view. This is the primary field views are loaded from, and is used so that views may be internal and not necessarily in the database. May only be alphanumeric characters plus underscores.',
       ),
       'view_display_id' => array(
         'type' => 'varchar',
-        'length' => '32',
+        'length' => '64',
         'default' => '',
         'not null' => TRUE,
         'description' => 'The unique name of the view. This is the primary field views are loaded from, and is used so that views may be internal and not necessarily in the database. May only be alphanumeric characters plus underscores.',
@@ -75,7 +75,7 @@ function views_data_export_schema() {
         'description' => 'The time this cache was created or updated.',
       ),
       'data' => array(
-        'type' => 'text',
+        'type' => 'blob',
         'size' => 'big',
         'description' => 'Serialized data being stored.',
         'serialize' => TRUE,
@@ -115,6 +115,47 @@ function views_data_export_update_7100() {
   db_add_field('views_data_export_object_cache', 'data', $new_field);
 }
 
+/**
+ * Increase the length of the view_name field to match views_schema_7301().
+ */
+function views_data_export_update_7300() {
+  $fields = array();
+
+  $fields['view_name'] = array(
+    'type' => 'varchar',
+    'length' => '128',
+    'default' => '',
+    'not null' => TRUE,
+    'description' => 'The unique name of the view. This is the primary field views are loaded from, and is used so that views may be internal and not necessarily in the database. May only be alphanumeric characters plus underscores.',
+  );
+
+  $fields['view_display_id'] = array(
+    'type' => 'varchar',
+    'length' => '64',
+    'default' => '',
+    'not null' => TRUE,
+    'description' => 'An identifier for this display; usually generated from the display_plugin, so should be something like page or page_1 or block_2, etc.',
+  );
+
+  // Apply the updates to the DB.
+  foreach ($fields as $field_name => $spec) {
+    db_change_field('views_data_export', $field_name, $field_name, $spec);
+  }
+}
+/**
+ * Change the object cache table to support postgres installations
+ */
+function views_data_export_update_7301(){
+  $spec = array(
+        'type' => 'blob',
+        'size' => 'big',
+        'description' => 'Serialized data being stored.',
+        'serialize' => TRUE,
+      );
+  db_change_field('views_data_export_object_cache', 'data', 'data', $spec);
+}
+
+
 /**
  * Implements hook_requirements().
  */
@@ -126,17 +167,36 @@ function views_data_export_requirements($phase) {
 
   switch ($phase) {
     case 'runtime':
-      // Check the max allowed packet size.
-      $max_allowed_packet = db_query('SHOW VARIABLES WHERE variable_name = :name', array(':name' => 'max_allowed_packet'))->fetchField(1);
-      if (is_numeric($max_allowed_packet)) {
-        if ($max_allowed_packet < (16 * 1024 * 1024)) {
-          $requirements['views_data_export'] = array(
-            'title' => $t('MySQL - max allowed packet'),
-            'value' => format_size($max_allowed_packet),
-            'description' => $t("Your MySQL 'max_allowed_packet' setting may be too low for Views data export to function correctly, Drupal's requirements recommend setting it to at least 16M. See: !link", array('!link' => l('http://drupal.org/requirements', 'http://drupal.org/requirements'))),
-            'severity' => REQUIREMENT_WARNING,
-          );
-        }
+
+      $requirements['views_data_export_temp'] = array(
+        'title' => t('Views Data Export temporary directory'),
+        'severity' => REQUIREMENT_OK,
+        'value' => t('Exists'),
+      );
+
+      $path = variable_get('views_data_export_directory', 'temporary://views_plugin_display');
+      if (!file_prepare_directory($path, FILE_CREATE_DIRECTORY)) {
+        $requirements['views_data_export_temp']['description'] = t('The Views Data Export temporary directory, %path could not be created due to a misconfigured directory. Please ensure that the temporary directory is correctly configured and that the webserver has permission to create directories.', array('%path' => file_uri_target($path)));
+        $requirements['views_data_export_temp']['severity'] = REQUIREMENT_ERROR;
+        $requirements['views_data_export_temp']['value'] = t('Unable to create');
+      }
+
+      $db_type = Database::getConnection()->databaseType();
+      switch ($db_type) {
+        case 'mysql':
+          // Check the max allowed packet size.
+          $max_allowed_packet = db_query('SHOW VARIABLES WHERE variable_name = :name', array(':name' => 'max_allowed_packet'))->fetchField(1);
+          if (is_numeric($max_allowed_packet)) {
+            if ($max_allowed_packet < (16 * 1024 * 1024)) {
+              $requirements['views_data_export'] = array(
+                'title' => $t('MySQL - max allowed packet'),
+                'value' => format_size($max_allowed_packet),
+                'description' => $t("Your MySQL 'max_allowed_packet' setting may be too low for Views data export to function correctly, Drupal's requirements recommend setting it to at least 16M. See: !link", array('!link' => l('http://drupal.org/requirements', 'http://drupal.org/requirements'))),
+                'severity' => REQUIREMENT_WARNING,
+              );
+            }
+          }
+          break;
       }
       break;
   }

+ 52 - 43
sites/all/modules/contrib/views/views_data_export/views_data_export.module

@@ -93,47 +93,49 @@ function views_data_export_cron() {
  *   garbage collect all exports.
  */
 function views_data_export_garbage_collect($expires = NULL, $chunk = NULL) {
+  if (lock_acquire('views_data_export_gc')) {
+    if (!isset($expires)) {
+      $expires = variable_get('views_data_export_gc_expires', 604800); // one week
+    }
+    if (!isset($chunk)) {
+      $chunk = variable_get('views_data_export_gc_chunk', 30);
+    }
 
-  if (!isset($expires)) {
-    $expires = variable_get('views_data_export_gc_expires', 604800); // one week
-  }
-  if (!isset($chunk)) {
-    $chunk = variable_get('views_data_export_gc_chunk', 30);
-  }
-
-  if ($chunk == -1) {
-    $result = db_query("SELECT eid FROM {views_data_export} WHERE time_stamp <= :timestamp ORDER BY time_stamp ASC", array(':timestamp' => REQUEST_TIME - $expires));
-  }
-  else {
-    $result = db_query_range("SELECT eid FROM {views_data_export} WHERE time_stamp <= :timestamp ORDER BY time_stamp ASC", 0, $chunk, array(':timestamp' => REQUEST_TIME - $expires));
-  }
+    if ($chunk == -1) {
+      $result = db_query("SELECT eid FROM {views_data_export} WHERE time_stamp <= :timestamp ORDER BY time_stamp ASC", array(':timestamp' => REQUEST_TIME - $expires));
+    }
+    else {
+      $result = db_query_range("SELECT eid FROM {views_data_export} WHERE time_stamp <= :timestamp ORDER BY time_stamp ASC", 0, $chunk, array(':timestamp' => REQUEST_TIME - $expires));
+    }
 
-  $eids_to_clear = array();
-  foreach ($result as $row) {
-    $eids_to_clear[] = $row->eid;
-  }
+    $eids_to_clear = array();
+    foreach ($result as $row) {
+      $eids_to_clear[] = $row->eid;
+    }
 
-  // We do two things to exports we want to garbage collect
-  // 1. Delete the index table for it, if it is still around
-  // 2. Delete the row from the exports table
-  // 3. Delete the view from the object_cache
-  if (count($eids_to_clear)) {
-    foreach ($eids_to_clear as $eid) {
-      // 1. Delete index table, if it is still around for some reason
-      $table = VIEWS_DATA_EXPORT_INDEX_TABLE_PREFIX . $eid;
-      if (db_table_exists($table)) {
-        db_drop_table($table);
+    // We do two things to exports we want to garbage collect
+    // 1. Delete the index table for it, if it is still around
+    // 2. Delete the row from the exports table
+    // 3. Delete the view from the object_cache
+    if (count($eids_to_clear)) {
+      foreach ($eids_to_clear as $eid) {
+        // 1. Delete index table, if it is still around for some reason
+        $table = VIEWS_DATA_EXPORT_INDEX_TABLE_PREFIX . $eid;
+        if (db_table_exists($table)) {
+          db_drop_table($table);
+        }
       }
-    }
 
-    // 2. Delete the entries in the exports table.
-    db_delete('views_data_export')
-      ->condition('eid', $eids_to_clear, 'IN')
-      ->execute();
+      // 2. Delete the entries in the exports table.
+      db_delete('views_data_export')
+        ->condition('eid', $eids_to_clear, 'IN')
+        ->execute();
 
-    // 3. Clear the cached views
-    views_data_export_view_clear($eids_to_clear);
+      // 3. Clear the cached views
+      views_data_export_view_clear($eids_to_clear);
+    }
 
+    lock_release('views_data_export_gc');
   }
 }
 
@@ -142,7 +144,7 @@ function views_data_export_garbage_collect($expires = NULL, $chunk = NULL) {
  * Batch API callback.
  * Handles all batching operations by executing the appropriate view.
  */
-function _views_data_export_batch_process($export_id, $display_id, &$context) {
+function _views_data_export_batch_process($export_id, $display_id, $exposed_input, &$context) {
   // Don't show the admin menu on batch page, some people don't like it.
   if (module_exists('admin_menu')) {
     module_invoke('admin_menu', 'suppress');
@@ -151,7 +153,9 @@ function _views_data_export_batch_process($export_id, $display_id, &$context) {
   // Fetch the view in question from our cache
   $view = views_data_export_view_retrieve($export_id);
   $view->set_display($display_id);
-
+  if (!empty($exposed_input)) {
+    $view->set_exposed_input($exposed_input);
+  }
   // Inform the data_export display which export it corresponds to and execute
   if (!isset($view->display_handler->batched_execution_state)) {
     $view->display_handler->batched_execution_state = new stdClass();
@@ -260,14 +264,19 @@ function views_data_export_view_retrieve($export_id) {
  *   An export ID or an array of export IDs to clear from the object cache.
  */
 function views_data_export_view_clear($export_id) {
-  if (is_array($export_id)) {
-    db_delete('views_data_export_object_cache')
-    ->condition('eid', $export_id, 'IN')
-    ->execute();
-  }
-  else {
-    db_delete('views_data_export_object_cache')
+  db_delete('views_data_export_object_cache')
     ->condition('eid', $export_id)
     ->execute();
+}
+
+/**
+ * Implements hook_file_presave().
+ */
+function views_data_export_file_presave($file) {
+  // Ensure temporary files really are temporary.
+  // @see: https://drupal.org/node/2198399
+  if (strpos($file->filename, 'views_data_export') === 0) {
+    // There is no FILE_STATUS_TEMPORARY.
+    $file->status = 0;
   }
 }