From bf4e135324847da634e90d29806b6f0045ca2ec3 Mon Sep 17 00:00:00 2001
From: hanoii <hanoii@23157.no-reply.drupal.org>
Date: Sun, 13 Jul 2014 17:42:06 -0700
Subject: [PATCH] Issue #2224643 by hanoii, MegaChriz: Added Support for input
 format configuration on a per-field basis .

---
 feeds.info                            |   1 +
 mappers/text.inc                      |  70 +++++++-
 plugins/FeedsProcessor.inc            |   2 +-
 plugins/FeedsTermProcessor.inc        |  26 ++-
 tests/feeds_mapper.test               |   3 +
 tests/feeds_mapper_format_config.test | 244 ++++++++++++++++++++++++++
 6 files changed, 338 insertions(+), 8 deletions(-)
 create mode 100644 tests/feeds_mapper_format_config.test

diff --git a/feeds.info b/feeds.info
index ec2ffda1..eb7387b0 100644
--- a/feeds.info
+++ b/feeds.info
@@ -41,6 +41,7 @@ files[] = tests/feeds_mapper_profile.test
 files[] = tests/feeds_mapper.test
 files[] = tests/feeds_mapper_config.test
 files[] = tests/feeds_fetcher_file.test
+files[] = tests/feeds_mapper_format_config.test
 files[] = tests/feeds_fetcher_http.test
 files[] = tests/feeds_processor_entity.test
 files[] = tests/feeds_processor_node.test
diff --git a/mappers/text.inc b/mappers/text.inc
index 48d9d7f8..235aea3a 100644
--- a/mappers/text.inc
+++ b/mappers/text.inc
@@ -36,17 +36,26 @@ function text_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_nam
         );
       }
     }
+
+    if (!empty($instance['settings']['text_processing'])) {
+      $targets[$name]['summary_callback'] = 'text_feeds_summary_callback';
+      $targets[$name]['form_callback'] = 'text_feeds_form_callback';
+    }
   }
 }
 
 /**
  * Callback for mapping text fields.
  */
-function text_feeds_set_target($source, $entity, $target, array $values) {
+function text_feeds_set_target(FeedsSource $source, $entity, $target, array $values, array $mapping = array()) {
   list($field_name, $column) = explode(':', $target . ':value');
 
   if ($column === 'value' && isset($source->importer->processor->config['input_format'])) {
     $format = $source->importer->processor->config['input_format'];
+    // Add in default values.
+    $mapping += array(
+      'format' => $format,
+    );
   }
 
   $field = isset($entity->$field_name) ? $entity->$field_name : array('und' => array());
@@ -63,8 +72,8 @@ function text_feeds_set_target($source, $entity, $target, array $values) {
 
       $field['und'][$delta][$column] = (string) $value;
 
-      if (isset($format)) {
-        $field['und'][$delta]['format'] = $format;
+      if (isset($mapping['format'])) {
+        $field['und'][$delta]['format'] = $mapping['format'];
       }
     }
 
@@ -73,3 +82,58 @@ function text_feeds_set_target($source, $entity, $target, array $values) {
 
   $entity->$field_name = $field;
 }
+
+/**
+ * Summary callback for text field targets.
+ *
+ * Displays which text format will be used for the text field target.
+ *
+ * @see text_feeds_processor_targets_alter()
+ * @see text_feeds_form_callback()
+ */
+function text_feeds_summary_callback(array $mapping, $target, array $form, array $form_state) {
+  global $user;
+  $formats = filter_formats($user);
+
+  // Processor-wide input format setting.
+  $importer = feeds_importer($form['#importer']);
+  $default_format = !empty($importer->processor->config['input_format']) ? $importer->processor->config['input_format'] : filter_fallback_format();
+  $mapping += array(
+    'format' => $default_format,
+  );
+
+  return t('Text format: %format', array('%format' => $formats[$mapping['format']]->name));
+}
+
+/**
+ * Form callback for text field targets.
+ *
+ * Allows to select a text format for the text field target.
+ *
+ * @see text_feeds_processor_targets_alter()
+ * @see text_feeds_summary_callback()
+ */
+function text_feeds_form_callback(array $mapping, $target, array $form, array $form_state) {
+  global $user;
+  $formats_options = array();
+  $formats = filter_formats($user);
+  foreach ($formats as $id => $format) {
+    $formats_options[$id] = $format->name;
+  }
+
+  // Processor-wide text format setting.
+  $importer = feeds_importer($form['#importer']);
+  $default_format = !empty($importer->processor->config['input_format']) ? $importer->processor->config['input_format'] : filter_fallback_format();
+  $mapping += array(
+    'format' => $default_format,
+  );
+
+  return array(
+    'format' => array(
+      '#type' => 'select',
+      '#title' => t('Text format'),
+      '#options' => $formats_options,
+      '#default_value' => $mapping['format'],
+    ),
+  );
+}
diff --git a/plugins/FeedsProcessor.inc b/plugins/FeedsProcessor.inc
index 66662769..833cd2c2 100755
--- a/plugins/FeedsProcessor.inc
+++ b/plugins/FeedsProcessor.inc
@@ -663,7 +663,7 @@ abstract class FeedsProcessor extends FeedsPlugin {
     $form['input_format'] = array(
       '#type' => 'select',
       '#title' => t('Text format'),
-      '#description' => t('Select the input format for the body field of the nodes to be created.'),
+      '#description' => t('Select the default input format for the text fields of the nodes to be created.'),
       '#options' => $format_options,
       '#default_value' => isset($this->config['input_format']) ? $this->config['input_format'] : 'plain_text',
       '#required' => TRUE,
diff --git a/plugins/FeedsTermProcessor.inc b/plugins/FeedsTermProcessor.inc
index b336096b..9b0024e7 100644
--- a/plugins/FeedsTermProcessor.inc
+++ b/plugins/FeedsTermProcessor.inc
@@ -34,7 +34,6 @@ class FeedsTermProcessor extends FeedsProcessor {
     $term = new stdClass();
     $term->vid = $vocabulary->vid;
     $term->vocabulary_machine_name = $vocabulary->machine_name;
-    $term->format = isset($this->config['input_format']) ? $this->config['input_format'] : filter_fallback_format();
     return $term;
   }
 
@@ -84,9 +83,11 @@ class FeedsTermProcessor extends FeedsProcessor {
   }
 
   /**
-   * Override setTargetElement to operate on a target item that is a taxonomy term.
+   * Overrides parent::setTargetElement().
+   *
+   * Operate on a target item that is a taxonomy term.
    */
-  public function setTargetElement(FeedsSource $source, $target_term, $target_element, $value) {
+  public function setTargetElement(FeedsSource $source, $target_term, $target_element, $value, array $mapping = array()) {
     switch ($target_element) {
       case 'parent':
         if (!empty($value)) {
@@ -108,6 +109,7 @@ class FeedsTermProcessor extends FeedsProcessor {
           $target_term->parent[] = 0;
         }
         break;
+
       case 'parentguid':
         // value is parent_guid field value
         $query = db_select('feeds_item')
@@ -115,8 +117,8 @@ class FeedsTermProcessor extends FeedsProcessor {
           ->condition('entity_type', $this->entityType());
         $parent_tid = $query->condition('guid', $value)->execute()->fetchField();
         $target_term->parent[] = ($parent_tid) ? $parent_tid : 0;
-
         break;
+
       case 'weight':
         if (!empty($value)) {
           $weight = intval($value);
@@ -126,6 +128,20 @@ class FeedsTermProcessor extends FeedsProcessor {
         }
         $target_term->weight = $weight;
         break;
+
+      case 'description':
+        if (!empty($mapping['format'])) {
+          $target_term->format = $mapping['format'];
+        }
+        elseif (!empty($this->config['input_format'])) {
+          $target_term->format = $this->config['input_format'];
+        }
+        else {
+          $target_term->format = filter_fallback_format();
+        }
+        $target_term->description = $value;
+        break;
+
       default:
         parent::setTargetElement($source, $target_term, $target_element, $value);
         break;
@@ -161,6 +177,8 @@ class FeedsTermProcessor extends FeedsProcessor {
       'description' => array(
         'name' => t('Term description'),
         'description' => t('Description of the taxonomy term.'),
+        'summary_callback' => 'text_feeds_summary_callback',
+        'form_callback' => 'text_feeds_form_callback',
       ),
     );
 
diff --git a/tests/feeds_mapper.test b/tests/feeds_mapper.test
index 81665b63..492af896 100644
--- a/tests/feeds_mapper.test
+++ b/tests/feeds_mapper.test
@@ -22,10 +22,13 @@ class FeedsMapperTestCase extends FeedsWebTestCase {
     'file' => 'file_generic',
     'image' => 'image_image',
     'link_field' => 'link_field',
+    'list_text' => 'options_select',
     'number_float' => 'number',
     'number_integer' => 'number',
     'nodereference' => 'nodereference_select',
     'text' => 'text_textfield',
+    'text_long' => 'text_textarea',
+    'text_with_summary' => 'text_textarea_with_summary',
     'userreference' => 'userreference_select',
    );
 
diff --git a/tests/feeds_mapper_format_config.test b/tests/feeds_mapper_format_config.test
new file mode 100644
index 00000000..92fa241a
--- /dev/null
+++ b/tests/feeds_mapper_format_config.test
@@ -0,0 +1,244 @@
+<?php
+
+/**
+ * @file
+ * Contains FeedsMapperFormatConfig.
+ */
+
+/**
+ * Class for testing "Text format" mapping configuration on text fields.
+ */
+class FeedsMapperFormatConfig extends FeedsMapperTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Mapper: Text format mapping configuration',
+      'description' => 'Test text format mapping configuration for text fields.',
+      'group' => 'Feeds',
+    );
+  }
+
+  public function setUp() {
+    parent::setUp(array('list', 'taxonomy'));
+  }
+
+  /**
+   * Basic test for setting mapping configuration.
+   */
+  public function test() {
+    // Create content type with three fields. Two that support text formats
+    // and one that doesn't.
+    $typename = $this->createContentType(array(), array(
+      'alpha' => array(
+        'type' => 'text',
+        'instance_settings' => array(
+          'instance[settings][text_processing]' => 1,
+        ),
+      ),
+      'beta' => array(
+        'type' => 'text_long',
+        'instance_settings' => array(
+          'instance[settings][text_processing]' => 1,
+        ),
+      ),
+      'gamma' => array(
+        'type' => 'text',
+        'instance_settings' => array(
+          'instance[settings][text_processing]' => 0,
+        ),
+      ),
+    ));
+
+    // Create a new filter format.
+    $format = drupal_strtolower($this->randomName());
+    $edit = array(
+      'format' => $format,
+      'name' => $this->randomName(),
+      // Authenticated users.
+      'roles[2]' => TRUE,
+    );
+    $this->drupalPost('admin/config/content/formats/add', $edit, t('Save configuration'));
+
+    // Create and configure importer.
+    $this->createImporterConfiguration();
+    $this->setSettings('syndication', NULL, array('content_type' => ''));
+
+    $this->setPlugin('syndication', 'FeedsFileFetcher');
+    $this->setPlugin('syndication', 'FeedsCSVParser');
+    $this->setSettings('syndication', 'FeedsNodeProcessor', array('bundle' => $typename));
+
+    $this->addMappings('syndication', array(
+      0 => array(
+        'source' => 'title',
+        'target' => 'title',
+      ),
+      1 => array(
+        'source' => 'created',
+        'target' => 'created',
+      ),
+      2 => array(
+        'source' => 'body',
+        'target' => 'body',
+        'format' => $format,
+      ),
+      3 => array(
+        'source' => 'alpha',
+        'target' => 'field_alpha',
+        'format' => $format,
+      ),
+      4 => array(
+        'source' => 'beta',
+        'target' => 'field_beta',
+        'format' => $format,
+      ),
+      5 => array(
+        'source' => 'gamma',
+        'target' => 'field_gamma',
+      ),
+    ));
+    // Assert that for the gamma field no format can be chosen.
+    $this->assertNoText('Text format: Plain text');
+
+    // Import csv file.
+    $this->importFile('syndication', $this->absolutePath() . '/tests/feeds/content.csv');
+    $this->assertText('Created 2 nodes');
+
+    // Assert that fields body, alpha and beta got the expected text format.
+    $node = node_load(1);
+    $this->assertEqual($format, $node->body[LANGUAGE_NONE][0]['format'], 'The body field got the expected format.');
+    $this->assertEqual($format, $node->field_alpha[LANGUAGE_NONE][0]['format'], 'The alpha field got the expected format.');
+    $this->assertEqual($format, $node->field_beta[LANGUAGE_NONE][0]['format'], 'The beta field got the expected format.');
+    $this->assertEqual(filter_fallback_format(), $node->field_gamma[LANGUAGE_NONE][0]['format'], 'The gama field got the expected format.');
+  }
+
+  /**
+   * Tests the filter formats a user has access to.
+   */
+  public function testWithLimitedPrivileges() {
+    // Create content type with a field that uses a text format.
+    $typename = $this->createContentType(array(), array(
+      'alpha' => array(
+        'type' => 'text',
+        'instance_settings' => array(
+          'instance[settings][text_processing]' => 1,
+        ),
+      ),
+    ));
+
+    // Create a new user with limited privileges.
+    $account = $this->drupalCreateUser(array('administer feeds'));
+
+    // Create filter format the user may use.
+    $format1 = drupal_strtolower($this->randomName());
+    $edit1 = array(
+      'format' => $format1,
+      'name' => $this->randomName(),
+      // Authenticated users.
+      'roles[2]' => TRUE,
+    );
+    $this->drupalPost('admin/config/content/formats/add', $edit1, t('Save configuration'));
+
+    // Create filter format the user may NOT use.
+    $rid = $this->drupalCreateRole(array());
+    $format2 = drupal_strtolower($this->randomName());
+    $edit2 = array(
+      'format' => $format2,
+      'name' => $this->randomName(),
+      'roles[' . $rid . ']' => TRUE,
+    );
+    $this->drupalPost('admin/config/content/formats/add', $edit2, t('Save configuration'));
+
+    // Login as the user that may only use certain formats.
+    $this->drupalLogin($account);
+
+    // Create importer and ensure the user can use the first format.
+    $this->createImporterConfiguration();
+    $this->setSettings('syndication', NULL, array(
+      'content_type' => '',
+      'import_period' => FEEDS_SCHEDULE_NEVER,
+    ));
+    $this->setPlugin('syndication', 'FeedsFileFetcher');
+    $this->setPlugin('syndication', 'FeedsCSVParser');
+    $this->setSettings('syndication', 'FeedsNodeProcessor', array('bundle' => $typename));
+    $this->addMappings('syndication', array(
+      0 => array(
+        'source' => 'alpha',
+        'target' => 'field_alpha',
+        'format' => $format1,
+      ),
+    ));
+
+    // Check user can choose first, but not second format as an option.
+    $this->drupalPostAJAX(NULL, array(), 'mapping_settings_edit_0');
+    $xpath = $this->constructFieldXpath('name', 'config[0][settings][format]');
+    $fields = $this->xpath($xpath);
+    $field = reset($fields);
+    $format_options = $this->getAllOptions($field);
+    $format1_found = FALSE;
+    $format2_found = FALSE;
+    foreach ($format_options as $option) {
+      if ($option['value'] == $format1) {
+        $format1_found = TRUE;
+      }
+      if ($option['value'] == $format2) {
+        $format2_found = TRUE;
+      }
+    }
+    // Assert first format can be chosen.
+    $this->assertTrue($format1_found, format_string('Text format %format can be chosen.', array('%format' => $format1)));
+    // Assert second format can NOT be chosen.
+    $this->assertFalse($format2_found, format_string('Text format %format can NOT be chosen.', array('%format' => $format2)));
+  }
+
+  /**
+   * Tests if text format can be set for taxonomy descriptions.
+   */
+  public function testTaxonomyDescriptionTextFormat() {
+    // Create a vocabulary.
+    $edit = array(
+      'name' => 'Tags',
+      'machine_name' => 'tags',
+    );
+    $this->drupalPost('admin/structure/taxonomy/add', $edit, 'Save');
+
+    // Create a new filter format.
+    $format = drupal_strtolower($this->randomName());
+    $edit = array(
+      'format' => $format,
+      'name' => $this->randomName(),
+      // Authenticated users.
+      'roles[2]' => TRUE,
+    );
+    $this->drupalPost('admin/config/content/formats/add', $edit, t('Save configuration'));
+
+    // Create a taxonomy term importer.
+    $this->createImporterConfiguration();
+    $this->setSettings('syndication', NULL, array(
+      'content_type' => '',
+      'import_period' => FEEDS_SCHEDULE_NEVER,
+    ));
+    $this->setPlugin('syndication', 'FeedsFileFetcher');
+    $this->setPlugin('syndication', 'FeedsCSVParser');
+    $this->setPlugin('syndication', 'FeedsTermProcessor');
+    $this->setSettings('syndication', 'FeedsTermProcessor', array('bundle' => 'tags'));
+    $this->addMappings('syndication', array(
+      0 => array(
+        'source' => 'title',
+        'target' => 'name',
+      ),
+      1 => array(
+        'source' => 'body',
+        'target' => 'description',
+        'format' => $format,
+      ),
+    ));
+
+    // Import csv file.
+    $this->importFile('syndication', $this->absolutePath() . '/tests/feeds/content.csv');
+    $this->assertText('Created 2 terms');
+
+    // Assert that the term description got the expected text format.
+    $term = taxonomy_term_load(1);
+    $this->assertEqual($format, $term->format, 'The taxonomy term got the expected format.');
+  }
+
+}
-- 
GitLab