You are here

MaestroTemplateFormBase.php in Maestro 3.x

Same filename and directory in other branches
  1. 8.2 src/Form/MaestroTemplateFormBase.php

File

src/Form/MaestroTemplateFormBase.php
View source
<?php

namespace Drupal\maestro\Form;

use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Form\FormStateInterface;
use Drupal\maestro\Engine\MaestroEngine;
use Drupal\views\Views;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\CloseModalDialogCommand;

/**
 * Class MaestroTemplateFormBase.
 *
 * @package Drupal\maestro\Form
 *
 * @ingroup maestro
 */
class MaestroTemplateFormBase extends EntityForm {

  /**
   * Overrides Drupal\Core\Entity\EntityFormController::form().
   *
   * Builds the entity add/edit form.
   *
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form's form state.
   *
   * @return array
   *   An associative array containing the Template add/edit form.
   */
  public function buildForm(array $form, FormStateInterface $form_state) {

    // Get anything we need form the base class.
    $form = parent::buildForm($form, $form_state);
    $isModal = $this
      ->getRequest()
      ->get('is_modal');
    $Template = $this->entity;

    // If we're modal, we remove the delete action.
    if ($isModal == 'modal') {
      unset($form['actions']['delete']);
    }

    // Build the form.
    $form['label'] = [
      '#type' => 'textfield',
      '#title' => $this
        ->t('Label'),
      '#maxlength' => 255,
      '#default_value' => $Template
        ->label(),
      '#required' => TRUE,
    ];
    $form['id'] = [
      '#type' => 'machine_name',
      '#title' => $this
        ->t('Machine name'),
      '#default_value' => $Template
        ->id(),
      '#machine_name' => [
        'exists' => [
          get_class($this),
          'exists',
        ],
      ],
    ];

    // The notion of App Groups will be carried across to D8 Maestro, however we
    // will simply hide for the time being as they were used sparingly in the Drupal 7 version.
    $form['app_group'] = [
      '#type' => 'hidden',
      '#title' => $this
        ->t('App Group'),
      '#maxlength' => 255,
      '#default_value' => isset($Template->app_group) ? $Template->app_group : 0,
      '#required' => TRUE,
    ];

    // Canvas height is a default value of 900 pixels.
    $form['canvas_height'] = [
      '#type' => 'textfield',
      '#title' => $this
        ->t('Canvas Height in pixels'),
      '#maxlength' => 255,
      '#default_value' => isset($Template->canvas_height) ? $Template->canvas_height : 900,
      '#required' => TRUE,
    ];

    // Default is 800 px wide.
    $form['canvas_width'] = [
      '#type' => 'textfield',
      '#title' => $this
        ->t('Canvas Width in pixels'),
      '#maxlength' => 255,
      '#default_value' => isset($Template->canvas_width) ? $Template->canvas_width : 800,
      '#required' => TRUE,
    ];

    // Default is to not show details.
    $form['show_details'] = [
      '#type' => 'checkbox',
      '#title' => $this
        ->t("Show details of this template's process in Task Console details?"),
      '#description' => $this
        ->t('When checked, the task console will enable the showing of details of the process/task.'),
      '#default_value' => isset($Template->show_details) ? $Template->show_details : 0,
    ];
    $form['show_details_area'] = [
      '#type' => 'fieldset',
      '#title' => $this
        ->t('Details Configuration'),
      '#states' => [
        'visible' => [
          ':input[name="show_details"]' => [
            'checked' => TRUE,
          ],
        ],
      ],
    ];
    $all_views = Views::getAllViews();
    $options = [
      '' => $this
        ->t('Select View'),
    ];
    foreach ($all_views as $machine_name => $view) {
      $options[$machine_name] = $view
        ->label();
    }
    $form['show_details_area']['add_view'] = [
      '#type' => 'select',
      '#title' => $this
        ->t('Add a view to the details panel.'),
      '#description' => $this
        ->t('You can add a view to be displayed in the details panel in the task console. QueueID and ProcessID are passed to the view as arguments.'),
      '#default_value' => '',
      '#options' => $options,
      '#required' => FALSE,
      '#states' => [
        'visible' => [
          ':input[name="show_details"]' => [
            'checked' => TRUE,
          ],
        ],
      ],
      '#ajax' => [
        'callback' => '::fetchViewsDisplays',
        'wrapper' => 'dropdown-views-bundles-replace',
      ],
    ];

    // Need to do an auto-lookup to get the view's display only cone the add_view has changed.
    $form['show_details_area']['add_view_display'] = [
      '#type' => 'select',
      '#title' => $this
        ->t('Select the view display.'),
      '#description' => $this
        ->t('The display of the view you wish to add.'),
      '#default_value' => '',
      '#options' => [],
      '#required' => FALSE,
      '#states' => [
        'visible' => [
          ':input[name="show_details"]' => [
            'checked' => TRUE,
          ],
          ':input[name="add_view"]' => [
            '!value' => '',
          ],
        ],
      ],
      '#validated' => TRUE,
      '#prefix' => '<div id="dropdown-views-bundles-replace">',
      '#suffix' => '</div>',
    ];
    $form['show_details_area']['views'] = [
      '#type' => 'details',
      '#title' => $this
        ->t('Views attached to details output'),
      '#prefix' => '<div id="views-replace">',
      '#suffix' => '</div>',
      '#open' => TRUE,
      '#states' => [
        'visible' => [
          ':input[name="show_details"]' => [
            'checked' => TRUE,
          ],
        ],
      ],
    ];

    // Generate the list of views attached with the option to delete only.
    $views_array = [];
    if (isset($this->entity->views_attached)) {
      foreach ($this->entity->views_attached as $key => $view_information) {
        $display = explode(';', $view_information['view_display']);
        $views_array[$view_information['view_weight']] = [
          'machine_name' => $view_information['view_machine_name'],
          'label' => Views::getView($view_information['view_machine_name'])->storage
            ->label(),
          'view_display' => isset($display[1]) ? $display[1] : '',
        ];
      }
    }

    // Now have a sorted by weight list of views.  Generate the table.
    $form['show_details_area']['views']['views_attached_to_template'] = [
      '#type' => 'table',
      '#header' => [
        $this
          ->t('Name'),
        $this
          ->t('Machine name'),
        $this
          ->t('Display'),
        $this
          ->t('Weight'),
        $this
          ->t('Remove'),
      ],
      '#empty' => $this
        ->t('There are no attached views'),
      '#tableselect' => FALSE,
      '#tabledrag' => [
        [
          'action' => 'order',
          'relationship' => 'sibling',
          'group' => 'views-attached-to-template-order-weight',
        ],
      ],
    ];
    foreach ($views_array as $weight => $view) {
      $form['show_details_area']['views']['views_attached_to_template'][$weight]['#attributes']['class'][] = 'draggable';
      $form['show_details_area']['views']['views_attached_to_template'][$weight]['#weight'] = $weight;
      $form['show_details_area']['views']['views_attached_to_template'][$weight]['name'] = [
        '#plain_text' => $view['label'],
      ];
      $form['show_details_area']['views']['views_attached_to_template'][$weight]['machine_name'] = [
        '#plain_text' => $view['machine_name'],
      ];
      $form['show_details_area']['views']['views_attached_to_template'][$weight]['display'] = [
        '#plain_text' => $view['view_display'],
      ];
      $form['show_details_area']['views']['views_attached_to_template'][$weight]['weight'] = [
        '#type' => 'weight',
        '#title' => $this
          ->t('Order'),
        '#title_display' => 'invisible',
        '#default_value' => $weight,
        // Classify the weight element for #tabledrag.
        '#attributes' => [
          'class' => [
            'views-attached-to-template-order-weight',
          ],
        ],
      ];
      $form['show_details_area']['views']['views_attached_to_template'][$weight]['delete'] = [
        '#type' => 'checkbox',
        '#title' => $this
          ->t('Delete'),
        '#title_display' => 'none',
        '#required' => FALSE,
      ];
    }

    // Default is 0.
    $form['default_workflow_timeline_stage_count'] = [
      '#type' => 'textfield',
      '#title' => $this
        ->t('The default number of stages you wish to show this workflow having'),
      '#description' => $this
        ->t('Default 0 will show no stages in the task console. Process variable for worflow_timeline_stage_count will
          be set with the value configured'),
      '#maxlength' => 3,
      '#size' => 3,
      '#default_value' => isset($Template->default_workflow_timeline_stage_count) ? $Template->default_workflow_timeline_stage_count : 0,
      '#required' => TRUE,
    ];

    // Variable definitions:
    // Complex type of machine name and variable value.
    $form['variables'] = [
      '#type' => 'details',
      '#title' => $this
        ->t('Variables'),
      '#group' => 'templatevariables',
      '#tree' => TRUE,
      '#prefix' => '<div id="multi-replace">',
      '#suffix' => '</div>',
    ];
    $key = 0;

    // See /src/Form/MaestroTemplateAddForm.php.
    $mandatory_variables = [
      'initiator',
      'workflow_timeline_stage_count',
      'workflow_current_stage',
      'workflow_current_stage_message',
    ];
    if (isset($this->entity->variables)) {
      foreach ($this->entity->variables as $key => $variable) {
        $disabled = FALSE;
        $attributes = NULL;
        $class = 'maestro-existing-variable';
        if (array_search($key, $mandatory_variables) !== FALSE) {

          // Do not allow the mandatory variables to be deleted.
          $disabled = TRUE;
          $class = 'maestro-existing-variable-no-delete';
          $attributes = [
            'title' => t("You cannot delete this variable.  This variable is required by Maestro."),
          ];
        }
        $form['variables'][$key]['delete'] = [
          '#type' => 'checkbox',
          '#title' => $this
            ->t('Delete'),
          '#title_display' => 'before',
          '#required' => FALSE,
          '#prefix' => '<div class="clearfix ' . $class . '">',
          '#disabled' => $disabled,
          '#attributes' => $attributes,
        ];
        $form['variables'][$key]['variable_id'] = [
          '#type' => 'machine_name',
          '#title' => $this
            ->t('Variable name'),
          '#default_value' => isset($this->entity->variables[$key]['variable_id']) ? $this->entity->variables[$key]['variable_id'] : '',
          '#machine_name' => [
            'exists' => [
              get_class($this),
              'exists',
            ],
          ],
          '#required' => FALSE,
          '#disabled' => $disabled,
        ];
        $form['variables'][$key]['variable_value'] = [
          '#type' => 'textfield',
          '#title' => $this
            ->t('Value'),
          '#maxlength' => 255,
          '#default_value' => isset($this->entity->variables[$key]['variable_value']) ? $this->entity->variables[$key]['variable_value'] : '',
          '#required' => FALSE,
          '#suffix' => '</div>',
        ];
      }
    }

    // Form elements for a new variable.
    $form['variables']['new_fieldset'] = [
      '#type' => 'fieldset',
      '#title' => 'Create New Variable',
    ];
    $form['variables']['new_fieldset']['new']['variable_id'] = [
      '#type' => 'machine_name',
      '#title' => $this
        ->t('Variable name'),
      '#default_value' => '',
      '#machine_name' => [
        'exists' => [
          get_class($this),
          'exists',
        ],
      ],
      '#required' => FALSE,
    ];
    $form['variables']['new_fieldset']['new']['variable_value'] = [
      '#type' => 'textfield',
      '#title' => $this
        ->t('Value'),
      '#maxlength' => 255,
      '#default_value' => '',
      '#required' => FALSE,
    ];
    $form['#attached']['library'][] = 'maestro/maestro-engine-css';
    return $form;
  }

  /**
   * Fetches the views displays associated to this template form.
   */
  public function fetchViewsDisplays(array $form, FormStateInterface $form_state) {
    $options = [];
    if ($form_state
      ->getValue('add_view') != '') {
      $view = Views::getView($form_state
        ->getValue('add_view'));
      if ($view) {
        foreach ($view->storage
          ->get('display') as $display_machine_name => $arr) {
          $options[$display_machine_name . ';' . $arr['display_title']] = $arr['display_title'];
        }
      }
      else {
        $options[''] = $this
          ->t('Please reselect View');
      }
      $form['show_details_area']['add_view_display']['#options'] = $options;
    }
    else {
      $form['show_details_area']['add_view_display'] = [
        '#display' => FALSE,
        '#prefix' => '<div id="dropdown-views-bundles-replace">',
        '#suffix' => '</div>',
      ];
    }
    return $form['show_details_area']['add_view_display'];
  }

  /**
   * Internal method callback to determine if a template already exists.
   */
  public static function exists($submitted_value, array $element, FormStateInterface $form_state) {
    $templates = MaestroEngine::getTemplates();
    if (array_key_exists($submitted_value, $templates)) {
      return TRUE;
    }
    return FALSE;
  }

  /**
   * Overrides Drupal\Core\Entity\EntityFormController::actions().
   *
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form's form state.
   *
   * @return array
   *   An array of supported actions for the current entity form.
   */
  protected function actions(array $form, FormStateInterface $form_state) {
    $actions = parent::actions($form, $form_state);
    $actions['submit']['#value'] = $this
      ->t('Save');
    return $actions;
  }

  /**
   * Overrides Drupal\Core\Entity\EntityFormController::validate().
   *
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form's form state.
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
    parent::validateForm($form, $form_state);
    if ($form_state
      ->getValue('add_view') && $form_state
      ->getValue('add_view') != '') {
      $view = Views::getView($form_state
        ->getValue('add_view'));
      if (!$view) {
        $form_state
          ->setErrorByName('add_view', $this
          ->t('An invalid view was entered'));
      }
    }
  }

  /**
   * Overrides Drupal\Core\Entity\EntityFormController::save().
   *
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form's form state.
   */
  public function save(array $form, FormStateInterface $form_state) {
    $isModal = $this
      ->getRequest()
      ->get('is_modal');

    // Remove the 'new' variable values here so that the save, well, saves them.
    // form_state->values['variables'] holds the saved variables
    // we need to ensure that the variables at this stage, since the parent validation has happened
    // is properly formatted to remove the 'new' key and add that to the numerical keys.
    $variables = $form_state
      ->getValue('variables');
    $new = $variables['new_fieldset']['new'];
    unset($variables['new_fieldset']);
    if (isset($new['variable_id']) && !empty($new['variable_id'])) {

      // We have a new variable here.
      $variables[$new['variable_id']] = $new;
    }

    // Now to handle deletion.
    foreach ($variables as $key => $variable) {
      if (array_key_exists('delete', $variable) && isset($variable['delete'])) {
        if ($variable['delete'] == 1) {
          unset($variables[$key]);
        }
        else {
          unset($variables[$key]['delete']);
        }
      }
    }
    $this->entity->variables = $variables;

    // Now handle attached views and handle the ordering properly.
    $views_ordering_from_form = $form_state
      ->getValue('views_attached_to_template');
    $existing_views = [];
    if (isset($this->entity->views_attached)) {
      foreach ($this->entity->views_attached as $machine_name => $arr) {
        $existing_views[$arr['view_weight']] = $machine_name;
      }
    }
    $views_ordering = [];
    if (!empty($views_ordering_from_form)) {
      foreach ($views_ordering_from_form as $key => $arr) {
        if (is_numeric($key)) {
          $views_ordering[$arr['weight']] = $existing_views[$key];
          if ($arr['delete']) {
            unset($views_ordering[$arr['weight']]);
          }
        }
      }
    }
    ksort($views_ordering);
    $views_attached = [];
    $lowest_weight = 0;
    foreach ($views_ordering as $weight => $machine_name) {
      if ($weight <= $lowest_weight) {
        $lowest_weight = $weight - 1;
      }
      $views_attached[$machine_name] = [
        'view_machine_name' => $machine_name,
        'view_weight' => $weight,
        'view_display' => $this->entity->views_attached[$machine_name]['view_display'],
      ];
    }

    // Now if there's a new view, attach it.
    if ($form_state
      ->getValue('add_view')) {
      $views_attached[$form_state
        ->getValue('add_view')] = [
        'view_machine_name' => $form_state
          ->getValue('add_view'),
        'view_weight' => $lowest_weight,
        'view_display' => $form_state
          ->getValue('add_view_display'),
      ];
    }
    $this->entity->views_attached = $views_attached;
    $status = $this->entity
      ->save();
    if ($status == SAVED_UPDATED) {

      // If we edited an existing entity...
      \Drupal::messenger()
        ->addMessage(t('Template %label has been updated.', [
        '%label' => $this->entity
          ->label(),
      ]));
      \Drupal::logger('maestro')
        ->notice('Template %label has been updated.', [
        '%label' => $this->entity
          ->label(),
      ]);
      if ($isModal == 'modal') {
        $response = new AjaxResponse();
        $response
          ->addCommand(new CloseModalDialogCommand());
        return $response;
      }
    }
    else {

      // If we created a new entity...
      \Drupal::messenger()
        ->addMessage(t('Template %label has been added.', [
        '%label' => $this->entity
          ->label(),
      ]));
      \Drupal::logger('maestro')
        ->notice('Template %label has been added.', [
        '%label' => $this->entity
          ->label(),
      ]);
      $form_state
        ->setRedirect('entity.maestro_template.list');
    }
  }

}

Classes

Namesort descending Description
MaestroTemplateFormBase Class MaestroTemplateFormBase.