class ConfigSourcePluginUi

Config source plugin UI.

That provides getEntity() method to retrieve list of entities of specific type. It also allows to implement alter hook to alter the entity query for a specific type.

Hierarchy

Expanded class hierarchy of ConfigSourcePluginUi

Related topics

File

sources/tmgmt_config/src/ConfigSourcePluginUi.php, line 19

Namespace

Drupal\tmgmt_config
View source
class ConfigSourcePluginUi extends SourcePluginUiBase {

  /**
   * Entity source list items limit.
   *
   * @var int
   */
  public $pagerLimit = 25;

  /**
   * {@inheritdoc}
   */
  public function overviewSearchFormPart(array $form, FormStateInterface $form_state, $type) {
    $form = parent::overviewSearchFormPart($form, $form_state, $type);
    if ($type == ConfigSource::SIMPLE_CONFIG) {
      $label_key = 'name';
      $label = t('Simple configuration');
    }
    else {
      $entity_type = \Drupal::entityTypeManager()
        ->getDefinition($type);
      $label_key = $entity_type
        ->getKey('label');
      $label = $entity_type
        ->getLabel();
    }
    if (!empty($label_key)) {
      $form['search_wrapper']['search'][$label_key] = array(
        '#type' => 'textfield',
        '#title' => t('@entity_name title', array(
          '@entity_name' => $label,
        )),
        '#size' => 25,
        '#default_value' => isset($_GET[$label_key]) ? $_GET[$label_key] : NULL,
      );
    }
    $form['search_wrapper']['search']['langcode'] = array(
      '#type' => 'language_select',
      '#title' => t('Source Language'),
      '#empty_option' => t('- Any -'),
      '#default_value' => isset($_GET['langcode']) ? $_GET['langcode'] : NULL,
    );
    $form['search_wrapper']['search']['target_language'] = array(
      '#type' => 'language_select',
      '#title' => $this
        ->t('Target language'),
      '#empty_option' => $this
        ->t('- Any -'),
      '#default_value' => isset($_GET['target_language']) ? $_GET['target_language'] : NULL,
    );
    $form['search_wrapper']['search']['target_status'] = array(
      '#type' => 'select',
      '#title' => $this
        ->t('Target status'),
      '#options' => array(
        'untranslated' => $this
          ->t('Untranslated'),
        'translated' => $this
          ->t('Translated'),
      ),
      '#default_value' => isset($_GET['target_status']) ? $_GET['target_status'] : NULL,
      '#states' => array(
        'invisible' => array(
          ':input[name="search[target_language]"]' => array(
            'value' => '',
          ),
        ),
      ),
    );
    return $form;
  }

  /**
   * Gets overview form header.
   *
   * @return array
   *   Header array definition as expected by theme_tablesort().
   */
  public function overviewFormHeader($type) {
    $header = array(
      'title' => array(
        'data' => $this
          ->t('Title (in source language)'),
      ),
      'config_id' => array(
        'data' => $this
          ->t('Configuration ID'),
      ),
    );
    $header += $this
      ->getLanguageHeader();
    return $header;
  }

  /**
   * Builds a table row for overview form.
   *
   * @param \Drupal\Core\Config\Entity\ConfigEntityInterface $entity
   *   Data needed to build the list row.
   *
   * @return array
   *   A single table row for the overview.
   */
  public function overviewRow(ConfigEntityInterface $entity) {
    $label = $entity
      ->label() ?: $this
      ->t('@type: @id', array(
      '@type' => $entity
        ->getEntityTypeId(),
      '@id' => $entity
        ->id(),
    ));

    // Get current job items for the entity to determine translation statuses.
    $source_lang = $entity
      ->language()
      ->getId();
    $current_job_items = tmgmt_job_item_load_latest('config', $entity
      ->getEntityTypeId(), $entity
      ->getConfigDependencyName(), $source_lang);
    $row['id'] = $entity
      ->id();
    $definition = \Drupal::entityTypeManager()
      ->getDefinition($entity
      ->bundle());
    $row['config_id'] = $definition
      ->getConfigPrefix() . '.' . $entity
      ->id();
    if ($entity
      ->hasLinkTemplate('edit-form')) {
      $row['title'] = $entity
        ->toLink($label, 'edit-form');
    }
    else {

      // If the entity doesn't have a link we display a label.
      $row['title'] = $label;
    }

    // Load entity translation specific data.
    foreach (\Drupal::languageManager()
      ->getLanguages() as $langcode => $language) {
      $translation_status = 'current';
      if ($langcode == $source_lang) {
        $translation_status = 'original';
      }
      elseif (!$this
        ->isTranslated($langcode, $entity
        ->getConfigDependencyName())) {
        $translation_status = 'missing';
      }

      // @todo Find a way to support marking configuration translations as outdated.
      $build = $this
        ->buildTranslationStatus($translation_status, isset($current_job_items[$langcode]) ? $current_job_items[$langcode] : NULL);
      $row['langcode-' . $langcode] = [
        'data' => \Drupal::service('renderer')
          ->render($build),
        'class' => array(
          'langstatus-' . $langcode,
        ),
      ];
    }
    return $row;
  }

  /**
   * Builds a table row for simple configuration.
   *
   * @param array $definition
   *   A definition.
   *
   * @return array
   *   A single table row for the overview.
   */
  public function overviewRowSimple(array $definition) {

    // Get current job items for the entity to determine translation statuses.
    $config_id = $definition['names'][0];
    $source_lang = \Drupal::config($definition['names'][0])
      ->get('langcode') ?: 'en';
    $current_job_items = tmgmt_job_item_load_latest('config', ConfigSource::SIMPLE_CONFIG, $definition['id'], $source_lang);
    $row = array(
      'id' => $definition['id'],
      'title' => $definition['title'],
    );

    // Load entity translation specific data.
    foreach (\Drupal::languageManager()
      ->getLanguages() as $langcode => $language) {
      $translation_status = 'current';
      if ($langcode == $source_lang) {
        $translation_status = 'original';
      }
      elseif (!$this
        ->isTranslated($langcode, $config_id)) {
        $translation_status = 'missing';
      }

      // @todo Find a way to support marking configuration translations as outdated.
      $build = $this
        ->buildTranslationStatus($translation_status, isset($current_job_items[$langcode]) ? $current_job_items[$langcode] : NULL);
      $row['langcode-' . $langcode] = [
        'data' => \Drupal::service('renderer')
          ->render($build),
        'class' => array(
          'langstatus-' . $langcode,
        ),
      ];
    }
    return $row;
  }

  /**
   * Checks, if an entity is translated.
   *
   * @param string $langcode
   *   Language code.
   * @param string $name
   *   Configuration name.
   *
   * @return bool
   *   Returns TRUE, if it is translatable.
   */
  public function isTranslated($langcode, $name) {
    $config = \Drupal::languageManager()
      ->getLanguageConfigOverride($langcode, $name);
    return !$config
      ->isNew();
  }

  /**
   * {@inheritdoc}
   */
  public function overviewForm(array $form, FormStateInterface $form_state, $type) {
    $form = parent::overviewForm($form, $form_state, $type);

    // Load search property params which will be passed into
    $search_property_params = array();
    $exclude_params = array(
      'q',
      'page',
    );
    foreach (\Drupal::request()->query
      ->all() as $key => $value) {

      // Skip exclude params, and those that have empty values, as these would
      // make it into query condition instead of being ignored.
      if (in_array($key, $exclude_params) || $value === '') {
        continue;
      }
      $search_property_params[$key] = $value;
    }

    // If the source is of type '_simple_config', we get all definitions that
    // don't have an entity type and display them through overviewRowSimple().
    if ($type == ConfigSource::SIMPLE_CONFIG) {
      $definitions = $this
        ->getFilteredSimpleConfigDefinitions($search_property_params);
      foreach ($definitions as $definition_id => $definition) {
        $form['items']['#options'][$definition_id] = $this
          ->overviewRowSimple($definition);
      }
    }
    else {
      foreach ($this
        ->getTranslatableEntities($type, $search_property_params) as $entity) {
        $form['items']['#options'][$entity
          ->getConfigDependencyName()] = $this
          ->overviewRow($entity);
      }
    }
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function overviewFormValidate(array $form, FormStateInterface $form_state, $type) {
    $target_language = $form_state
      ->getValue(array(
      'search',
      'target_language',
    ));
    if (!empty($target_language) && $form_state
      ->getValue(array(
      'search',
      'langcode',
    )) == $target_language) {
      $form_state
        ->setErrorByName('search[target_language]', $this
        ->t('The source and target languages must not be the same.'));
    }
  }

  /**
   * Gets translatable entities of a given type.
   *
   * Additionally you can specify entity property conditions, pager and limit.
   *
   * @param string $entity_type_id
   *   Drupal entity type.
   * @param array $property_conditions
   *   Entity properties. There is no value processing so caller must make sure
   *   the provided entity property exists for given entity type and its value
   *   is processed.
   *
   * @return \Drupal\Core\Config\Entity\ConfigEntityInterface[]
   *   Array of translatable entities.
   */
  function getTranslatableEntities($entity_type_id, $property_conditions = array()) {
    $target_status = NULL;
    $target_language = NULL;

    // We unset the target_status and target_language, because we can't filter
    // them this way.
    if (isset($property_conditions['target_status']) && isset($property_conditions['target_language'])) {
      $target_status = $property_conditions['target_status'];
      $target_language = $property_conditions['target_language'];
    }
    unset($property_conditions['target_status']);
    unset($property_conditions['target_language']);
    $search = \Drupal::entityQuery($entity_type_id);
    $search
      ->accessCheck(TRUE);

    // unset($property_conditions['target_status']);
    foreach ($property_conditions as $property_name => $property_value) {
      $search
        ->condition($property_name, $property_value, 'CONTAINS');
    }
    $result = $search
      ->execute();
    $entities = array();
    if (!empty($result)) {

      // Load the entities.
      $entities = \Drupal::entityTypeManager()
        ->getStorage($entity_type_id)
        ->loadMultiple($result);

      // @todo Optimize the code below (code duplication).
      // Remove all entities, that are already translated, because we are looking
      // for untranslated entities.
      if ($target_status == 'untranslated') {
        $entities = array_filter($entities, function (ConfigEntityInterface $entity) use ($target_language) {
          return !$this
            ->isTranslated($target_language, $entity
            ->getConfigDependencyName());
        });
      }
      elseif ($target_status == 'translated') {
        $entities = array_filter($entities, function (ConfigEntityInterface $entity) use ($target_language) {
          return $this
            ->isTranslated($target_language, $entity
            ->getConfigDependencyName());
        });
      }
    }
    return $entities;
  }

  /**
   * Filter translatable definitions.
   *
   * @param array $search_properties
   *   Search properties that are going to be used for the filter.
   *
   * @return \Drupal\Core\Entity\EntityTypeInterface[]
   *   Array of translatable definitions.
   */
  public function getFilteredSimpleConfigDefinitions($search_properties = array()) {
    $definitions = \Drupal::service('plugin.manager.config_translation.mapper')
      ->getDefinitions();
    $definitions = array_filter($definitions, function ($definition) use ($search_properties) {
      if (isset($definition['entity_type'])) {
        return FALSE;
      }
      if (isset($search_properties['name']) && strpos(strtolower($definition['title']), strtolower($search_properties['name'])) === FALSE) {
        return FALSE;
      }
      if (isset($search_properties['target_language'])) {
        if ($search_properties['target_status'] == 'translated' && !$this
          ->isTranslated($search_properties['target_language'], $definition['names'][0])) {
          return FALSE;
        }
        if ($search_properties['target_status'] == 'untranslated' && $this
          ->isTranslated($search_properties['target_language'], $definition['names'][0])) {
          return FALSE;
        }
      }
      return TRUE;
    });
    return $definitions;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
ConfigSourcePluginUi::$pagerLimit public property Entity source list items limit.
ConfigSourcePluginUi::getFilteredSimpleConfigDefinitions public function Filter translatable definitions.
ConfigSourcePluginUi::getTranslatableEntities function Gets translatable entities of a given type.
ConfigSourcePluginUi::isTranslated public function Checks, if an entity is translated.
ConfigSourcePluginUi::overviewForm public function Builds the overview form for the source entities. Overrides SourcePluginUiBase::overviewForm
ConfigSourcePluginUi::overviewFormHeader public function Gets overview form header.
ConfigSourcePluginUi::overviewFormValidate public function Overrides SourcePluginUiBase::overviewFormValidate
ConfigSourcePluginUi::overviewRow public function Builds a table row for overview form.
ConfigSourcePluginUi::overviewRowSimple public function Builds a table row for simple configuration.
ConfigSourcePluginUi::overviewSearchFormPart public function Builds search form for entity sources overview. Overrides SourcePluginUiBase::overviewSearchFormPart
SourcePluginUiBase::buildTranslationStatus function Builds the translation status render array with source and job item status.
SourcePluginUiBase::getLanguageHeader protected function Gets languages form header.
SourcePluginUiBase::hook_views_default_views public function Overrides SourcePluginUiInterface::hook_views_default_views
SourcePluginUiBase::overviewFormSubmit public function Submit handler for the source entities overview form.
SourcePluginUiBase::overviewSearchFormRedirect public function Performs redirect with search params appended to the uri.
SourcePluginUiBase::reviewDataItemElement public function Form callback for the data item element form. Overrides SourcePluginUiInterface::reviewDataItemElement
SourcePluginUiBase::reviewForm public function Form callback for the job item review form. Overrides SourcePluginUiInterface::reviewForm 1
SourcePluginUiBase::reviewFormSubmit public function Submit callback for the job item review form. Overrides SourcePluginUiInterface::reviewFormSubmit 1
SourcePluginUiBase::reviewFormValidate public function Validation callback for the job item review form. Overrides SourcePluginUiInterface::reviewFormValidate