You are here

feeds_tamper_ui.admin.inc in Feeds Tamper 6

Same filename and directory in other branches
  1. 7 feeds_tamper_ui/feeds_tamper_ui.admin.inc

Forms and their accompanying validation and submit functions for Feeds Tamper UI.

File

feeds_tamper_ui/feeds_tamper_ui.admin.inc
View source
<?php

/**
 * @file
 * Forms and their accompanying validation and submit functions for Feeds Tamper
 * UI.
 */
function feeds_tamper_ui_list_form(&$form_state, $importer) {
  drupal_add_css(drupal_get_path('module', 'feeds_tamper_ui') . '/feeds_tamper_ui.css');
  $mappings = $importer->processor->config['mappings'];
  $sources = $importer->parser
    ->getMappingSources();
  $targets = $importer->processor
    ->getMappingTargets();
  $instances = feeds_tamper_load_by_importer($importer->id, TRUE);

  // Help message at the top. I have a seceret, I added the link back to the
  // mappings because it makes my life a lot easier while testing this.
  $link = l(t('mapping'), FEEDS_TAMPER_UI_FEEDS_BASE . '/edit/' . $importer->id . '/mapping');
  $message = 'Configure plugins to modify Feeds data before it gets saved. Each !mapping can be manipulated individually.';
  $message = t($message, array(
    '!mapping' => $link,
  ));
  $form['help']['#markup'] = '<div class="help"><p>' . $message . '</p></div>';
  $form['mappings'] = array();

  // Helpful shortcut.
  $map =& $form['mappings'];
  $form['#importer'] = $importer;
  foreach ($mappings as $mapping) {
    $source = $mapping['source'];
    $target = $mapping['target'];

    // We will skip building the table if it has been built for a source, but
    // we need to add the target label to indicate to the user that more than
    // one field will be affected.
    $target_label = !empty($targets[$target]['name']) ? check_plain($targets[$target]['name']) : check_plain($target);
    $map[$source]['#title']['targets'][] = $target_label;

    // We don't need to build the table again for this source.
    if (isset($map[$source]['table'])) {
      continue;
    }
    $source_label = !empty($sources[$source]['name']) ? check_plain($sources[$source]['name']) : check_plain($source);
    $map[$source]['#title']['source'] = $source_label;
    $map[$source]['#tree'] = TRUE;
    $map[$source]['table'] = array();

    // "Add plugin" link.
    $add = FEEDS_TAMPER_UI_BASE . '/add/' . $importer->id . '/' . bin2hex($source);
    $map[$source]['#add_link'] = l(t('Add plugin'), $add);

    // There are no plugins for this source. We've built all we need to.
    if (!isset($instances[$source])) {
      continue;
    }
    foreach ($instances[$source] as $instance) {

      // Plugin instance description.
      $description = !empty($instance->description) ? check_plain($instance->description) : $instance->id;
      $map[$source]['table'][$instance->id]['#description'] = $description;

      // Weight field.
      $map[$source]['table'][$instance->id]['weight'] = array(
        '#type' => 'textfield',
        '#size' => 5,
        '#default_value' => $instance->weight,
        '#attributes' => array(
          'class' => 'weight',
        ),
      );

      // Name of plugin.
      $plugin = feeds_tamper_get_plugin($instance->plugin_id);
      $map[$source]['table'][$instance->id]['#name'] = $plugin['name'];

      // Calculate where the plugin lives and it's corresponding operations.
      if ($instance->export_type == EXPORT_IN_CODE) {
        $status = t('Default');
        $edit = t('Override');
        $delete = '';
      }
      elseif ($instance->export_type == EXPORT_IN_DATABASE) {
        $status = t('Normal');
        $edit = t('Edit');
        $delete = t('Delete');
      }
      elseif ($instance->export_type == (EXPORT_IN_CODE | EXPORT_IN_DATABASE)) {
        $status = t('Overridden');
        $edit = t('Edit');
        $delete = t('Revert');
      }

      // Status column, Default, Normal, Overridden.
      $map[$source]['table'][$instance->id]['#status'] = $status;

      // Build Edit | Delete, Edit | Revert, Override links.
      $ops = l(t($edit), FEEDS_TAMPER_UI_BASE . '/edit/' . $instance->id);

      // Plugins provided in code can't be deleted but they can be reverted.
      if (!empty($delete)) {
        $ops .= ' | ';
        $ops .= l(t($delete), FEEDS_TAMPER_UI_BASE . '/delete/' . $instance->id);
      }
      $map[$source]['table'][$instance->id]['#edit'] = $ops;

      // Enable/disable checkbox.
      $map[$source]['table'][$instance->id]['enabled'] = array(
        '#type' => 'checkbox',
        '#default_value' => !$instance->disabled,
      );
    }
  }
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save'),
  );
  return $form;
}
function feeds_tamper_ui_list_form_validate($form, &$form_state) {
  $mappings = element_children($form['mappings']);
  foreach ($mappings as $i) {
    if (empty($form_state['values'][$i]['table'])) {
      continue;
    }
    foreach ($form_state['values'][$i]['table'] as $id => $value) {

      // I'm anal.
      $value['weight'] = (int) $value['weight'];

      // Someone would have to type this in manually, but that's not too far
      // of of a stretch.
      if ($value['weight'] < 0) {
        form_set_error($i . '][table][' . $id . '][weight', t('Weight must be greater than or equal to zero.'));
      }
    }
  }
}
function feeds_tamper_ui_list_form_submit($form, &$form_state) {
  $mappings = element_children($form['mappings']);
  foreach ($mappings as $i) {
    if (empty($form_state['values'][$i]['table'])) {
      continue;
    }
    foreach ($form_state['values'][$i]['table'] as $id => $value) {
      $instance = feeds_tamper_load_instance($id);
      $instance->disabled = !(bool) $value['enabled'];
      $instance->weight = $value['weight'];
      feeds_tamper_save_instance($instance);
    }
  }
  drupal_set_message(t('Your changes have been saved.'));
}
function theme_feeds_tamper_ui_list_form($form) {

  // Shortcut to save typing and screen space.
  $map =& $form['mappings'];
  $mappings = element_children($map);
  $header_normal = array(
    t('Description'),
    t('Weight'),
    t('Plugin'),
    t('Status'),
    t('Operations'),
    t('Enabled'),
  );

  // Remove weight column for empty tables. It looks nicer.
  $header_empty = $header_normal;
  unset($header_empty[1]);
  if (empty($mappings)) {

    // Can't use drupal_set_message here.
    $link = FEEDS_TAMPER_UI_FEEDS_BASE . '/edit/' . $form['#importer']->id . '/mapping';
    $link = l(t('mappings'), $link);
    $output = '<div class="messages warning">';
    $message = 'There are no !mappings defined for this importer.';
    $output .= t($message, array(
      '!mappings' => $link,
    ));
    $output .= '</div>';
    return $output;
  }
  foreach ($mappings as $key => $i) {
    $table_rows = $disabled_rows = array();

    // We used to use the source name in the table id, but it just needs to be
    // unique, so use the key to avoid problems.
    $table_id = 'feeds-tamper-' . $key . '-table';

    // Plugin instances for a particluar source.
    $instances = element_children($map[$i]['table']);
    if (empty($instances)) {
      $header = $header_empty;
      $help_text = t('No plugins defined.');
      $table_rows = array(
        'data' => array(
          array(
            'data' => $help_text,
            'colspan' => 5,
          ),
        ),
      );
    }
    else {
      $header = $header_normal;
      foreach ($instances as $id) {
        $enabled = !empty($map[$i]['table'][$id]['enabled']['#default_value']);

        // Assemble enabled plugin rows.
        if ($enabled) {
          $this_row = array();

          // Add description column.
          $this_row[] = $map[$i]['table'][$id]['#description'];

          // Add weight column, it will be hidden if javascript is enabled.
          $this_row[] = drupal_render($map[$i]['table'][$id]['weight']);

          // The name of the plugin, as defined in a PLUGIN.inc.
          $this_row[] = $map[$i]['table'][$id]['#name'];

          // One of Normal, Default, Overridden.
          $this_row[] = $map[$i]['table'][$id]['#status'];

          // Operations to perform on a plugin instance.
          $this_row[] = $map[$i]['table'][$id]['#edit'];

          // Enabled checkbox.
          $this_row[] = drupal_render($map[$i]['table'][$id]['enabled']);

          // Add draggable class for sortable table.
          $table_rows[] = array(
            'data' => $this_row,
            'class' => 'draggable',
          );
        }
        else {

          // Assemble disabled plugin rows.
          $this_row = array();

          // Add description column.
          $this_row[] = $map[$i]['table'][$id]['#description'];

          // Add weight column, it will be hidden if javascript is enabled.
          $this_row[] = drupal_render($map[$i]['table'][$id]['weight']);

          // The name of the plugin, as defined in a PLUGIN.inc.
          $this_row[] = $map[$i]['table'][$id]['#name'];

          // One of Normal, Default, Overridden.
          $this_row[] = $map[$i]['table'][$id]['#status'];

          // Operations to perform on a plugin instance. It's disabled, so make
          // it just text.
          $this_row[] = strip_tags($map[$i]['table'][$id]['#edit']);

          // Enabled checkbox.
          $this_row[] = drupal_render($map[$i]['table'][$id]['enabled']);

          // Add disabled class to differentiate.
          $disabled_rows[] = array(
            'data' => $this_row,
            'class' => 'disabled',
          );
        }
      }

      // Only add tabledrag if there were plugins for that source.
      drupal_add_tabledrag($table_id, 'order', 'sibling', 'weight');
    }

    // Combine enabled and disabled rows.
    $table_rows = array_merge($table_rows, $disabled_rows);

    // "Add plugin" link is the last row.
    $table_rows[] = array(
      'data' => array(
        array(
          'data' => $map[$i]['#add_link'],
          'colspan' => 7,
        ),
      ),
      'class' => 'feeds-tamper-add',
    );

    // Table caption, in the form of source_name -> target_name1, target_name2
    $caption = $map[$i]['#title']['source'] . ' -> ' . implode(', ', $map[$i]['#title']['targets']);
    $table = theme_table($header, $table_rows, array(
      'id' => $table_id,
    ), $caption);

    //$table['#attributes']['id'] = $table_id;

    //$table['#attached']['css'][] = drupal_get_path('module', 'feeds_tamper_ui') . '/feeds_tamper_ui.css';
    $map[$i]['table'] = array(
      '#value' => $table,
    );
    $map[$i]['#prefix'] = '<div class="feeds-tamper-table">';
    $map[$i]['#suffix'] = '</div>';
  }
  return drupal_render($form);
}
function feeds_tamper_ui_add_plugin_form(&$form_state, $importer, $source) {
  $source = rawurldecode($source);

  // Add css.
  drupal_add_css(drupal_get_path('module', 'feeds_tamper_ui') . '/feeds_tamper_ui.css');

  // Steal Feeds JS for machine_name goodness.
  drupal_add_js(drupal_get_path('module', 'feeds_ui') . '/feeds_ui.js');

  // Workaround some bug unserializing $_SESSION stuff. Most likely related to
  // ajax.
  // @todo Fix this properly.
  if (get_class($importer) == '__PHP_Incomplete_Class') {
    foreach ($importer as $key => $value) {
      if ($key == 'id') {
        $id = $value;
        break;
      }
    }
    $importer = feeds_importer($id);
  }

  // Set breadcrumb.
  $crumb = drupal_get_breadcrumb();
  $crumb[] = l(t('Tamper plugins: @importer', array(
    '@importer' => $importer->config['name'],
  )), FEEDS_TAMPER_UI_BASE . '/list/' . $importer->id);
  drupal_set_breadcrumb($crumb);

  // Set importer and source for use in validate and submit.
  $form_state['storage']['importer'] = $importer;
  $form_state['storage']['source'] = $source;

  // Build plugin select list.
  $feeds_tamper_plugins = feeds_tamper_get_plugins();
  $plugins = array();
  foreach ($feeds_tamper_plugins as $plugin_id => $plugin) {
    $plugins[t($plugin['category'])][$plugin_id] = t($plugin['name']);
  }
  ksort($plugins);
  foreach ($plugins as &$p) {
    asort($p);
  }
  $form = array();
  $machine_name = key(reset($plugins));
  if (!empty($form_state['values']['plugin_id'])) {
    $machine_name = $form_state['values']['plugin_id'];
  }
  $plugin = feeds_tamper_get_plugin($machine_name);
  $form['plugin_id'] = array(
    '#title' => t('The plugin to add'),
    '#type' => 'select',
    '#options' => $plugins,
    '#default_value' => $machine_name,
    '#ahah' => array(
      'path' => 'feeds_tamper/js',
      'wrapper' => 'plugin-wrapper',
    ),
  );
  $form['update'] = array(
    '#type' => 'submit',
    '#value' => t('Choose'),
    '#submit' => array(
      'feeds_tamper_ui_ajax_submit',
    ),
    '#attributes' => array(
      'class' => 'no-js',
    ),
    '#submit' => array(
      'feeds_tamper_ui_ajax_submit',
    ),
  );
  $form['plugin']['description'] = array(
    '#title' => t('Description'),
    '#type' => 'textfield',
    '#default_value' => !empty($plugin['default description']) ? t($plugin['default description']) : t($plugin['name']),
    '#required' => TRUE,
    '#description' => t('A useful description of what this plugin is doing.'),
    '#attributes' => array(
      'class' => 'feed-name',
    ),
  );
  $form['plugin']['id'] = array(
    '#title' => t('Machine name'),
    '#type' => 'textfield',
    '#default_value' => feeds_tamper_make_machine($form['plugin']['description']['#default_value']),
    '#maxlength' => 32,
    '#attributes' => array(
      'class' => 'feed-id',
    ),
    // For Feeds JS.
    '#required' => TRUE,
  );

  // Ajax wrapper.
  $form['plugin']['#prefix'] = '<div id="plugin-wrapper">';
  $form['plugin']['#suffix'] = '</div>';
  $form['plugin']['settings'] = array(
    '#title' => t('Configure @name', array(
      '@name' => $plugin['name'],
    )),
    '#type' => 'fieldset',
    '#tree' => TRUE,
  );
  $form['plugin']['settings'] += $plugin['form']($importer, $source, array());
  $form['add'] = array(
    '#type' => 'submit',
    '#value' => t('Add'),
  );
  return $form;
}
function feeds_tamper_ui_add_plugin_form_validate($form, &$form_state) {
  if ($form_state['clicked_button']['#value'] == t('Add')) {
    $plugin_id = $form_state['values']['plugin_id'];
    $plugin = feeds_tamper_get_plugin($plugin_id);
    if (!empty($plugin['validate']) && isset($form_state['values']['settings'])) {
      $plugin['validate']($form_state['values']['settings']);
    }
    $form_state['values']['id'] = $form_state['storage']['importer']->id . '-' . feeds_tamper_make_machine($form_state['storage']['source']) . '-' . $form_state['values']['id'];
    if (feeds_tamper_load_instance($form_state['values']['id'])) {
      form_set_error('id', t('Id is taken.'));
    }
  }
}
function feeds_tamper_ui_add_plugin_form_submit($form, &$form_state) {
  if ($form_state['clicked_button']['#value'] == t('Add')) {
    $obj = feeds_tamper_new_instance();
    $obj->plugin_id = $form_state['values']['plugin_id'];
    if (isset($form_state['values']['settings'])) {
      $obj->settings = $form_state['values']['settings'];
    }
    $obj->importer = $form_state['storage']['importer']->id;
    $obj->source = $form_state['storage']['source'];
    $obj->export_type = NULL;
    $obj->description = $form_state['values']['description'];
    $obj->id = $form_state['values']['id'];

    // Allow redirects.
    unset($form_state['storage']);
    feeds_tamper_save_instance($obj);
    $form_state['redirect'] = FEEDS_TAMPER_UI_BASE . '/list/' . $obj->importer;
    $source_name = feeds_tamper_ui_source_name($obj);
    drupal_set_message(t('Plugin %description was successfully added to %source.', array(
      '%description' => $obj->description,
      '%source' => $source_name,
    )));
  }
}
function feeds_tamper_ui_edit_plugin_form(&$form_state, $instance) {
  if (!$instance) {
    drupal_set_message(t('Invalid plugin id.'), 'error');
    return;
  }

  // Set breadcrumb.
  $importer = feeds_importer($instance->importer);
  $crumb = drupal_get_breadcrumb();
  $crumb[] = l(t('Tamper plugins: @importer', array(
    '@importer' => $importer->config['name'],
  )), FEEDS_TAMPER_UI_BASE . '/list/' . $importer->id);
  drupal_set_breadcrumb($crumb);
  $form_state['storage']['instance'] = $instance;
  $plugin = feeds_tamper_get_plugin($instance->plugin_id);
  $form = array();
  $form['#tree'] = TRUE;
  $form['description'] = array(
    '#title' => t('Description'),
    '#type' => 'textfield',
    '#description' => t('A useful description of what this plugin is doing.'),
    '#default_value' => $instance->description,
  );
  $form['settings'] = array(
    '#title' => t('Configure @plugin', array(
      '@plugin' => $plugin['name'],
    )),
    '#type' => 'fieldset',
    '#tree' => TRUE,
  );
  $form['settings'] += $plugin['form']($importer, $instance->source, $instance->settings);
  $form['save'] = array(
    '#type' => 'submit',
    '#value' => t('Save'),
  );
  return $form;
}
function feeds_tamper_ui_edit_plugin_form_validate($form, &$form_state) {
  $plugin_id = $form_state['storage']['instance']->plugin_id;
  $plugin = feeds_tamper_get_plugin($plugin_id);
  if (!empty($plugin['validate'])) {
    $plugin['validate']($form_state['values']['settings']);
  }
}
function feeds_tamper_ui_edit_plugin_form_submit($form, &$form_state) {
  $instance = $form_state['storage']['instance'];
  if (isset($form_state['values']['settings'])) {
    $instance->settings = $form_state['values']['settings'];
  }
  $instance->description = $form_state['values']['description'];
  feeds_tamper_save_instance($instance);
  unset($form_state['storage']);
  drupal_set_message(t('The plugin %plugin has been updated.', array(
    '%plugin' => $instance->description,
  )));
  $form_state['redirect'] = FEEDS_TAMPER_UI_BASE . '/list/' . $instance->importer;
}
function feeds_tamper_ui_delete_form(&$form_state, $instance) {
  if (!$instance) {
    drupal_set_message(t('Invalid plugin id.'), 'error');
    return;
  }
  $form = array();

  // Set breadcrumb.
  $importer = feeds_importer($instance->importer);
  $crumb = drupal_get_breadcrumb();
  $crumb[] = l(t('Tamper plugins: @importer', array(
    '@importer' => $importer->config['name'],
  )), FEEDS_TAMPER_UI_BASE . '/list/' . $importer->id);
  drupal_set_breadcrumb($crumb);
  $form_state['storage']['instance'] = $instance;
  if ($instance->export_type & EXPORT_IN_CODE) {
    $question = t('Would you really like to revert the plugin @instance?', array(
      '@instance' => $instance->description,
    ));
    $button_label = t('Revert');
  }
  else {
    $question = t('Would you really like to delete the plugin @instance?', array(
      '@instance' => $instance->description,
    ));
    $button_label = t('Delete');
  }
  return confirm_form($form, $question, FEEDS_TAMPER_UI_BASE . '/list/' . $instance->importer, NULL, $button_label);
}
function feeds_tamper_ui_delete_form_submit($form, &$form_state) {
  $instance = $form_state['storage']['instance'];
  feeds_tamper_delete_instance($instance);
  unset($form_state['storage']);
  $source_name = feeds_tamper_ui_source_name($instance);
  switch ($instance->export_type) {
    case EXPORT_IN_DATABASE:
      drupal_set_message(t('The plugin %plugin has been deleted from %source.', array(
        '%plugin' => $instance->description,
        '%source' => $source_name,
      )));
      break;
    case EXPORT_IN_CODE | EXPORT_IN_DATABASE:
      drupal_set_message(t('The plugin %plugin has been reverted.', array(
        '%plugin' => $instance->description,
      )));
      break;
  }
  $form_state['redirect'] = FEEDS_TAMPER_UI_BASE . '/list/' . $instance->importer;
}

/**
 * Ajax callback for add form.
 */
function feeds_tamper_ui_js() {
  $form_state = array(
    'storage' => NULL,
    'submitted' => FALSE,
  );
  $form_build_id = $_POST['form_build_id'];
  $form = form_get_cache($form_build_id, $form_state);
  $args = $form['#parameters'];
  $form_id = array_shift($args);
  $form_state['post'] = $form['#post'] = $_POST;
  $form['#programmed'] = $form['#redirect'] = FALSE;
  $form_state['submitted'] = TRUE;
  if (!isset($_POST['op'])) {
    $form['#validate'] = array();
    $form['#submit'] = array();
  }
  drupal_process_form($form_id, $form, $form_state);
  $form = drupal_rebuild_form($form_id, $form_state, $args, $form_build_id);
  $plugin_form = $form['plugin'];
  unset($plugin_form['#prefix'], $plugin_form['#suffix']);

  // Prevent duplicate wrappers.
  $javascript = drupal_add_js(NULL, NULL, 'header');
  $settings = call_user_func_array('array_merge_recursive', $javascript['setting']);
  drupal_json(array(
    'status' => TRUE,
    'data' => theme('status_messages') . drupal_render($plugin_form),
    'settings' => $settings,
  ));
}
function feeds_tamper_ui_ajax_submit($form, &$form_state) {
  $form_state['rebuild'] = TRUE;
}