You are here

class DynamicFilterForm in Feed Import 8

Hierarchy

Expanded class hierarchy of DynamicFilterForm

File

src/Form/DynamicFilterForm.php, line 19
Contains \Drupal\feed_import\Form\DynamicFilterForm

Namespace

Drupal\feed_import\Form
View source
class DynamicFilterForm extends FormBase {

  /**
   * The feed being edited.
   *
   * @var object containing feed settings.
   */
  protected $feed;

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'feed_import_dynamic_filter';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state, $fid = NULL) {
    $this->feed = FeedImport::loadFeed($fid);
    if (is_null($form_state
      ->getValues())) {
      drupal_set_message(t('Dynamic filter functions are created using eval() which can be dangerous for import!'), 'warning');
    }
    $form['description'] = array(
      '#markup' => t('If possible please use a php file including filters (see Filter settings).') . '<br>' . t('Import will not start if any of these functions have syntax errors. If you have problems please check logs.') . '<br>' . '<strong>' . t('If an error occurs on runtime in one of these functions the whole script stops immediately, resulting a broken import process!') . '<br>' . t('Main purpose of these filter functions is testing.') . '<br>' . '</strong>' . '<i>' . t('Ok, eval() can be generally dangerous, but Feed Import assumes that access is enabled only for administrator.') . '</i>',
    );
    $form['fields'] = array(
      '#type' => 'container',
      '#tree' => TRUE,
      '#attributes' => array(
        'id' => 'feed_import_func_fields',
      ),
    );
    $func = array();
    $current_item = $form_state
      ->get('current_item');
    if (!is_null($current_item)) {
      $fv = $form_state
        ->getValue('fields');
      for ($i = 0; $i <= $current_item; $i++) {
        if (!isset($fv['container_' . $i])) {
          continue;
        }
        $field =& $fv['container_' . $i];
        $func += $this
          ->generateFunctionItem($i, $field);
        unset($field);
      }
      unset($fv);
    }
    else {
      $current_item = -1;
      foreach ($this->feed->settings['functions'] as &$field) {
        $current_item++;
        $func += $this
          ->generateFunctionItem($current_item, $field, TRUE);
      }
      unset($field);
    }
    $trigger = $form_state
      ->getTriggeringElement();
    $cbk = isset($trigger['#name']) ? $trigger['#name'] : '';
    if ($cbk == 'add_new_func') {
      $fv = $form_state
        ->getValue('fields');
      $form_state
        ->set('field_added', FALSE);
      if ($field = Unicode::strtolower($form_state
        ->getValue('func'))) {
        $i = -1;
        $exists = FALSE;
        while (++$i <= $current_item) {
          if (isset($fv['container_' . $i]['name']) && $fv['container_' . $i]['name'] == $field) {
            $exists = TRUE;
            break;
          }
        }
        if (!$exists) {
          $form_state
            ->set('field_added', TRUE);
          $current_item++;
          $func += $this
            ->generateFunctionItem($current_item, array(
            'name' => $field,
            'args' => '',
            'body' => '',
          ));
        }
      }
    }
    elseif (preg_match('/remove_container_([0-9]{1,9})/', $cbk, $match)) {

      // Delete container.
      unset($func['container_' . $match[1]]);
    }
    $form_state
      ->set('current_item', $current_item);

    // Add fields.
    $form['fields'] += $func;
    $form['func'] = array(
      '#type' => 'textfield',
      '#title' => t('Function name'),
      '#attributes' => array(
        'id' => 'func-name',
      ),
      '#description' => t('Name must start with underscore and can contain only alphanumeric chars or underscores.'),
      '#prefix' => '<div id="func-container">',
      '#suffix' => '</div>',
    );
    $form['add_new_func'] = array(
      '#type' => 'button',
      '#name' => 'add_new_func',
      '#value' => t('Add function'),
      '#ajax' => array(
        'event' => 'click',
        'method' => 'replaceWith',
        'callback' => array(
          $this,
          'ajaxAddItem',
        ),
        'wrapper' => 'feed_import_func_fields',
      ),
    );
    $form['submit'] = array(
      '#type' => 'submit',
      '#name' => 'save',
      '#value' => t('Save functions'),
    );

    // Add js.
    $form['#attached'] = array(
      'library' => array(
        'feed_import/behaviors',
      ),
    );
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
    if ($form_state
      ->getValue('func') && !preg_match('/^_[a-z0-9_]+$/i', $form_state
      ->getValue('func'))) {
      $form_state
        ->setError($form['func'], t('Name must start with underscore and can contain only alphanumeric chars or underscores.'));
      $form['add_new_func']['#ajax']['wrapper'] = 'func-container';
    }
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $v = $form_state
      ->getValues();
    if (!$this->feed) {
      return;
    }
    $funcs = array();
    for ($i = 0; $i <= $form_state
      ->get('current_item'); $i++) {
      if (empty($v['fields']['container_' . $i]['name'])) {
        continue;
      }
      $f = $v['fields']['container_' . $i];
      unset($f['remove_container_' . $i]);
      $f = array_map('trim', $f);
      if ($f['name'] && $f['body']) {
        $funcs[] = $f;
      }
    }
    $this->feed->settings['functions'] = $funcs;
    if (FeedImport::saveFeed($this->feed)) {
      drupal_set_message(t('Feed saved'));
    }
  }

  /**
   * Generates function fields.
   */
  protected function generateFunctionItem($pos, array $values, $collapsed = FALSE) {
    if (!preg_match('/^_[a-z0-9_]+$/i', $values['name'])) {
      return array();
    }
    $container = 'container_' . $pos;
    $item[$container] = array(
      '#type' => 'fieldset',
      '#title' => t('Function @name', array(
        '@name' => $values['name'],
      )),
      '#collapsible' => TRUE,
      '#collapsed' => $collapsed,
      '#attributes' => array(
        'id' => 'item_container_' . $pos,
      ),
    );
    $container =& $item[$container];
    $container['name'] = array(
      '#type' => 'textfield',
      '#title' => t('Name'),
      '#description' => t('Name must start with underscore and can contain only alphanumeric chars or underscores.'),
      '#default_value' => $values['name'],
      '#attributes' => array(
        'id' => 'func_name_' . $pos,
      ),
    );
    $container['args'] = array(
      '#type' => 'textfield',
      '#title' => t('Parameters'),
      '#description' => t('Use variable names separated by comma, like: $a, $b'),
      '#default_value' => $values['args'],
    );
    $container['body'] = array(
      '#type' => 'textarea',
      '#rows' => 5,
      '#title' => t('Body'),
      '#description' => t('Write only the function body. Do not forget to return a value.'),
      '#default_value' => $values['body'],
    );
    $container['remove_container_' . $pos] = array(
      '#type' => 'button',
      '#name' => 'remove_container_' . $pos,
      '#value' => t('Remove function'),
      '#ajax' => array(
        'event' => 'click',
        'wrapper' => 'item_container_' . $pos,
        'callback' => array(
          $this,
          'ajaxRemoveItem',
        ),
        'method' => 'replaceWith',
      ),
    );
    return $item;
  }

  /**
   * Ajax callback to add a new item
   */
  public function ajaxAddItem(array &$form, FormStateInterface $form_state) {
    $response = new AjaxResponse();
    if ($form_state
      ->get('field_added')) {
      $selector = '#' . $form['add_new_func']['#ajax']['wrapper'];
      $content = $form['fields']['container_' . $form_state
        ->get('current_item')];
      $response
        ->addCommand(new AfterCommand($selector, $content));
    }
    $status = array(
      '#type' => 'status_messages',
    );
    $response
      ->addCommand(new ReplaceCommand('#func-container', $form['func']));
    $response
      ->addCommand(new RemoveCommand('div.messages'));
    $response
      ->addCommand(new BeforeCommand('.region-highlighted', $status));
    return $response;
  }

  /**
   * Ajax callback to remove an item
   */
  public function ajaxRemoveItem(array &$form, FormStateInterface $form_state) {

    // Return empty string
    return array(
      '#markup' => '',
    );
  }

}

Members

Namesort descending Modifiers Type Description Overrides
DependencySerializationTrait::$_entityStorages protected property An array of entity type IDs keyed by the property name of their storages.
DependencySerializationTrait::$_serviceIds protected property An array of service IDs keyed by property name used for serialization.
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2
DynamicFilterForm::$feed protected property The feed being edited.
DynamicFilterForm::ajaxAddItem public function Ajax callback to add a new item
DynamicFilterForm::ajaxRemoveItem public function Ajax callback to remove an item
DynamicFilterForm::buildForm public function Form constructor. Overrides FormInterface::buildForm
DynamicFilterForm::generateFunctionItem protected function Generates function fields.
DynamicFilterForm::getFormId public function Returns a unique string identifying the form. Overrides FormInterface::getFormId
DynamicFilterForm::submitForm public function Form submission handler. Overrides FormInterface::submitForm
DynamicFilterForm::validateForm public function Form validation handler. Overrides FormBase::validateForm
FormBase::$configFactory protected property The config factory. 1
FormBase::$requestStack protected property The request stack. 1
FormBase::$routeMatch protected property The route match.
FormBase::config protected function Retrieves a configuration object.
FormBase::configFactory protected function Gets the config factory for this form. 1
FormBase::container private function Returns the service container.
FormBase::create public static function Instantiates a new instance of this class. Overrides ContainerInjectionInterface::create 87
FormBase::currentUser protected function Gets the current user.
FormBase::getRequest protected function Gets the request object.
FormBase::getRouteMatch protected function Gets the route match.
FormBase::logger protected function Gets the logger for a specific channel.
FormBase::redirect protected function Returns a redirect response object for the specified route. Overrides UrlGeneratorTrait::redirect
FormBase::resetConfigFactory public function Resets the configuration factory.
FormBase::setConfigFactory public function Sets the config factory for this form.
FormBase::setRequestStack public function Sets the request stack object to use.
LinkGeneratorTrait::$linkGenerator protected property The link generator. 1
LinkGeneratorTrait::getLinkGenerator Deprecated protected function Returns the link generator.
LinkGeneratorTrait::l Deprecated protected function Renders a link to a route given a route name and its parameters.
LinkGeneratorTrait::setLinkGenerator Deprecated public function Sets the link generator service.
LoggerChannelTrait::$loggerFactory protected property The logger channel factory service.
LoggerChannelTrait::getLogger protected function Gets the logger for a specific channel.
LoggerChannelTrait::setLoggerFactory public function Injects the logger channel factory.
MessengerTrait::$messenger protected property The messenger. 29
MessengerTrait::messenger public function Gets the messenger. 29
MessengerTrait::setMessenger public function Sets the messenger.
RedirectDestinationTrait::$redirectDestination protected property The redirect destination service. 1
RedirectDestinationTrait::getDestinationArray protected function Prepares a 'destination' URL query parameter for use with \Drupal\Core\Url.
RedirectDestinationTrait::getRedirectDestination protected function Returns the redirect destination service.
RedirectDestinationTrait::setRedirectDestination public function Sets the redirect destination service.
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.
UrlGeneratorTrait::$urlGenerator protected property The url generator.
UrlGeneratorTrait::getUrlGenerator Deprecated protected function Returns the URL generator service.
UrlGeneratorTrait::setUrlGenerator Deprecated public function Sets the URL generator service.
UrlGeneratorTrait::url Deprecated protected function Generates a URL or path for a specific route based on the given parameters.