You are here

protected function FeaturesEditForm::buildComponentList in Features 8.3

Same name and namespace in other branches
  1. 8.4 modules/features_ui/src/Form/FeaturesEditForm.php \Drupal\features_ui\Form\FeaturesEditForm::buildComponentList()

Returns the render array elements for the Components selection on the Edit form.

1 call to FeaturesEditForm::buildComponentList()
FeaturesEditForm::buildForm in modules/features_ui/src/Form/FeaturesEditForm.php
Form constructor.

File

modules/features_ui/src/Form/FeaturesEditForm.php, line 427

Class

FeaturesEditForm
Defines the features settings form.

Namespace

Drupal\features_ui\Form

Code

protected function buildComponentList(FormStateInterface $form_state) {
  $element = [
    '#type' => 'fieldset',
    '#title' => $this
      ->t('Components'),
    '#description' => $this
      ->t('Expand each component section and select which items should be included in this feature export.'),
    '#tree' => FALSE,
    '#prefix' => '<div id="features-export-wrapper" class="features-export-wrapper js-features-export-wrapper">',
    '#suffix' => '</div>',
    '#weight' => 1,
  ];

  // Filter field used in javascript, so javascript will unhide it.
  $element['features_filter_wrapper'] = [
    '#type' => 'fieldgroup',
    '#title' => $this
      ->t('Filters'),
    '#title_display' => 'invisible',
    '#tree' => FALSE,
    '#prefix' => '<div id="features-filter" class="features-filter js-features-filter visually-hidden">',
    '#suffix' => '</div>',
    '#weight' => -10,
    '#attributes' => [
      'class' => [
        'features-filter__fieldset',
        'container-inline',
      ],
    ],
  ];
  $element['features_filter_wrapper']['features_filter'] = [
    '#type' => 'textfield',
    '#title' => $this
      ->t('Search'),
    '#hidden' => TRUE,
    '#default_value' => '',
    '#attributes' => [
      'class' => [
        'js-features-filter-input',
      ],
    ],
    '#suffix' => "<span class='features-filter-clear js-features-filter-clear'>" . $this
      ->t('Clear') . "</span>",
  ];
  $element['features_filter_wrapper']['checkall'] = [
    '#type' => 'checkbox',
    '#default_value' => FALSE,
    '#hidden' => TRUE,
    '#title' => $this
      ->t('Select all'),
    '#attributes' => [
      'class' => [
        'features-checkall',
        'js-features-checkall',
        'features-filter',
        'js-features-filter',
      ],
    ],
    '#label_attributes' => [
      'title' => $this
        ->t('Select all currently expanded configurations'),
    ],
  ];
  $element['features_filter_wrapper']['toggle-components'] = [
    '#type' => 'html_tag',
    '#tag' => 'a',
    '#value' => $this
      ->t('Expand all'),
    '#attributes' => [
      'href' => '#',
      'title' => $this
        ->t('Expand/collapse components in order to "Select all".'),
      'class' => [
        'features-toggle-components',
        'features-filter',
        'js-features-filter',
      ],
    ],
  ];
  $element['features_filter_wrapper']['hide-components'] = [
    '#type' => 'select',
    '#title' => $this
      ->t('Hide'),
    '#options' => [
      'included' => $this
        ->t('Normal'),
      'included+groups' => $this
        ->t('Normal (and empty groups)'),
      'added' => $this
        ->t('Added'),
      'detected' => $this
        ->t('Auto detected'),
      'conflict' => $this
        ->t('Conflict'),
    ],
    '#empty_option' => $this
      ->t('- None -'),
    '#default_value' => '',
    '#attributes' => [
      'class' => [
        'features-hide-component',
        'features-filter',
        'js-features-filter',
      ],
      'title' => $this
        ->t('Hide specific Features components'),
    ],
  ];
  $element['features_filter_wrapper']['features_legend'] = [
    '#type' => 'fieldset',
    '#title' => $this
      ->t('Legend'),
    '#tree' => FALSE,
    '#prefix' => '<div id="features-legend">',
    '#suffix' => '</div>',
  ];
  $element['features_filter_wrapper']['features_legend']['legend'] = [
    '#markup' => implode('', [
      "<span class='features-legend-component features-legend-component--included'>" . $this
        ->t('Normal') . '</span> ',
      "<span class='features-legend-component features-legend-component--added'>" . $this
        ->t('Added') . '</span> ',
      "<span class='features-legend-component features-legend-component--detected'>" . $this
        ->t('Auto detected') . '</span> ',
      "<span class='features-legend-component features-legend-component--conflict'>" . $this
        ->t('Conflict') . '</span> ',
    ]),
  ];
  $sections = [
    'included',
    'detected',
    'added',
  ];
  $config_types = $this->featuresManager
    ->listConfigTypes();

  // Generate the export array for the current feature and user selections.
  $export = $this
    ->getComponentList($form_state);
  foreach ($export['components'] as $component => $component_info) {
    $component_items_count = count($component_info['_features_options']['sources']);
    $label = new FormattableMarkup('@component (<span class="component-count js-component-count">@count</span>)', [
      '@component' => $config_types[$component],
      '@count' => $component_items_count,
    ]);
    $count = 0;
    foreach ($sections as $section) {
      $count += count($component_info['_features_options'][$section]);
    }
    $extra_class = $count == 0 ? 'features-export-empty' : '';
    $component_name = str_replace('_', '-', Html::escape($component));
    if ($count + $component_items_count > 0) {
      $element[$component] = [
        '#markup' => '',
        '#tree' => TRUE,
      ];
      $element[$component]['sources'] = [
        '#type' => 'details',
        '#title' => $label,
        '#tree' => TRUE,
        '#open' => FALSE,
        '#attributes' => [
          'class' => [
            'features-export-component',
            'js-features-export-component',
          ],
        ],
        '#prefix' => "<div class='features-export-parent js-features-export-parent js-component--name-{$component}'>",
      ];
      $element[$component]['sources']['selected'] = [
        '#type' => 'checkboxes',
        '#id' => "edit-sources-{$component_name}",
        '#options' => $this
          ->domDecodeOptions($component_info['_features_options']['sources']),
        '#default_value' => $this
          ->domDecodeOptions($component_info['_features_selected']['sources'], FALSE),
        '#attributes' => [
          'class' => [
            'component-select',
          ],
        ],
        '#prefix' => "<span class='components-select js-components-select'>",
        '#suffix' => '</span>',
      ];
      $element[$component]['before-list'] = [
        '#markup' => "<div class='component-list js-component-list features-export-list js-features-export-list {$extra_class}'>",
      ];
      foreach ($sections as $section) {
        $element[$component][$section] = [
          '#type' => 'checkboxes',
          '#options' => !empty($component_info['_features_options'][$section]) ? $this
            ->domDecodeOptions($component_info['_features_options'][$section]) : [],
          '#default_value' => !empty($component_info['_features_selected'][$section]) ? $this
            ->domDecodeOptions($component_info['_features_selected'][$section], FALSE) : [],
          '#attributes' => [
            'class' => [
              'component-' . $section,
              'js-component-' . $section,
            ],
          ],
          '#prefix' => "<span class='components-{$section} js-components-{$section}'>",
          '#suffix' => '</span>',
        ];
      }

      // Close both the before-list as well as the sources div.
      $element[$component]['after-list'] = [
        '#markup' => "</div></div>",
      ];
    }
  }
  $element['features_missing'] = [
    '#theme' => 'item_list',
    '#wrapper_attributes' => [
      'class' => [
        'features-missing-items',
      ],
    ],
    '#items' => $export['missing'],
    '#title' => $this
      ->t('Configuration missing from active site:'),
    '#suffix' => '<div class="description">' . $this
      ->t('Import the feature to create the missing config listed above.') . '</div>',
    '#access' => !empty($export['missing']),
  ];
  return $element;
}