You are here

abstract class ParserBase in Feeds extensible parsers 8

The Feeds extensible parser.

Hierarchy

Expanded class hierarchy of ParserBase

1 file declares its use of ParserBase
TestUiParser.php in tests/modules/feeds_ex_test/src/Feeds/Parser/TestUiParser.php

File

src/Feeds/Parser/ParserBase.php, line 29

Namespace

Drupal\feeds_ex\Feeds\Parser
View source
abstract class ParserBase extends FeedsParserBase implements ParserInterface, PluginFormInterface, MappingPluginFormInterface {

  /**
   * The messenger, for compatibility with Drupal 8.5.
   *
   * @var \Drupal\Core\Messenger\MessengerInterface
   */
  protected $feedsExMessenger;

  /**
   * The class used as the text encoder.
   *
   * @var string
   */
  protected $encoderClass = '\\Drupal\\feeds_ex\\Encoder\\TextEncoder';

  /**
   * The encoder used to convert encodings.
   *
   * @var \Drupal\feeds_ex\Encoder\EncoderInterface
   */
  protected $encoder;

  /**
   * The default list of HTML tags allowed by Xss::filter().
   *
   * In addition of \Drupal\Component\Utility\Xss::$htmlTags also the <pre>-tag
   * is added to the list of allowed tags. This is because for the JMESPath
   * parser an error can be generated that needs to be displayed preformatted.
   *
   * @var array
   *
   * @see \Drupal\Component\Utility\Xss::filter()
   */
  protected static $htmlTags = [
    'a',
    'em',
    'strong',
    'cite',
    'blockquote',
    'br',
    'pre',
    'code',
    'ul',
    'ol',
    'li',
    'dl',
    'dt',
    'dd',
  ];

  /**
   * Constructs a ParserBase object.
   *
   * @param array $configuration
   *   The plugin configuration.
   * @param string $plugin_id
   *   The plugin id.
   * @param array $plugin_definition
   *   The plugin definition.
   */
  public function __construct(array $configuration, $plugin_id, array $plugin_definition) {
    if (!$this
      ->hasConfigForm()) {
      unset($plugin_definition['form']['configuration']);
    }
    parent::__construct($configuration, $plugin_id, $plugin_definition);
  }

  /**
   * Returns rows to be parsed.
   *
   * @param \Drupal\feeds\FeedInterface $feed
   *   Source information.
   * @param \Drupal\feeds\Result\FetcherResultInterface $fetcher_result
   *   The result returned by the fetcher.
   * @param \Drupal\feeds\StateInterface $state
   *   The state object.
   *
   * @return array|Traversable
   *   Some iterable that returns rows.
   */
  protected abstract function executeContext(FeedInterface $feed, FetcherResultInterface $fetcher_result, StateInterface $state);

  /**
   * Executes a single source expression.
   *
   * @param string $machine_name
   *   The source machine name being executed.
   * @param string $expression
   *   The expression to execute.
   * @param mixed $row
   *   The row to execute on.
   *
   * @return scalar|[]scalar
   *   Either a scalar, or a list of scalars. If null, the value will be
   *   ignored.
   */
  protected abstract function executeSourceExpression($machine_name, $expression, $row);

  /**
   * Validates an expression.
   *
   * @param string &$expression
   *   The expression to validate.
   *
   * @return string|null
   *   Return the error string, or null if validation was passed.
   */
  protected abstract function validateExpression(&$expression);

  /**
   * Returns the errors after parsing.
   *
   * @return array
   *   A structured array array with keys:
   *   - message: The error message.
   *   - variables: The variables for the message.
   *   - severity: The severity of the message.
   *
   * @see watchdog()
   */
  protected abstract function getErrors();

  /**
   * Allows subclasses to prepare for parsing.
   *
   * @param \Drupal\feeds\FeedInterface $feed
   *   The feed we are parsing for.
   * @param \Drupal\feeds\Result\FetcherResultInterface $fetcher_result
   *   The result of the fetching stage.
   * @param \Drupal\feeds\StateInterface $state
   *   The state object.
   */
  protected function setUp(FeedInterface $feed, FetcherResultInterface $fetcher_result, StateInterface $state) {
  }

  /**
   * Allows subclasses to cleanup after parsing.
   *
   * @param \Drupal\feeds\FeedInterface $feed
   *   The feed we are parsing for.
   * @param \Drupal\feeds\Result\ParserResultInterface $parser_result
   *   The result of parsing.
   * @param \Drupal\feeds\StateInterface $state
   *   The state object.
   */
  protected function cleanUp(FeedInterface $feed, ParserResultInterface $parser_result, StateInterface $state) {
  }

  /**
   * Starts internal error handling.
   *
   * Subclasses can override this to being error handling.
   */
  protected function startErrorHandling() {
  }

  /**
   * Stops internal error handling.
   *
   * Subclasses can override this to end error handling.
   */
  protected function stopErrorHandling() {
  }

  /**
   * Loads the necessary library.
   *
   * Subclasses can override this to load the necessary library. It will be
   * called automatically.
   *
   * @throws \RuntimeException
   *   Thrown if the library does not exist.
   */
  protected function loadLibrary() {
  }

  /**
   * Returns whether or not this parser uses a context query.
   *
   * Sub-classes can return false here if they don't require a user-configured
   * context query.
   *
   * @return bool
   *   True if the parser uses a context query and false if not.
   */
  protected function hasConfigurableContext() {
    return TRUE;
  }

  /**
   * Returns the label for single source.
   *
   * @return \Drupal\Core\StringTranslation\TranslatableMarkup|null
   *   A translated string if the source has a special name. Null otherwise.
   */
  protected function configSourceLabel() {
    return NULL;
  }

  /**
   * Returns the list of table headers.
   *
   * @return array
   *   A list of header names keyed by the form keys.
   */
  protected function configFormTableHeader() {
    return [];
  }

  /**
   * Returns a form element for a specific column.
   *
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current form state.
   * @param array $values
   *   The individual source item values.
   * @param string $column
   *   The name of the column.
   * @param string $machine_name
   *   The machine name of the source.
   *
   * @return array
   *   A single form element.
   */
  protected function configFormTableColumn(FormStateInterface $form_state, array $values, $column, $machine_name) {
    return [];
  }

  /**
   * {@inheritdoc}
   */
  public function parse(FeedInterface $feed, FetcherResultInterface $fetcher_result, StateInterface $state) {
    $this
      ->loadLibrary();
    $this
      ->startErrorHandling();
    $result = new ParserResult();

    // @todo Set link?
    // $fetcher_config = $feed->getConfigurationFor($feed->importer->fetcher);
    // $result->link = is_string($fetcher_config['source']) ? $fetcher_config['source'] : '';
    try {
      $this
        ->setUp($feed, $fetcher_result, $state);
      $this
        ->parseItems($feed, $fetcher_result, $result, $state);
      $this
        ->cleanUp($feed, $result, $state);
    } catch (EmptyFeedException $e) {

      // The feed is empty.
      $this
        ->getMessenger()
        ->addMessage($this
        ->t('The feed is empty.'), 'warning', FALSE);
    } catch (Exception $exception) {

      // Do nothing. Store for later.
    }

    // Display errors.
    $errors = $this
      ->getErrors();
    $this
      ->printErrors($errors, $this->configuration['display_errors'] ? RfcLogLevel::DEBUG : RfcLogLevel::ERROR);
    $this
      ->stopErrorHandling();
    if (isset($exception)) {
      throw $exception;
    }
    return $result;
  }

  /**
   * Performs the actual parsing.
   *
   * @param \Drupal\feeds\FeedInterface $feed
   *   The feed source.
   * @param \Drupal\feeds\Result\FetcherResultInterface $fetcher_result
   *   The fetcher result.
   * @param \Drupal\feeds\Result\ParserResultInterface $result
   *   The parser result object to populate.
   * @param \Drupal\feeds\StateInterface $state
   *   The state object.
   */
  protected function parseItems(FeedInterface $feed, FetcherResultInterface $fetcher_result, ParserResultInterface $result, StateInterface $state) {
    $expressions = $this
      ->prepareExpressions();
    $variable_map = $this
      ->prepareVariables($expressions);
    foreach ($this
      ->executeContext($feed, $fetcher_result, $state) as $row) {
      if ($item = $this
        ->executeSources($row, $expressions, $variable_map)) {
        $result
          ->addItem($item);
      }
    }
  }

  /**
   * Prepares the expressions for parsing.
   *
   * At this point we just remove empty expressions.
   *
   * @return array
   *   A map of machine name to expression.
   */
  protected function prepareExpressions() {
    $expressions = [];
    foreach ($this->configuration['sources'] as $machine_name => $source) {
      if (strlen($source['value'])) {
        $expressions[$machine_name] = $source['value'];
      }
    }
    return $expressions;
  }

  /**
   * Prepares the variable map used to substitution.
   *
   * @param array $expressions
   *   The expressions being parsed.
   *
   * @return array
   *   A map of machine name to variable name.
   */
  protected function prepareVariables(array $expressions) {
    $variable_map = [];
    foreach ($expressions as $machine_name => $expression) {
      $variable_map[$machine_name] = '$' . $machine_name;
    }
    return $variable_map;
  }

  /**
   * Executes the source expressions.
   *
   * @param mixed $row
   *   A single item returned from the context expression.
   * @param array $expressions
   *   A map of machine name to expression.
   * @param array $variable_map
   *   A map of machine name to varible name.
   *
   * @return array
   *   The fully-parsed item array.
   */
  protected function executeSources($row, array $expressions, array $variable_map) {
    $item = new DynamicItem();
    $variables = [];
    foreach ($expressions as $machine_name => $expression) {

      // Variable substitution.
      $expression = strtr($expression, $variables);
      $result = $this
        ->executeSourceExpression($machine_name, $expression, $row);
      if (!empty($this->configuration['sources'][$machine_name]['debug'])) {
        $this
          ->debug($result, $machine_name);
      }
      if ($result === NULL) {
        $variables[$variable_map[$machine_name]] = '';
        continue;
      }
      $item
        ->set($machine_name, $result);
      $variables[$variable_map[$machine_name]] = is_array($result) ? reset($result) : $result;
    }
    return $item;
  }

  /**
   * Prints errors to the screen.
   *
   * @param array $errors
   *   A list of errors as returned by stopErrorHandling().
   * @param int $severity
   *   (optional) Limit to only errors of the specified severity. Defaults to
   *   RfcLogLevel::ERROR.
   *
   * @see watchdog()
   */
  protected function printErrors(array $errors, $severity = RfcLogLevel::ERROR) {
    foreach ($errors as $error) {
      if ($error['severity'] > $severity) {
        continue;
      }
      $this
        ->getMessenger()
        ->addMessage($this
        ->t($error['message'], $error['variables']), $error['severity'] <= RfcLogLevel::ERROR ? 'error' : 'warning', FALSE);
    }
  }

  /**
   * Prepares the raw string for parsing.
   *
   * @param \Drupal\feeds\Result\FetcherResultInterface $fetcher_result
   *   The fetcher result.
   *
   * @return string
   *   The prepared raw string.
   */
  protected function prepareRaw(FetcherResultInterface $fetcher_result) {
    $raw = $this
      ->getEncoder()
      ->convertEncoding($fetcher_result
      ->getRaw());

    // Strip null bytes.
    $raw = trim(str_replace("\0", '', $raw));

    // Check that the string has at least one character.
    if (!isset($raw[0])) {
      throw new EmptyFeedException();
    }
    return $raw;
  }

  /**
   * Renders our debug messages into a list.
   *
   * @param mixed $data
   *   The result of an expression. Either a scalar or a list of scalars.
   * @param string $machine_name
   *   The source key that produced this query.
   */
  protected function debug($data, $machine_name) {
    $name = $machine_name;
    if ($this->configuration['sources'][$machine_name]['name']) {
      $name = $this->configuration['sources'][$machine_name]['name'];
    }
    $output = '<strong>' . $name . ':</strong>';
    $data = is_array($data) ? $data : [
      $data,
    ];
    foreach ($data as $key => $value) {
      $data[$key] = Html::escape($value);
    }
    $output .= _theme('item_list', [
      'items' => $data,
    ]);
    $this
      ->getMessenger()
      ->addMessage($output);
  }

  /**
   * {@inheritdoc}
   */
  public function getMappingSources() {
    return $this->configuration['sources'];
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return [
      'sources' => [],
      'context' => [
        'value' => '',
      ],
      'display_errors' => FALSE,
      'source_encoding' => [
        'auto',
      ],
      'debug_mode' => FALSE,
      'line_limit' => 100,
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
    return [];
  }

  /**
   * {@inheritdoc}
   */
  public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {

    // Validation is optional.
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {

    // Preserve some configuration.
    $config = array_merge([
      'context' => $this
        ->getConfiguration('context'),
      'sources' => $this
        ->getConfiguration('sources'),
    ], $form_state
      ->getValues());
    $this
      ->setConfiguration($config);
  }

  /**
   * {@inheritdoc}
   */
  public function mappingFormAlter(array &$form, FormStateInterface $form_state) {
    if ($this
      ->hasConfigurableContext()) {
      $form['context'] = [
        '#type' => 'textfield',
        '#title' => $this
          ->t('Context'),
        '#default_value' => $this->configuration['context']['value'],
        '#description' => $this
          ->t('The base query to run. See the <a href=":link" target="_new">Context query documentation</a> for more information.', [
          ':link' => 'https://www.drupal.org/node/3227985',
        ]),
        '#size' => 50,
        '#required' => TRUE,
        '#maxlength' => 1024,
        '#weight' => -50,
      ];
    }
    parent::mappingFormAlter($form, $form_state);
  }

  /**
   * {@inheritdoc}
   */
  public function mappingFormValidate(array &$form, FormStateInterface $form_state) {
    try {

      // Validate context.
      if ($this
        ->hasConfigurableContext()) {
        if ($message = $this
          ->validateExpression($form_state
          ->getValue('context'))) {
          $message = new FormattableMarkup(Xss::filter($message, static::$htmlTags), []);
          $form_state
            ->setErrorByName('context', $message);
        }
      }

      // Validate new sources.
      $mappings = $form_state
        ->getValue('mappings');
      foreach ($mappings as $i => $mapping) {
        foreach ($mapping['map'] as $subtarget => $map) {
          if ($map['select'] == '__new' && isset($map['__new']['value'])) {
            if ($message = $this
              ->validateExpression($map['__new']['value'])) {
              $message = new FormattableMarkup(Xss::filter($message, static::$htmlTags), []);
              $form_state
                ->setErrorByName("mappings][{$i}][map][{$subtarget}][__new][value", $message);
            }
          }
        }
      }
    } catch (Exception $e) {

      // Exceptions due to missing libraries could occur, so catch these.
      $form_state
        ->setError($form, $e
        ->getMessage());
    }
  }

  /**
   * {@inheritdoc}
   */
  public function mappingFormSubmit(array &$form, FormStateInterface $form_state) {
    $config = [];

    // Set context.
    $config['context'] = [
      'value' => $form_state
        ->getValue('context'),
    ];

    // Set sources.
    // @todo refactor to let parsers use custom sources directly.
    $config['sources'] = [];
    $mappings = $form_state
      ->getValue('mappings');
    foreach ($mappings as $i => $mapping) {
      foreach ($mapping['map'] as $subtarget => $map) {
        if (empty($map['select'])) {
          continue;
        }
        if ($map['select'] == '__new') {
          $name = $map['__new']['machine_name'];
        }
        else {
          $name = $map['select'];
        }
        $source = $this->feedType
          ->getCustomSource($name);
        if ($source) {
          unset($source['machine_name']);
          $config['sources'][$name] = $source;
        }
      }
    }
    $this
      ->setConfiguration($config);
  }

  /**
   * Builds configuration form for the parser settings.
   *
   * @todo The code below is still D7 code and does not work in D8 yet. Also,
   * it's likely that most of the code below is no longer needed as the parser
   * UI is planned to be implemented in a completely different way.
   *
   * @see https://www.drupal.org/node/2917924
   */
  public function _buildConfigurationForm(array $form, FormStateInterface $form_state) {
    $form = [
      '#tree' => TRUE,
      '#theme' => 'feeds_ex_configuration_table',
      '#prefix' => '<div id="feeds-ex-configuration-wrapper">',
      '#suffix' => '</div>',
    ];
    $form['sources'] = [
      '#id' => 'feeds-ex-source-table',
      '#attributes' => [
        'class' => [
          'feeds-ex-source-table',
        ],
      ],
    ];
    $max_weight = 0;
    foreach ($this->configuration['sources'] as $machine_name => $source) {
      $form['sources'][$machine_name]['name'] = [
        '#type' => 'textfield',
        '#title' => $this
          ->t('Name'),
        '#title_display' => 'invisible',
        '#default_value' => $source['name'],
        '#size' => 20,
      ];
      $form['sources'][$machine_name]['machine_name'] = [
        '#title' => $this
          ->t('Machine name'),
        '#title_display' => 'invisible',
        '#markup' => $machine_name,
      ];
      $form['sources'][$machine_name]['value'] = [
        '#type' => 'textfield',
        '#title' => $this
          ->t('Value'),
        '#title_display' => 'invisible',
        '#default_value' => $source['value'],
        '#size' => 50,
        '#maxlength' => 1024,
      ];
      foreach ($this
        ->configFormTableHeader() as $column => $name) {
        $form['sources'][$machine_name][$column] = $this
          ->configFormTableColumn($form_state, $source, $column, $machine_name);
      }
      $form['sources'][$machine_name]['debug'] = [
        '#type' => 'checkbox',
        '#title' => $this
          ->t('Debug'),
        '#title_display' => 'invisible',
        '#default_value' => $source['debug'],
      ];
      $form['sources'][$machine_name]['remove'] = [
        '#type' => 'checkbox',
        '#title' => $this
          ->t('Remove'),
        '#title_display' => 'invisible',
      ];
      $form['sources'][$machine_name]['weight'] = [
        '#type' => 'textfield',
        '#default_value' => $source['weight'],
        '#size' => 3,
        '#attributes' => [
          'class' => [
            'feeds-ex-source-weight',
          ],
        ],
      ];
      $max_weight = $source['weight'];
    }
    $form['add']['name'] = [
      '#type' => 'textfield',
      '#title' => $this
        ->t('Add new source'),
      '#id' => 'edit-sources-add-name',
      '#description' => $this
        ->t('Name'),
      '#size' => 20,
    ];
    $form['add']['machine_name'] = [
      '#title' => $this
        ->t('Machine name'),
      '#title_display' => 'invisible',
      '#type' => 'machine_name',
      '#machine_name' => [
        'exists' => 'feeds_ex_source_exists',
        'source' => [
          'add',
          'name',
        ],
        'standalone' => TRUE,
        'label' => '',
      ],
      '#field_prefix' => '<span dir="ltr">',
      '#field_suffix' => '</span>&lrm;',
      '#feeds_importer' => $this->id,
      '#required' => FALSE,
      '#maxlength' => 32,
      '#size' => 15,
      '#description' => $this
        ->t('A unique machine-readable name containing letters, numbers, and underscores.'),
    ];
    $form['add']['value'] = [
      '#type' => 'textfield',
      '#description' => $this
        ->t('Value'),
      '#title' => '&nbsp;',
      '#size' => 50,
      '#maxlength' => 1024,
    ];
    foreach ($this
      ->configFormTableHeader() as $column => $name) {
      $form['add'][$column] = $this
        ->configFormTableColumn($form_state, [], $column, '');
    }
    $form['add']['debug'] = [
      '#type' => 'checkbox',
      '#title' => $this
        ->t('Debug'),
      '#title_display' => 'invisible',
    ];
    $form['add']['weight'] = [
      '#type' => 'textfield',
      '#default_value' => ++$max_weight,
      '#size' => 3,
      '#attributes' => [
        'class' => [
          'feeds-ex-source-weight',
        ],
      ],
    ];
    $form['display_errors'] = [
      '#type' => 'checkbox',
      '#title' => $this
        ->t('Display errors'),
      '#description' => $this
        ->t('Display all error messages after parsing. Fatal errors will always be displayed.'),
      '#default_value' => $this->configuration['display_errors'],
    ];
    $form['debug_mode'] = [
      '#type' => 'checkbox',
      '#title' => $this
        ->t('Enable debug mode'),
      '#description' => $this
        ->t('Displays the configuration form on the feed source page to ease figuring out the expressions. Any values entered on that page will be saved here.'),
      '#default_value' => $this->configuration['debug_mode'],
    ];
    $form = $this
      ->getEncoder()
      ->buildConfigurationForm($form, $form_state);
    $form['#attached']['drupal_add_tabledrag'][] = [
      'feeds-ex-source-table',
      'order',
      'sibling',
      'feeds-ex-source-weight',
    ];
    $form['#attached']['css'][] = drupal_get_path('module', 'feeds_ex') . '/feeds_ex.css';
    $form['#header'] = $this
      ->getFormHeader();
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function configFormValidate(&$values) {

    // Throwing an exception during validation shows a nasty error to users.
    try {
      $this
        ->loadLibrary();
    } catch (RuntimeException $e) {
      $this
        ->getMessenger()
        ->addMessage($e
        ->getMessage(), 'error', FALSE);
      return;
    }

    // @todo We should do this in Feeds automatically.
    $values += $this
      ->defaultConfiguration();

    // Remove sources.
    foreach ($values['sources'] as $machine_name => $source) {
      if (!empty($source['remove'])) {
        unset($values['sources'][$machine_name]);
      }
    }

    // Add new source.
    if (strlen($values['add']['machine_name']) && strlen($values['add']['name'])) {
      if ($message = $this
        ->validateExpression($values['add']['value'])) {
        form_set_error('add][value', $message);
      }
      else {
        $values['sources'][$values['add']['machine_name']] = $values['add'];
      }
    }

    // Rebuild sources to keep the configuration values clean.
    $columns = $this
      ->getFormHeader();
    unset($columns['remove'], $columns['machine_name']);
    $columns = array_keys($columns);
    foreach ($values['sources'] as $machine_name => $source) {
      $new_value = [];
      foreach ($columns as $column) {
        $new_value[$column] = $source[$column];
      }
      $values['sources'][$machine_name] = $new_value;
    }

    // Sort by weight.
    uasort($values['sources'], 'ctools_plugin_sort');

    // Let the encoder do its thing.
    $this
      ->getEncoder()
      ->configFormValidate($values);
  }

  /**
   * {@inheritdoc}
   */
  public function hasConfigForm() {
    return FALSE;
  }

  /**
   * {@inheritdoc}
   */
  public function sourceDefaults() {
    return [];
  }

  /**
   * {@inheritdoc}
   */
  public function buildFeedForm(array $form, FormStateInterface $form_state, FeedInterface $feed) {
    if (!$this
      ->hasSourceConfig()) {
      return [];
    }
    $form = $this
      ->buildConfigurationForm($form, $form_state);
    $form['add']['machine_name']['#machine_name']['source'] = [
      'feeds',
      get_class($this),
      'add',
      'name',
    ];
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function sourceFormValidate(&$source_config) {
    $this
      ->configFormValidate($source_config);
  }

  /**
   * {@inheritdoc}
   */
  public function sourceSave(FeedInterface $feed) {
    $config = $feed
      ->getConfigurationFor($this);
    $feed
      ->setConfigFor($this, []);
    if ($this
      ->hasSourceConfig() && $config) {
      $this
        ->setConfig($config);
      $this
        ->save();
    }
  }

  /**
   * {@inheritdoc}
   */
  public function hasSourceConfig() {
    return !empty($this->configuration['debug_mode']);
  }

  /**
   * Returns the configuration form table header.
   *
   * @return array
   *   The header array.
   */
  protected function getFormHeader() {
    $header = [
      'name' => $this
        ->t('Name'),
      'machine_name' => $this
        ->t('Machine name'),
      'value' => $this
        ->t('Value'),
    ];
    $header += $this
      ->configFormTableHeader();
    $header += [
      'debug' => $this
        ->t('Debug'),
      'remove' => $this
        ->t('Remove'),
      'weight' => $this
        ->t('Weight'),
    ];
    return $header;
  }

  /**
   * Sets the encoder.
   *
   * @param \Drupal\feeds_ex\Encoder\EncoderInterface $encoder
   *   The encoder.
   *
   * @return $this
   *   The parser object.
   */
  public function setEncoder(EncoderInterface $encoder) {
    $this->encoder = $encoder;
    return $this;
  }

  /**
   * Returns the encoder.
   *
   * @return \Drupal\feeds_ex\Encoder\EncoderInterface
   *   The encoder object.
   */
  public function getEncoder() {
    if (!isset($this->encoder)) {
      $class = $this->encoderClass;
      $this->encoder = new $class($this->configuration['source_encoding']);
    }
    return $this->encoder;
  }

  /**
   * Sets the messenger.
   *
   * For compatibility with both Drupal 8.5 and Drupal 8.6.
   * Basically only useful for automated tests.
   *
   * @param \Drupal\Core\Messenger\MessengerInterface $messenger
   *   The messenger.
   */
  public function setFeedsExMessenger(MessengerInterface $messenger) {
    if (method_exists($this, 'setMessenger')) {
      $this
        ->setMessenger($messenger);
    }
    else {
      $this->feedsExMessenger = $messenger;
    }
  }

  /**
   * Gets the messenger.
   *
   * For compatibility with both Drupal 8.5 and Drupal 8.6.
   *
   * @return \Drupal\Core\Messenger\MessengerInterface
   *   The messenger.
   */
  public function getMessenger() {
    if (method_exists($this, 'messenger')) {
      return $this
        ->messenger();
    }
    if (isset($this->feedsExMessenger)) {
      return $this->feedsExMessenger;
    }
    return \Drupal::messenger();
  }

}

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
DependencyTrait::$dependencies protected property The object's dependencies.
DependencyTrait::addDependencies protected function Adds multiple dependencies.
DependencyTrait::addDependency protected function Adds a dependency.
MessengerTrait::$messenger protected property The messenger. 29
MessengerTrait::messenger public function Gets the messenger. 29
MessengerTrait::setMessenger public function Sets the messenger.
ParserBase::$encoder protected property The encoder used to convert encodings.
ParserBase::$encoderClass protected property The class used as the text encoder. 1
ParserBase::$feedsExMessenger protected property The messenger, for compatibility with Drupal 8.5.
ParserBase::$htmlTags protected static property The default list of HTML tags allowed by Xss::filter().
ParserBase::buildConfigurationForm public function Form constructor. Overrides PluginFormInterface::buildConfigurationForm 1
ParserBase::buildFeedForm public function
ParserBase::cleanUp protected function Allows subclasses to cleanup after parsing. 3
ParserBase::configFormTableColumn protected function Returns a form element for a specific column. 1
ParserBase::configFormTableHeader protected function Returns the list of table headers. 1
ParserBase::configFormValidate public function 1
ParserBase::configSourceDescription protected function Returns the description for single source. 1
ParserBase::configSourceLabel protected function Returns the label for single source. Overrides ParserBase::configSourceLabel 1
ParserBase::debug protected function Renders our debug messages into a list.
ParserBase::defaultConfiguration public function Gets default configuration for this plugin. Overrides PluginBase::defaultConfiguration 1
ParserBase::executeContext abstract protected function Returns rows to be parsed. 4
ParserBase::executeSourceExpression abstract protected function Executes a single source expression. 4
ParserBase::executeSources protected function Executes the source expressions.
ParserBase::getEncoder public function Returns the encoder.
ParserBase::getErrors abstract protected function Returns the errors after parsing. 4
ParserBase::getFormHeader protected function Returns the configuration form table header.
ParserBase::getMappingSources public function Declare the possible mapping sources that this parser produces. Overrides ParserInterface::getMappingSources
ParserBase::getMessenger public function Gets the messenger.
ParserBase::hasConfigForm public function 1
ParserBase::hasConfigurableContext protected function Returns whether or not this parser uses a context query. 2
ParserBase::hasSourceConfig public function
ParserBase::loadLibrary protected function Loads the necessary library. 3
ParserBase::mappingFormAlter public function Alter mapping form. Overrides ParserBase::mappingFormAlter
ParserBase::mappingFormSubmit public function Submit handler for the mapping form. Overrides ParserBase::mappingFormSubmit
ParserBase::mappingFormValidate public function Validate handler for the mapping form. Overrides ParserBase::mappingFormValidate
ParserBase::parse public function Parses content returned by fetcher. Overrides ParserInterface::parse
ParserBase::parseItems protected function Performs the actual parsing. 2
ParserBase::prepareExpressions protected function Prepares the expressions for parsing.
ParserBase::prepareRaw protected function Prepares the raw string for parsing.
ParserBase::prepareVariables protected function Prepares the variable map used to substitution.
ParserBase::printErrors protected function Prints errors to the screen.
ParserBase::setEncoder public function Sets the encoder.
ParserBase::setFeedsExMessenger public function Sets the messenger.
ParserBase::setUp protected function Allows subclasses to prepare for parsing. 3
ParserBase::sourceDefaults public function
ParserBase::sourceFormValidate public function
ParserBase::sourceSave public function
ParserBase::startErrorHandling protected function Starts internal error handling. 2
ParserBase::stopErrorHandling protected function Stops internal error handling. 1
ParserBase::submitConfigurationForm public function Form submission handler. Overrides PluginFormInterface::submitConfigurationForm
ParserBase::validateConfigurationForm public function Form validation handler. Overrides PluginFormInterface::validateConfigurationForm
ParserBase::validateExpression abstract protected function Validates an expression. 4
ParserBase::_buildConfigurationForm public function Builds configuration form for the parser settings.
ParserBase::__construct public function Constructs a ParserBase object. Overrides PluginBase::__construct 2
PluginBase::$configuration protected property Configuration information passed into the plugin. 1
PluginBase::$feedType protected property The importer this plugin is working for.
PluginBase::$linkGenerator protected property The link generator.
PluginBase::$pluginDefinition protected property The plugin implementation definition. 1
PluginBase::$pluginId protected property The plugin_id.
PluginBase::$urlGenerator protected property The url generator.
PluginBase::calculateDependencies public function Calculates dependencies for the configured plugin. Overrides DependentPluginInterface::calculateDependencies 2
PluginBase::container private function Returns the service container.
PluginBase::defaultFeedConfiguration public function Returns default feed configuration. Overrides FeedsPluginInterface::defaultFeedConfiguration 3
PluginBase::DERIVATIVE_SEPARATOR constant A string which is used to separate base plugin IDs from the derivative ID.
PluginBase::getBaseId public function Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface::getBaseId
PluginBase::getConfiguration public function Gets this plugin's configuration. Overrides ConfigurableInterface::getConfiguration
PluginBase::getDerivativeId public function Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface::getDerivativeId
PluginBase::getPluginDefinition public function Gets the definition of the plugin implementation. Overrides PluginInspectionInterface::getPluginDefinition 3
PluginBase::getPluginId public function Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface::getPluginId
PluginBase::isConfigurable public function Determines if the plugin is configurable.
PluginBase::l protected function Renders a link to a route given a route name and its parameters.
PluginBase::linkGenerator protected function Returns the link generator service.
PluginBase::onFeedDeleteMultiple public function A feed is being deleted. 3
PluginBase::onFeedSave public function A feed is being saved.
PluginBase::onFeedTypeDelete public function The feed type is being deleted. 1
PluginBase::onFeedTypeSave public function The feed type is being saved. 1
PluginBase::pluginType public function Returns the type of plugin. Overrides FeedsPluginInterface::pluginType
PluginBase::setConfiguration public function Sets the configuration for this plugin instance. Overrides ConfigurableInterface::setConfiguration 1
PluginBase::url protected function Generates a URL or path for a specific route based on the given parameters.
PluginBase::urlGenerator protected function Returns the URL generator 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.