Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
novicell/custom_forms / src / Form / CustomFormFieldListForm.php
Size: Mime:
<?php

namespace Drupal\custom_forms\Form;

use Drupal\Component\Serialization\Json;
use Drupal\Core\Database\Connection;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Template\Attribute;
use Drupal\Core\Url;
use Drupal\custom_forms\CustomFormItem;
use Drupal\custom_forms\CustomFormItemFactory;
use Drupal\custom_forms\Entity\CustomForm;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Form controller for the custom form entity fields.
 */
class CustomFormFieldListForm extends FormBase {

  /**
   * @var \Drupal\Core\Database\Connection
   *   The database connection.
   */
  private $connection;

  /**
   * The entity being used by this form.
   *
   * @var CustomForm
   */
  protected $entity;

  /**
   * The factory in charge of CRUD operations for custom form items.
   *
   * @var \Drupal\custom_forms\CustomFormItemFactory
   */
  protected $itemFactory;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('database'),
      $container->get('custom_forms.factory.item')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function __construct(Connection $connection, CustomFormItemFactory $item_factory) {
    $this->connection = $connection;
    $attributes = \Drupal::request()->attributes;
    $this->entity = $attributes->get('custom_form');
    $this->itemFactory = $item_factory;
  }

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

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $form['#attributes']['class'][] = 'custom-forms-fields';
    $form['#attached']['library'][] = 'custom_forms/admin-style';
    $form['#attached']['library'][] = 'core/drupal.dialog.ajax';
    $form['#prefix'] = '<div id="custom-form__field-list">';
    $form['#suffix'] = '</div>';
    $form['#action'] = Url::fromRoute('entity.custom_form.fields_form', ['custom_form' => $this->entity->id()])->toString();

    $items          = $this->itemFactory->getFormItemsAsTree($this->entity, TRUE);
    $table_headers  = $this->generateTableHeaders();

    $form['items-table'] = [
      '#type' => 'table',
      '#header' => $table_headers,
      '#empty' => $this->t('No fields found for this form.'),
      '#attributes' => [
        'class' => [
          'custom-forms-fields-table',
        ],
      ],
      '#tabledrag' => [
        [
          'action' => 'match',
          'relationship' => 'parent',
          'group' => 'row-pid',
          'source' => 'row-id',
          'hidden' => TRUE, // Hides the WEIGHT and PARENT columns.
          'limit' => FALSE,
        ],
        [
          'action' => 'order',
          'relationship' => 'sibling',
          'group' => 'row-weight'
        ]
      ],
    ];

    if (!empty($items)) {
      /** @var \Drupal\custom_forms\CustomFormItem $item */
      foreach ($items as $item) {
        $form['items-table'][$item->id()] = $this->generateTableRow($item);
      }
    }


    $form['actions'] = [
      '#type' => 'actions',
    ];

    $form['actions']['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Save'),
      '#attributes' => [
        'class' => [
          'button',
          'button-action',
          'button--primary',
        ]
      ],
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  protected function actionsElement(array $form, FormStateInterface $form_state) {
    $element = parent::actionsElement($form, $form_state);

    // We don't want the ability to delete the form from the fields page.
    unset($element['delete']);

    return $element;
  }

  /**
   * Generates the table headers for the item table.
   *
   * @return array
   */
  private function generateTableHeaders() {
    return [
      [
        'data' => $this->t('Name'),
        'class' => [
          'header-field-name',
        ],
        'data-secondary-header' => $this->t('Machine name')
      ],
      [
        'data' => $this->t('Visibility'),
        'class' => [
          'header-visibility',
        ],
      ],
      $this->t('Type'),
      $this->t('Operations'),
      $this->t('Weight'),
      $this->t('Parent ID'),
    ];
  }

  /**
   * @param \Drupal\custom_forms\CustomFormItem $item
   *
   * @return array
   */
  private function generateTableRow($item) {
    $row = [];
    // TableDrag: Mark the table row as draggable.
    $row['#attributes']['class'][] = 'draggable';
    // TableDrag: Sort the table row according to its existing/configured
    // weight.
    $row['#weight'] = $item->getWeight();

    // Indent item on load.
    if (!empty($item->getDepth()) && $item->getDepth() > 0) {
      $indentation = [
        '#theme' => 'indentation',
        '#size' => $item->getDepth(),
      ];
    }

    // If the item is a field, give it the class to prevent nesting items under it.
    if ($item->getType() === 'field') {
      $row['#attributes']['class'][] = 'tabledrag-leaf';
      $row['#attributes']['class'][] = 'custom-forms-field';
    } else {
      $row['#attributes']['class'][] = 'custom-forms-group';
    }
    // If the item settings specify that it is a root item, give it the class to
    // prevent it being nested under other items.
    if ((boolean) $item->getSetting('is_root_item')) {
      $row['#attributes']['class'][] = 'tabledrag-root';
    }

    // Add the actual table data.
    $label_attributes = new Attribute();
    $label_attributes->addClass('label');
    if ($item->getType() === 'group') {
      $label_attributes->addClass('group-label');
    }
    $name = [
      '#theme' => 'custom_field_list__field_name',
      '#label' => $item->getSetting('label'),
      '#machine_name' => $item->getMachineName(),
      '#label_attributes' => $label_attributes,
    ];

    // Hide the machine name from select fields.
    if ($item->isMachineNameHidden()) {
      unset($name['#machine_name']);
    }

    $row['name'] = [
      '#markup' => \Drupal::service('renderer')->render($name),
      '#prefix' => !empty($indentation) ? \Drupal::service('renderer')->render($indentation) : '',
    ];

    $row['name']['id'] = [
      '#type' => 'value',
      '#value' => $item->getLangcode(),
      '#parents' => ['items-table', $item->id(), 'langcode'],
    ];
    if ($item->getType() === 'field') {
      $row['visibility'] = [
        '#theme' => 'custom_field_list__field_visibility',
        '#visibility' => $item->getSetting('visibility') === 'hidden'? FALSE : TRUE,
      ];
    } else {
      $row['visibility'] = [];
    }
    $row['type'] = [
      '#markup' => !empty($item->getPluginDefinition()['label'])? $item->getPluginDefinition()['label'] : '',
    ];

    $field_operations = [
      'edit' => [
        'title' => $this->t('Settings'),
        'url' => Url::fromRoute('custom_form.field_list.item_settings_form', ['custom_form' => $item->getFormId(), 'item' => $item->id()]),
        'attributes' => [
          'class' => [
            'use-ajax'
          ],
          'data-dialog-type' => 'dialog',
          'data-dialog-renderer' => 'off_canvas',
          'data-dialog-options' => Json::encode([
            'width' => '30%'
          ]),
        ],
      ],
    ];

    // Invoke hook for altering field operations.
    \Drupal::moduleHandler()->alter('custom_forms_item_operations', $field_operations, $item);

    $field_operations['delete'] = [
      'title' => $this->t('Delete'),
      'url' => Url::fromRoute('custom_form.field_list.delete_item_form', ['custom_form' => $item->getFormId(), 'item' => $item->id()])
    ];

    $row['operations'] = [
      '#type' => 'operations',
      '#links' => $field_operations
    ];

    // If an item plugin definition has no UI, disable operations.
    if (isset($item->getPluginDefinition()['no_ui']) && $item->getPluginDefinition()['no_ui']) {
      $row['operations'] = [];
    }

    $row['weight'] = [
      '#type' => 'weight',
      '#title' => $this->t('Weight'),
      '#title_display' => 'invisible',
      '#default_value' => $item->getWeight(),
      // Classify the weight element for #tabledrag.
      '#attributes' => [
        'class' => ['row-weight'],
      ],
    ];
    $row['parent']['revision'] = [
      '#parents' => ['items-table', $item->id(), 'revision'],
      '#type' => 'value',
      '#value' => $item->getRevision(),
      '#attributes' => [
        'class' => ['row-id'],
      ],
    ];
    $row['parent']['id'] = [
      '#parents' => ['items-table', $item->id(), 'id'],
      '#type' => 'hidden',
      '#value' => $item->id(),
      '#attributes' => [
        'class' => ['row-id'],
      ],
    ];
    $row['parent']['pid'] = [
      '#parents' => ['items-table', $item->id(), 'pid'],
      '#type' => 'number',
      '#size' => 3,
      '#min' => 0,
      '#title' => $this->t('Parent ID'),
      '#title_display' => 'invisible',
      '#default_value' => $item->getParentId(),
      '#attributes' => [
        'class' => ['row-pid'],
      ],
    ];

    return $row;
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $trigger = $form_state->getTriggeringElement();
    $request = \Drupal::request();

    if ((isset($trigger['#op']) && $trigger['#op'] === 'ajax_submit') || $request->isXmlHttpRequest()) {
      return;
    }

    $values = $form_state->cleanValues()->getValues();

    if (!empty($values['items-table'])) {
      // Update weight and parent ID values.
      foreach ($values['items-table'] as $id => $item) {
        $customFormItem = $this->itemFactory->loadItem($item['id'], $item['revision'], NULL, $item['langcode']);
        // If parent ID and weight have not changed, skip this field.
        if ($item['pid'] === $customFormItem->getParentId() && $item['weight'] === $customFormItem->getWeight()) {
          continue;
        }
        // We need to make sure that we don't allow items to be nested with a
        // field as parent, as that is not supported. This is mainly a fall-
        // back in case the javascript fails, or makes some mistakes.
        if ($item['pid'] > 0) {
          $parent = $this->itemFactory->loadItem($item['pid'], NULL, NULL, $item['langcode']);
          // If the parent is a field, we set parent ID to 0 to remove any
          // nesting.
          if ($parent->getType() === 'field') {
            $pid = 0;
          } else {
            // If not a field, we simply allow the parent value.
            $pid = $item['pid'];
          }
        } else {
          $pid = $item['pid'];
        }

        $query = $this->connection->update('custom_forms__items');
        $query->condition('id', $id);
        $query->condition('revision', $item['revision']);
        $query->condition('langcode', $item['langcode']);
        $query->condition('form_revision', $customFormItem->getFormRevisionId());
        $query->fields([
          'weight' => $item['weight'],
          'pid' => $pid
        ]);
        $query->execute();
      }
    }
  }
}