You are here

WebformSubmissionValue.php in Pardot Integration 2.x

File

src/Plugin/PardotFormMapFormatterPlugin/WebformSubmissionValue.php
View source
<?php

namespace Drupal\pardot\Plugin\PardotFormMapFormatterPlugin;

use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Form\FormStateInterface;
use Drupal\pardot\Plugin\PardotFormMapFormatterPluginBase;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\pardot\PluginSubFormHelpers;
use Drupal\webform\WebformSubmissionInterface;
use Drupal\webform_ui\Form\WebformUiElementAddForm;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Form\FormState;

/**
 * Plugin to generate a text field and consume tokens for mappings.
 *
 * @PardotFormMapFormatterPlugin(
 *  id = "webform_submission_value",
 *  label = @Translation("Submission Value"),
 *  types = {
 *     "webform",
 *   }
 * )
 */
class WebformSubmissionValue extends PardotFormMapFormatterPluginBase implements ContainerFactoryPluginInterface {

  /**
   * Entity field manager to get the contact form field definitions.
   *
   * @var \Drupal\Core\Entity\EntityTypeManager
   */
  protected $entityTypeManager;

  /**
   * The webform element manager.
   *
   * @var \Drupal\webform\Plugin\WebformElementManagerInterface
   */
  protected $pluginManagerWebformElement;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    $instance = new static($configuration, $plugin_id, $plugin_definition);
    $instance->entityTypeManager = $container
      ->get('entity_type.manager');
    $instance->pluginManagerWebformElement = $container
      ->get('plugin.manager.webform.element');
    return $instance;
  }

  /**
   * {@inheritdoc}
   */
  public function getPluginId() {
    return 'webform_submission_value';
  }

  /**
   * {@inheritdoc}
   */
  public function getPluginDefinition() {
    return $this->pluginDefinition;
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return [
      'element' => '',
      'single_format' => 'value',
      'multiple_format' => 'comma',
      'hash' => rand(),
      'disallowed_field_types' => [
        'webform_actions',
      ],
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
    $elements = $this
      ->getWebformElements();
    $wrapper_hash = $this->configuration['hash'];
    $element_type = $this->configuration['element'] ?? '';
    if ($form_state
      ->get("element_type__{$wrapper_hash}")) {
      $element_type_state = $form_state
        ->get("element_type__{$wrapper_hash}");
    }
    else {
      $element_type_state = $element_type;
    }
    $form['settings_container'] = [
      '#type' => 'container',
      '#prefix' => "<div id='webform_submission_value_wrapper__{$wrapper_hash}'>",
      '#suffix' => '</div>',
    ];
    $form['settings_container']['element'] = [
      '#type' => 'select',
      '#title' => 'Element',
      '#default_value' => $element_type_state,
      '#options' => $this
        ->getElementCollection(),
      '#required' => TRUE,
      '#ajax' => [
        'event' => 'change',
        'callback' => [
          $this,
          'updateFieldMap',
        ],
        'wrapper' => "webform_submission_value_wrapper__{$wrapper_hash}",
        'trigger_as' => [
          'name' => "element_type_select__{$wrapper_hash}",
        ],
      ],
    ];
    $form['settings_container']['element_type_select'] = [
      '#submit' => [
        [
          $this,
          'pluginTypeChangeSubmit',
        ],
      ],
      '#type' => 'submit',
      '#attributes' => [
        'class' => [
          'visually-hidden',
        ],
      ],
      '#wrapper_hash' => $wrapper_hash,
      '#ajax' => [
        'callback' => [
          $this,
          'ajaxChangeFieldMap',
        ],
        'wrapper' => "webform_submission_value_wrapper__{$wrapper_hash}",
        'effect' => 'fade',
      ],
      '#limit_validation_errors' => [],
      '#name' => "element_type_select__{$wrapper_hash}",
    ];
    if ($element_type_state && $element_type_state !== 'none') {

      // Get the Webform object.

      /** @var \Drupal\webform\Plugin\WebformElementManager $webform_element_manager */
      $webform_element_manager = $this->pluginManagerWebformElement;
      $webform = $this
        ->getWebform();

      // Get element instance and build a fresh form.
      $plugin = $webform_element_manager
        ->getElementInstance($elements[$element_type_state], $webform);
      $plugin_form_base = WebformUiElementAddForm::create(\Drupal::getContainer());

      // No idea why but you need this line but don't remove it.
      $plugin_form_base
        ->buildForm([], $form_state, $webform, $element_type_state);
      $new_form_state = new FormState();
      $new_form_state
        ->set('element', $elements[$element_type_state]);
      $new_form_state
        ->setFormObject($plugin_form_base);

      // Build the form.
      $plugin_form = PluginSubFormHelpers::buildPluginForm($plugin, $form, $new_form_state, [
        'plugin',
      ]);

      // Remove unwanted items from the elements formatting options.
      unset($plugin_form['display']['format_attributes']);
      unset($plugin_form['display']['item']['format']['#options']['custom']);
      unset($plugin_form['display']['items']['format_items']['#options']['custom']);
      unset($plugin_form['display']['items']['format_items']['#options']['ol']);
      unset($plugin_form['display']['items']['format_items']['#options']['ul']);

      // Set the formatter options to the form.
      $form['settings_container']['format'] = [
        '#type' => 'select',
        '#title' => 'Single Format',
        '#default_value' => $this->configuration['properties']['format'],
        '#options' => $plugin_form['display']['item']['format']['#options'] ?? [],
      ];
      $form['settings_container']['format_items'] = [
        '#type' => 'select',
        '#title' => 'Multiple Format',
        '#default_value' => $this->configuration['properties']['format_items'],
        '#options' => $plugin_form['display']['items']['format_items']['#options'] ?? [],
      ];
    }
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
    $values = $form_state
      ->getValues();
    $container = $values['settings_container'];
    $this->configuration['element'] = $container['element'];
    $this->configuration['properties']['format'] = $container['format'] ?? '';
    $this->configuration['properties']['format_items'] = $container['format_items'] ?? '';
  }

  /**
   * Get the list of elements to map with.
   *
   * @return array|mixed|null
   *   Just return the mapped field container.
   */
  public function getElementCollection() {
    $fields = [];
    $disallowed_types = $this->configuration['disallowed_field_types'] ?? [];
    $elements = $this
      ->getWebformElements();
    foreach ($elements as $id => $element) {
      if ($disallowed_types && !in_array($element['#type'], $disallowed_types)) {
        $fields[$id] = (string) $element['#title'];
      }
      elseif (!$disallowed_types) {
        $fields[$id] = (string) $element['#title'];
      }
    }
    $fields = [
      'none' => 'None',
    ] + $fields;
    return $fields;
  }

  /**
   * Get the list of elements.
   *
   * @return array
   *   Return the list of Elements.
   */
  public function getWebformElements() {
    $webform = $this
      ->getWebform();
    if ($webform) {
      return $this
        ->getWebform()
        ->getElementsDecodedAndFlattened();
    }
    return [];
  }

  /**
   * Get Webform.
   *
   * @return null|\Drupal\webform\Entity\Webform
   *   Return the webform object.
   */
  public function getWebform() {
    $entity_id = explode(':', $this->configuration['entity_id'])[1] ?? '';

    /** @var \Drupal\webform\Entity\Webform $webform */
    return $this->entityTypeManager
      ->getStorage('webform')
      ->load($entity_id);
  }

  /**
   * Get the form field from the form state and apply formatting.
   *
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state object.
   *
   * @return mixed
   *   The formatted value or null i guess.
   */
  public function getFormattedValue(FormStateInterface $form_state) {

    // Grab formatting selections and the element.
    $options = $this->configuration['properties'];
    $element = $this->configuration['element'];

    // Get the Webform Submission from the form state.

    /** @var \Drupal\webform\WebformSubmissionInterface $webform_submission */
    $webform_submission = $form_state
      ->getFormObject()
      ->getEntity();

    // Also grab the Webform.
    $webform = $webform_submission
      ->getWebform();
    $webform_element_manager = $this->pluginManagerWebformElement;

    // Get all the elements of the webform.
    $elements = $webform
      ->getElementsDecodedAndFlattened();

    // Get the plugin instance of the element from the webform.
    $element_plugin = $webform_element_manager
      ->getElementInstance($elements[$element], $webform);
    $webform_options['webform_key'] = $element;
    $element = $elements[$element];

    // Swap out the chosen options from the webform configuration with the settings from this plugin.
    $element['#format'] = $options['format'];
    $element['#format_items'] = $options['format_items'];

    // Get the value with the built in formatText method from the WebformElement plugin.
    return $element_plugin
      ->formatText($element, $webform_submission, $webform_options);
  }

  /**
   * This is used to update the dom of the table container when changing a row plugin.
   *
   * @param array $form
   *   The form array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state object.
   *
   * @return array|mixed|null
   *   Just return the mapped field container.
   */
  public function ajaxChangeFieldMap(array &$form, FormStateInterface $form_state) {
    $trigger_element = $form_state
      ->getTriggeringElement();
    $parents = array_slice($trigger_element['#array_parents'], 0, -1);
    return NestedArray::getValue($form, $parents);
  }

  /**
   * Set the mapping array on change.
   *
   * @param array $form
   *   The form array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state object.
   */
  public function pluginTypeChangeSubmit(array &$form, FormStateInterface $form_state) {
    $trigger_element = $form_state
      ->getTriggeringElement();
    $parents = array_slice($trigger_element['#array_parents'], 0, -1);
    $parents[] = 'element';
    $wrapper_hash = $trigger_element['#wrapper_hash'];
    $plugin_type = NestedArray::getValue($form, $parents)['#value'];
    $form_state
      ->set("element_type__{$wrapper_hash}", $plugin_type);
    $form_state
      ->setRebuild();
  }

}

Classes

Namesort descending Description
WebformSubmissionValue Plugin to generate a text field and consume tokens for mappings.