fdk-8.x-1.0/src/FDKHelper.php

src/FDKHelper.php
<?php

namespace Drupal\fdk;


use Drupal\Core\Field\FormatterInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Cache\CacheBackendInterface;

class FDKHelper {

  public static function prepareConfigurationSettings($settings) {
    $defaultSettings = [
      'field_wrapper' => [
        'html_element' => '_default',
        'html_element_other' => '',
        'html_element_classes' => '',
        'html_element_attributes' => '',
        'force_multiple' => FALSE,
      ],
      'field_item_wrapper' => [
        'html_element' => '_default',
        'html_element_other' => '',
        'html_element_link_href' => '',
        'html_element_classes' => '',
        'html_element_attributes' => '',
      ],
      'label' => [
        'html_element' => '_default',
        'html_element_other' => '',
        'html_element_classes' => '',
        'html_element_attributes' => '',
        'value' => '',
      ],
      'field_delimiter' => [
        'enabled' => FALSE,
        'value' => ', ',
        'include_and' => TRUE,
      ],
    ];
    return $settings = NestedArray::mergeDeep($defaultSettings, $settings);
  }

  public static function settingsForm(FormatterInterface $plugin, FieldDefinitionInterface $field_definition, $view_mode, $form, FormStateInterface $form_state) {
    $elements = [];

    $field_info = $field_definition->getFieldStorageDefinition();
    if (!empty($field_info)) {
      $token_types = [$field_definition->getTargetEntityTypeId()];

      $field_name = $field_info->getName();
      $settings = self::prepareConfigurationSettings($plugin->getThirdPartySettings('fdk'));
      $wrapper_options = ['div'];
      $wrapper_options = ['_default' => t('Default')] + array_combine($wrapper_options, $wrapper_options) + ['_other' => t('Other')];

      $elements['fdk'] = [
        '#type' => 'details',
        '#title' => t('Field Display Kit Settings'),
        // Default to open if we have any values to show.
        '#open' => $settings['field_wrapper']['html_element'] != '_default' || $settings['field_item_wrapper']['html_element'] != '_default',
      ];

      $elements['fdk']['field_wrapper'] = [
        '#type' => 'details',
        '#title' => t('Field wrapper'),
        // Default to open if we have any values to show.
        '#open' => $settings['field_wrapper']['html_element'] != '_default',
      ];

      $elements['fdk']['field_wrapper']['html_element'] = [
        '#type' => 'select',
        '#title' => t('Wrapper element'),
        '#description' => t('Select a wrapper element to be used for entire field output.'),
        '#default_value' => $settings['field_wrapper']['html_element'],
        '#options' => $wrapper_options,
      ];

      $elements['fdk']['field_wrapper']['html_element_other'] = [
        '#type' => 'textfield',
        '#description' => t('Enter HTML tag name of the wrapper element.'),
        '#default_value' => $settings['field_wrapper']['html_element_other'],
        '#element_validate' => [ [self::class, 'validateHtmlTagName'] ],
        '#states' => [
          'visible' => [
            ':input[name="fields[' . $field_name . '][settings_edit_form][third_party_settings][fdk][field_wrapper][html_element]"]' => ['value' => '_other'],
          ],
        ],
        '#depended_field' => 'html_element',
      ];

      $elements['fdk']['field_wrapper']['html_element_classes'] = [
        '#type' => 'textfield',
        '#title' => t('Classes'),
        '#description' => t('Enter one or more HTML class names separated by spaces. It can be used to style the field with CSS.'),
        '#default_value' => $settings['field_wrapper']['html_element_classes'],
        '#states' => [
          'visible' => [
            ':input[name="fields[' . $field_name . '][settings_edit_form][third_party_settings][fdk][field_wrapper][html_element]"]' => ['!value' => '_default'],
          ],
        ],
      ];

      $elements['fdk']['field_wrapper']['html_element_attributes'] = [
        '#title' => t('Attributes'),
        '#type' => 'textarea',
        '#description' => t('Set attributes for this wrapper. Enter one value per line, in the format attribute|value. The value is optional. Tokens are supported in attribute values.'),
        '#default_value' => $settings['field_wrapper']['html_element_attributes'],
        '#element_validate' => [ [self::class, 'validateHtmlAttributesList'] ],
        '#depended_field' => 'field_wrapper',
        '#states' => [
          'visible' => [
            ':input[name="fields[' . $field_name . '][settings_edit_form][third_party_settings][fdk][field_wrapper][html_element]"]' => ['!value' => '_default'],
          ],
        ],
      ];

      if (\Drupal::moduleHandler()->moduleExists('token')) {
        $elements['fdk']['field_wrapper']['html_element_attributes_token'] = [
          '#type' => 'item',
          '#theme' => 'token_tree_link',
          '#token_types' => $token_types,
          '#states' => [
            'visible' => [
              ':input[name="fields[' . $field_name . '][settings_edit_form][third_party_settings][fdk][field_wrapper][html_element]"]' => ['!value' => '_default'],
            ],
          ],
        ];
      }
      $elements['fdk']['field_wrapper']['force_multiple'] = [
        '#type' => 'checkbox',
        '#title' => t('Include field wrapper even if this field has only one value and label is hidden'),
        '#description' => t('By default field wrapper will not be present in output when field has only one value. Enable this checkbox to force inlcuding the field wrapper.'),
        '#default_value' => $settings['field_wrapper']['force_multiple'],
      ];

      $elements['fdk']['label'] = [
        '#type' => 'details',
        '#title' => t('Field label wrapper'),
        // Default to open if we have any values to show.
        '#open' => $settings['label']['html_element'] != '_default',
      ];

      // Layout Builder provides facility to override title.
      // So, not to show in the Layout Builder configuration.
      if (isset($form['#form_id']) && strpos($form['#form_id'], "layout_builder") !== 0) {
        $elements['fdk']['label']['value'] = [
          '#type' => 'textfield',
          '#title' => t('Override field title'),
          '#description' => t('Enter a custom label value to overwrite the default.'),
          '#default_value' => $settings['label']['value'],
        ];
      }

      $elements['fdk']['label']['html_element'] = [
        '#type' => 'select',
        '#title' => t('Wrapper element'),
        '#description' => t('Select a wrapper element to be used for field label.'),
        '#default_value' => $settings['label']['html_element'],
        '#options' => $wrapper_options,
      ];

      $elements['fdk']['label']['html_element_other'] = [
        '#type' => 'textfield',
        '#description' => t('Enter HTML tag name of the wrapper element.'),
        '#default_value' => $settings['label']['html_element_other'],
        '#element_validate' => [ [self::class, 'validateHtmlTagName'] ],
        '#states' => [
          'visible' => [
            ':input[name="fields[' . $field_name . '][settings_edit_form][third_party_settings][fdk][label][html_element]"]' => ['value' => '_other'],
          ],
        ],
        '#depended_field' => 'html_element',
      ];

      $elements['fdk']['label']['html_element_classes'] = [
        '#type' => 'textfield',
        '#title' => t('Classes'),
        '#description' => t('Enter one or more HTML class names separated by spaces. It can be used to style with CSS.'),
        '#default_value' => $settings['label']['html_element_classes'],
        '#states' => [
          'visible' => [
            ':input[name="fields[' . $field_name . '][settings_edit_form][third_party_settings][fdk][label][html_element]"]' => ['!value' => '_default'],
          ],
        ],
      ];

      $elements['fdk']['label']['html_element_attributes'] = [
        '#title' => t('Attributes'),
        '#type' => 'textarea',
        '#description' => t('Set attributes for this wrapper. Enter one value per line, in the format attribute|value. The value is optional. Tokens are supported in attribute values.'),
        '#default_value' => $settings['label']['html_element_attributes'],
        '#element_validate' => [ [self::class, 'validateHtmlAttributesList'] ],
        '#depended_field' => 'html_element',
        '#states' => [
          'visible' => [
            ':input[name="fields[' . $field_name . '][settings_edit_form][third_party_settings][fdk][label][html_element]"]' => ['!value' => '_default'],
          ],
        ],
      ];

      if (\Drupal::moduleHandler()->moduleExists('token')) {
        $elements['fdk']['label']['html_element_attributes_token'] = [
          '#type' => 'item',
          '#theme' => 'token_tree_link',
          '#token_types' => $token_types,
          '#states' => [
            'visible' => [
              ':input[name="fields[' . $field_name . '][settings_edit_form][third_party_settings][fdk][label][html_element]"]' => ['!value' => '_default'],
            ],
          ],
        ];
      }

      $elements['fdk']['field_item_wrapper'] = [
        '#type' => 'details',
        '#title' => t('Field value wrapper'),
        // Default to open if we have any values to show.
        '#open' => $settings['field_item_wrapper']['html_element'] != '_default',
      ];

      $item_wrapper_options = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'div', 'span', 'p', 'strong'];
      $item_wrapper_options = ['_default' => t('Default')] + ['a' => t('Link')] + array_combine($item_wrapper_options, $item_wrapper_options) + ['_other' => t('Other')];

      $elements['fdk']['field_item_wrapper']['html_element'] = [
        '#type' => 'select',
        '#title' => t('Wrapper element'),
        '#description' => t('Select a wrapper element to be used for each field item value output.'),
        '#default_value' => $settings['field_item_wrapper']['html_element'],
        '#options' => $item_wrapper_options,
      ];

      $elements['fdk']['field_item_wrapper']['html_element_other'] = [
        '#type' => 'textfield',
        // '#title' => t('Field wrapper'),
        '#description' => t('Enter HTML tag name of the wrapper element.'),
        '#default_value' => $settings['field_item_wrapper']['html_element_other'],
        '#element_validate' => [ [self::class, 'validateHtmlTagName'] ],
        '#states' => [
          'visible' => [
            ':input[name="fields[' . $field_name . '][settings_edit_form][third_party_settings][fdk][field_item_wrapper][html_element]"]' => ['value' => '_other'],
          ],
        ],
        '#depended_field' => 'html_element',
      ];

      $elements['fdk']['field_item_wrapper']['html_element_link_href'] = [
        '#type' => 'textfield',
        '#title' => t('Link destination'),
        '#description' => t('Enter destination for the link. Tokens are supported.'),
        '#default_value' => $settings['field_item_wrapper']['html_element_link_href'],
        '#element_validate' => [ [self::class, 'validateHref'] ],
        '#states' => [
          'visible' => [
            ':input[name="fields[' . $field_name . '][settings_edit_form][third_party_settings][fdk][field_item_wrapper][html_element]"]' => ['value' => 'a'],
          ],
        ],
        '#depended_field' => 'html_element',
      ];

      if (\Drupal::moduleHandler()->moduleExists('token')) {
        $elements['fdk']['field_item_wrapper']['html_element_link_href_token'] = [
          '#type' => 'item',
          '#theme' => 'token_tree_link',
          '#token_types' => $token_types,
          '#states' => [
            'visible' => [
              ':input[name="fields[' . $field_name . '][settings_edit_form][third_party_settings][fdk][field_item_wrapper][html_element]"]' => ['value' => 'a'],
            ],
          ],
        ];
      }

      $elements['fdk']['field_item_wrapper']['html_element_classes'] = [
        '#type' => 'textfield',
        '#title' => t('Classes'),
        '#description' => t('Enter one or more HTML class names separated by spaces. It can be used to style the field items with CSS.'),
        '#default_value' => $settings['field_item_wrapper']['html_element_classes'],
        '#states' => [
          'visible' => [
            ':input[name="fields[' . $field_name . '][settings_edit_form][third_party_settings][fdk][field_item_wrapper][html_element]"]' => ['!value' => '_default'],
          ],
        ],
      ];

      $elements['fdk']['field_item_wrapper']['html_element_attributes'] = [
        '#title' => t('Attributes'),
        '#type' => 'textarea',
        '#description' => t('Set attributes for each field item wrapper. Enter one value per line, in the format attribute|value. The value is optional. Tokens are supported in attribute values.'),
        '#default_value' => $settings['field_item_wrapper']['html_element_attributes'],
        '#element_validate' => [ [self::class, 'validateHtmlAttributesList'] ],
        '#depended_field' => 'field_item_wrapper',
        '#states' => [
          'visible' => [
            ':input[name="fields[' . $field_name . '][settings_edit_form][third_party_settings][fdk][field_item_wrapper][html_element]"]' => ['!value' => '_default'],
          ],
        ],
      ];
      if (\Drupal::moduleHandler()->moduleExists('token')) {
        $elements['fdk']['field_item_wrapper']['html_element_attributes_token'] = [
          '#type' => 'item',
          '#theme' => 'token_tree_link',
          '#token_types' => $token_types,
          '#states' => [
            'visible' => [
              ':input[name="fields[' . $field_name . '][settings_edit_form][third_party_settings][fdk][field_item_wrapper][html_element]"]' => ['!value' => '_default'],
            ],
          ],
        ];
      }

      $elements['fdk']['field_delimiter'] = [
        '#type' => 'details',
        '#title' => t('Field delimiter'),
        // Default to open if we have any values to show.
        '#open' => $settings['field_item_wrapper']['html_element'] != '_default',
      ];

      $elements['fdk']['field_delimiter']['enabled'] = [
        '#type' => 'checkbox',
        '#title' => t('Add comma between field items'),
        '#default_value' => $settings['field_delimiter']['enabled'],
      ];

      // $elements['fdk']['field_delimiter']['after'] = [
      //   '#type' => 'textfield',
      //   '#title' => t('After'),
      //   '#description' => t('Enter a string to be added after each of the field item value. You can enter comma here to construct a comma separated list.'),
      //   '#default_value' => $settings['field_delimiter']['after'],
      // ];

      $elements['fdk']['field_delimiter']['include_and'] = [
        '#type' => 'checkbox',
        '#title' => t('Include "and" before the last item'),
        '#description' => t('If enabled "and" will be added before the last item if there are more than one field values to display.'),
        '#default_value' => $settings['field_delimiter']['include_and'],
        '#states' => [
          'visible' => [
            ':input[name="fields[' . $field_name . '][settings_edit_form][third_party_settings][fdk][field_delimiter][enabled]"]' => ['checked' => TRUE],
          ],
        ],
      ];

    }

    return $elements['fdk'];
  }

  public static function validateHtmlTagName(&$element, FormStateInterface $form_state, &$complete_form) {
    $input_exists = FALSE;
    $input = NestedArray::getValue($form_state->getValues(), $element['#parents'], $input_exists);

    $parents = $element['#parents'];
    array_pop($parents);
    $parents[] = $element['#depended_field'];
    $wrapper = NestedArray::getValue($form_state->getValues(), $parents);

    if ($wrapper == '_other' && empty($input)) {
      $form_state->setError($element, t('Please enter a wrapper tag name.'));
    }
    else if (!empty($input) && !preg_match('/^[a-zA-Z]+\d?$/', $input)) {
      $form_state->setError($element, t('Enter a valid HTML tag name. %name is not a valid tag name.', ['%name' => $input]));
    }
  }

  public static function validateHtmlAttributesList(&$element, FormStateInterface $form_state, &$complete_form) {
    $input_exists = FALSE;
    $input = NestedArray::getValue($form_state->getValues(), $element['#parents'], $input_exists);

    $list = explode("\n", $input);
    $list = array_map('trim', $list);
    $list = array_filter($list, 'strlen');

    $generated_keys = $explicit_keys = FALSE;
    foreach ($list as $position => $text) {
      // Check for an explicit key.
      $matches = [];
      if (preg_match('/^([\w]+(\-[\w]+)*)\|(.*)$/', $text, $matches)) {
        // Trim key and value to avoid unwanted spaces issues.
        $key = trim($matches[1]);
        $value = trim($matches[3]);
      }
      else {
        $form_state->setError($element, t('Invalid attribute setting(s).'));
        break;
      }
    }
  }

  public static function validateHref(&$element, FormStateInterface $form_state, &$complete_form) {
    $input_exists = FALSE;
    $input = NestedArray::getValue($form_state->getValues(), $element['#parents'], $input_exists);

    $parents = $element['#parents'];
    array_pop($parents);
    $parents = array_merge($parents, [$element['#depended_field']]);
    $select_field_value = NestedArray::getValue($form_state->getValues(), $parents);

    if ($select_field_value == 'a' && empty($input)) {
      $form_state->setError($element, t('Please enter a destination for the link.'));
    }
  }

  public static function formatter_settings_summary_alter(array &$summary, array $context) {
    $formatter_plugin = $context['formatter'];
    $settings = self::prepareConfigurationSettings($formatter_plugin->getThirdPartySettings('fdk'));
    $summary[] = [
      '#theme' => 'fdk_settings_summary',
      '#settings' => $settings,
    ];
  }

  public static function getAttributesFromConfig($attributes_string, $token_data = NULL) {
    $attribute_list = explode("\n", $attributes_string);
    $attribute_list = array_map('trim', $attribute_list);
    $attribute_list = array_filter($attribute_list, 'strlen');

    $attributes = [];
    foreach ($attribute_list as $text) {
      // Check for an explicit key.
      $matches = [];
      if (preg_match('/^([\w]+(\-[\w]+)*)\|(.*)$/', $text, $matches)) {
        // Trim key and value to avoid unwanted spaces issues.
        $key = trim($matches[1]);
        $value = trim($matches[3]);
        if ($token_data) {
          $attributes[$key] = \Drupal::token()->replace($value, $token_data, ['clear' => TRUE]);
        }
        else {
          $attributes[$key] = $value;
        }
      }
    }
    return $attributes;
  }

  /**
   * The FDK module proivides its own version of field.html.twig templates.
   * All themes are supposed to override the FDK version of the template than Drupal core.
   * This function scans over all active themes and finds incompatible field templates.
   * @return array
   *  Array of file info keyed by theme names.
   */
  public static function getIncompatibleFieldTemplates() {
    $cache = \Drupal::cache();
    $cache_key = 'fdk_incompatible_template_files';

    if ($cached = $cache->get($cache_key)) {
      $files_info = $cached->data;
    }
    else {
      // Get all active themes.
      $active_themes = array_map(function($theme) {
        if ($theme->status) {
          return $theme;
        }
      }, \Drupal::service('theme_handler')->listInfo());

      $files_info = [];
      foreach ($active_themes as $theme_name => $theme) {
        $theme_dir = \Drupal::root() . '/' . $theme->getPath();
        $files = \Drupal::service('file_system')->scanDirectory($theme_dir . '/templates', '/^field(\-\-.*)?\.html\.twig$/', ['key' => 'filename']);
        if (!empty($files)) {
          $incompatible_files = [];
          foreach ($files as $file_info) {
            $file_content = file_get_contents($file_info->uri);
            // Check whether the template contains any of FDK specific variables.
            $field_wrapper_tag_exists = (bool) preg_match('/{{\s*field_wrapper_tag\s*}}/', $file_content);
            $label_tag_exists = (bool) preg_match('/{{\s*label_tag\s*}}/', $file_content);
            $field_item_wrapper_tag_exists = (bool) preg_match('/{{\s*field_item_wrapper_tag\s*}}/', $file_content);

            if (!($field_wrapper_tag_exists || $label_tag_exists || $field_item_wrapper_tag_exists)) {
              // No FDK specific variables found. Add to incompatible list.
              $incompatible_files[] = $file_info;
            }
          }
          if (!empty($incompatible_files)) {
            $files_info[$theme_name] = $incompatible_files;
          }
        }
      }
      $cache->set($cache_key, $files_info, CacheBackendInterface::CACHE_PERMANENT);
    }
    return $files_info;
  }
}

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

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