visualn-8.x-1.x-dev/modules/visualn_file_field/src/Plugin/Field/FieldWidget/VisualNWidget.php

modules/visualn_file_field/src/Plugin/Field/FieldWidget/VisualNWidget.php
<?php

// @todo: rename the file to VisualNFileWidget.php
// @todo: fix bugs:
//    @see https://www.drupal.org/project/drupal/issues/2926219
//    @see https://www.drupal.org/project/drupal/issues/2926220

namespace Drupal\visualn_file_field\Plugin\Field\FieldWidget;

use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Render\ElementInfoManagerInterface;
use Drupal\Core\Field\FieldItemListInterface;
//use Drupal\Core\Field\WidgetBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Form\SubformState;
//use Drupal\file\Plugin\Field\FieldWidget\FileWidget;
use Drupal\visualn_file_field\Plugin\FileWidgetWrapper;
use Symfony\Component\HttpFoundation\Request;
use Drupal\visualn\Helpers\VisualNFormsHelper;
use Drupal\Core\Field\WidgetBase;
use Drupal\visualn\Helpers\VisualN;

/**
 * Plugin implementation of the 'visualn_visualn' widget.
 *
 * @FieldWidget(
 *   id = "visualn_file",
 *   label = @Translation("VisualN file"),
 *   field_types = {
 *     "visualn_file"
 *   }
 * )
 */
//class VisualNWidget extends FileWidget {
class VisualNWidget extends FileWidgetWrapper {

  const RAW_RESOURCE_FORMAT_GROUP = 'visualn_file_widget';

  /**
   * {@inheritdoc}
   */
  public static function defaultSettings() {
    return array(
      'visualn_style_id' => '',
      'visualn_data' => '',
    ) + parent::defaultSettings();
  }

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

    return $element;
  }


  /**
   * {@inheritdoc}
   */
  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {

    $element = parent::formElement($items, $delta, $element, $form, $form_state);
    $item = $items[$delta];

    // exclude element with no files uploaded ("add more" button)
    if (empty($item->fids)) {
      return $element;
    }

    // @todo: check the same issue https://drupal.stackexchange.com/questions/235459/get-previous-values-for-inline-entity-form-items-when-parent-form-submitted

    // @todo: Basically it is a hack to keep initial field configuration for selected visualn style
    //    to be able to return to it when user changes selected style and then goes back.
    //    We can avoid overriding $item->visualn_data and visualn_style_id here and just create another
    //    standard object (or an array) to pass the initial config to #process callback (see below
    //    for $element['drawer_container']['#item']).
    //    The issue is related to FileWidet::submit() and maybe FileWidget::extractFormValues().
/*
    if (!isset($item->visualn_data_storage)) {
      $item->visualn_data_storage = $item->visualn_data;
    }
    //$item->visualn_data = $item->visualn_data_storage;
    if (!isset($item->visualn_style_id_storage)) {
      $item->visualn_style_id_storage = $item->visualn_style_id;
    }
    //$item->visualn_style_id = $item->visualn_style_id_storage;
*/

    $visualn_data = !empty($item->visualn_data) ? unserialize($item->visualn_data) : [];
    //$visualn_data = !empty($item->visualn_data_storage) ? unserialize($item->visualn_data_storage) : [];
    $visualn_data['resource_format'] = !empty($visualn_data['resource_format']) ? $visualn_data['resource_format'] : '';

    // @todo: it is a weird behaviour somehow connected with adding/removing new files and rebuilding the
    //    whole widget form. For details see FileWidget::submit(), where it unsets user input with comment
    //    that "The rebuilt elements will have #default_value set appropriately for the current state of the field,
    //    so nothing is lost in doing this."
    // @todo: see FileWidget::submit()

/*
    // We can't use here visual_data key directly because it will be overridden by actual form values.
    $element['visualn_style_id_storage'] = [
      '#type' => 'hidden',
      //'#default_value' => $item->visualn_data_storage ? : $item->visualn_data,
      '#default_value' => $item->visualn_style_id_storage,
    ];
    $element['visualn_data_storage'] = [
      '#type' => 'hidden',
      //'#default_value' => $item->visualn_data_storage ? : $item->visualn_data,
      '#default_value' => $item->visualn_data_storage,
    ];
*/

    // @todo: together with the FileWidget::submit() override in FileWidgetWrapper this
    // is a hack to keep visualn_data between requests (especially when uploading new files)
    // @todo: !important: leaving it like this may potentially cause security issues since
    //    configuration may containt data that shouldn't be accessible by user
    //    (that may have access to the widget form).
/*
    $element['visualn_data'] = [
      '#type' => 'hidden',
      '#default_value' => $item->visualn_data,
    ];
*/
    $element['visualn_data'] = [
      '#type' => 'value',
      '#value' => $item->visualn_data,
    ];



    // @todo: all this deserves more attention, it seems to be very buggy, at least
    //    what relates to retrieving original visualn_style_id and visualn_data from storage



/*
    $initial_config_item = new \StdClass();
    $initial_config_item->visualn_style_id = $item->visualn_style_id_storage;
    $initial_config_item->visualn_data = $item->visualn_data_storage;
*/

    //dsm($item->visualn_style_id);
    //dsm($item->visualn_data);

    // @todo: this is a copy of VisualNResourceWidget so may be moved into the \VisualNFormsHelper class
    //    except the last line with setting #item key to initial_config_item
    //    also here visualn_style_id is used from original value which resembles actual state of the
    //    form. For more detail see FileWidget::submit().

    $definitions = VisualN::getRawResourceFormatsByGroup(self::RAW_RESOURCE_FORMAT_GROUP);


    // @todo: there should be some default behaviour for the 'None' choice (actually, this refers to formatter)
    $resource_formats = [];
    foreach ($definitions as $definition) {
      $resource_formats[$definition['id']] = $definition['label'];
    }

    $element['resource_format'] = [
      '#type' => 'select',
      '#title' => $this->t('Resource format'),
      '#description' => $this->t('The format of the data source'),
      '#default_value' => $visualn_data['resource_format'],
      '#options' => $resource_formats,
      '#empty_option' => $this->t('- None -'),
      '#weight' => '2',
    ];

    // @todo: it is not clear why it saving the values (actually why it works as it should) since
    //    in ResourceGenericDrawingFetcher the drawer_container part should have been moved into a separate #process callback
    $visualn_style_id = $item->visualn_style_id ?: '';
    $field_name = $this->fieldDefinition->getName();
    $ajax_wrapper_id = $field_name . '-' . $delta . '-drawer-config-ajax-wrapper';
    $visualn_styles = visualn_style_options(FALSE);
    asort($visualn_styles);
    $element['visualn_style_id'] = [
      '#title' => t('VisualN style'),
      '#type' => 'select',
      '#default_value' => $visualn_style_id,
      '#empty_option' => t('- Select -'),
      '#options' => $visualn_styles,
      '#weight' => '3',
      '#ajax' => [
        'callback' => [get_called_class(), 'ajaxCallback'],
        'wrapper' => $ajax_wrapper_id,
      ],
    ];
    $element['drawer_container'] = [
      '#prefix' => '<div id="' . $ajax_wrapper_id . '">',
      '#suffix' => '</div>',
      '#weight' => '3',
      '#type' => 'container',
      '#process' => [[$this, 'processDrawerContainerSubform']],
    ];
    // @todo: $item is needed in the #process callback to access drawer_config from field configuration,
    //    maybe there is a better way
    $element['drawer_container']['#item'] = $item;
    //$element['drawer_container']['#item'] = $initial_config_item;

    return $element;
  }


  /**
   * {@inheritdoc}
   */
  public function extractFormValues(FieldItemListInterface $items, array $form, FormStateInterface $form_state) {
    //parent::extractFormValues($items, $form, $form_state);
    //return;

    // @todo: needs to open an issue on the FileWidget?
    // This is not a static method, this is a way to call parent class for FileWidget
    // since FileWidget::extractFormValues() overrides initial $items values with current ones
    // and thus we can't get initial values for drawer_plugin initialization and checking if style select
    // was changed.
    WidgetBase::extractFormValues($items, $form, $form_state);
  }


  /**
   * {@inheritdoc}
   */
  public function massageFormValues(array $values, array $form, FormStateInterface $form_state) {
    //$new_values = parent::massageFormValues($values, $form, $form_state);
    $values = parent::massageFormValues($values, $form, $form_state);
    // @todo: get drawer config values and attach to $new_values
    foreach ($values as &$value) {
      //$value['uri'] = static::getUserEnteredStringAsUri($value['uri']);
      $drawer_config = [];
      if (!empty($value['drawer_config'])) {
        foreach ($value['drawer_config'] as $drawer_config_key => $drawer_config_item) {
          $drawer_config[$drawer_config_key] = $drawer_config_item;
        }
      }

      $drawer_fields = !empty($value['drawer_fields']) ? $value['drawer_fields'] : [];


      $visualn_data = [
        'resource_format' => isset($value['resource_format']) ? $value['resource_format'] : '',
        'drawer_config' => $drawer_config,
        'drawer_fields' => $drawer_fields,
      ];

      // unset the values
      unset($value['drawer_config']);
      unset($value['drawer_fields']);
      unset($value['resource_format']);

      $value['visualn_data'] = serialize($visualn_data);
      // @todo: add comment
      $value += ['options' => []];
    }

    return $values;
  }


  // @todo: this should be static since may not work on field settings form (see fetcher field widget for example)
  // @todo: mostly this is a copy ResourceGenericDrawerFetcher::processDrawerContainerSubform()
  public static function processDrawerContainerSubform(array $element, FormStateInterface $form_state, $form) {
    $item = $element['#item'];
    $visualn_data = !empty($item->visualn_data) ? unserialize($item->visualn_data) : [];
    $visualn_data['resource_format'] = !empty($visualn_data['resource_format']) ? $visualn_data['resource_format'] : '';
    $visualn_data['drawer_config'] = !empty($visualn_data['drawer_config']) ? $visualn_data['drawer_config'] : [];
    $visualn_data['drawer_fields'] = !empty($visualn_data['drawer_fields']) ? $visualn_data['drawer_fields'] : [];

    $configuration = $visualn_data;
    $configuration['visualn_style_id'] = $item->visualn_style_id ?: '';
    //dsm('resource id: ' . $item->visualn_style_id);
    // @todo: add visualn_style_id = "" to widget default config (check) to avoid "?:" check

    $element = VisualNFormsHelper::processDrawerContainerSubform($element, $form_state, $form, $configuration);

    return $element;
  }


  /**
   * {@inheritdoc}
   *
   * return drawerConfigForm via ajax at style change
   * @todo: Add into an interface or add description
   * @todo: Rename method if needed
   */
  public static function ajaxCallback(array $form, FormStateInterface $form_state, Request $request) {
    $triggering_element = $form_state->getTriggeringElement();
    $triggering_element_parents = array_slice($triggering_element['#array_parents'], 0, -1);
    $element = NestedArray::getValue($form, $triggering_element_parents);

    return $element['drawer_container'];
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc