You are here

function linked_field_field_formatter_third_party_settings_form in Linked Field 8

Implements hook_field_formatter_third_party_settings_form().

Parameters

\Drupal\Core\Field\FormatterInterface $plugin: The instantiated field formatter plugin.

\Drupal\Core\Field\FieldDefinitionInterface $field_definition: The field definition.

string $view_mode: The entity view mode.

array $form: The (entire) configuration form array.

\Drupal\Core\Form\FormStateInterface $form_state: The form state.

File

./linked_field.module, line 109
Main file of Linked Field module.

Code

function linked_field_field_formatter_third_party_settings_form(FormatterInterface $plugin, FieldDefinitionInterface $field_definition, $view_mode, array $form, FormStateInterface $form_state) {

  /** @var \Drupal\linked_field\LinkedFieldManager $manager */
  $manager = \Drupal::service('linked_field.manager');
  $available_attributes = $manager
    ->getAttributes();
  $settings = $plugin
    ->getThirdPartySettings('linked_field');
  if (in_array($field_definition
    ->getType(), $manager
    ->getFieldTypeBlacklist())) {
    return;
  }
  $settings = NestedArray::mergeDeep([
    'linked' => 0,
    'type' => 'field',
    'destination' => '',
    'advanced' => [
      'text' => '',
    ],
  ], $settings);
  if (!isset($settings['type'])) {
    $settings['type'] = 'custom';
  }
  $destination = [
    'field' => '',
    'custom' => '',
  ];
  $destination[$settings['type']] = $settings['destination'];
  $settings['destination'] = $destination;
  $element['linked'] = [
    '#type' => 'checkbox',
    '#title' => t('Link this field'),
    '#default_value' => $settings['linked'],
  ];

  // The target bundle is sometimes null so we grab it from form instead.
  $bundle = $field_definition
    ->getTargetBundle();
  if (!$bundle) {
    $bundle = isset($form['#bundle']) ? $form['#bundle'] : NULL;
  }
  $field_names = [];
  $fields_available = NULL;
  if ($bundle) {
    $field_names = $manager
      ->getDestinationFields($field_definition
      ->getTargetEntityTypeId(), $bundle);
    $fields_available = count($field_names);
  }

  // Switch to 'custom' mode if no fields are available.
  if (!$fields_available) {
    $settings['type'] = 'custom';
  }
  $element['type'] = [
    '#type' => 'radios',
    '#title' => t('Type'),
    '#options' => [
      'field' => t('Field'),
      'custom' => t('Custom'),
    ],
    // Use "custom" as default value to support updates from older versions.
    '#default_value' => !isset($settings['type']) ? 'custom' : $settings['type'],
    '#states' => [
      'visible' => [
        'input[name$="[third_party_settings][linked_field][linked]"]' => [
          'checked' => TRUE,
        ],
      ],
    ],
    '#attributes' => [
      'class' => [
        'container-inline',
      ],
    ],
  ];
  $element['destination'] = [
    '#type' => 'container',
    '#element_validate' => [
      'linked_field_element_validate_destination',
    ],
    '#states' => [
      'visible' => [
        'input[name$="[third_party_settings][linked_field][linked]"]' => [
          'checked' => TRUE,
        ],
      ],
    ],
  ];
  if (!$fields_available) {
    $element['destination']['field_message'] = [
      '#type' => 'container',
      '#states' => [
        'visible' => [
          'input[name$="[third_party_settings][linked_field][type]"]' => [
            'value' => 'field',
          ],
        ],
      ],
    ];
    $element['destination']['field_message']['message'] = [
      '#theme' => 'status_messages',
      '#message_list' => [
        'warning' => [
          t('No fields are available for linking, please choose the <em>custom</em> type.'),
        ],
      ],
    ];
  }
  $element['destination']['field'] = [
    '#type' => 'select',
    '#title' => t('Field'),
    '#options' => $field_names,
    '#disabled' => !$fields_available,
    '#empty_option' => t('- Select -'),
    '#default_value' => $settings['destination'],
    '#description' => t('The value of that field will be used as link destination.'),
    '#states' => [
      'visible' => [
        'input[name$="[third_party_settings][linked_field][type]"]' => [
          'value' => 'field',
        ],
      ],
      'required' => [
        'input[name$="[third_party_settings][linked_field][linked]"]' => [
          'checked' => TRUE,
        ],
        'input[name$="[third_party_settings][linked_field][type]"]' => [
          'value' => 'field',
        ],
      ],
    ],
  ];
  $element['destination']['custom'] = [
    '#type' => 'textfield',
    '#title' => t('Destination'),
    '#default_value' => $settings['destination']['custom'],
    '#description' => t('Tokens are supported. Internal path must be prefixed with a <code>internal:/</code>.'),
    '#states' => [
      'visible' => [
        'input[name$="[third_party_settings][linked_field][type]"]' => [
          'value' => 'custom',
        ],
      ],
      'required' => [
        'input[name$="[third_party_settings][linked_field][linked]"]' => [
          'checked' => TRUE,
        ],
        'input[name$="[third_party_settings][linked_field][type]"]' => [
          'value' => 'custom',
        ],
      ],
    ],
  ];
  $destination = \Drupal::destination()
    ->getAsArray();
  $config_path = Url::fromRoute('linked_field.config', [], [
    'query' => $destination,
  ])
    ->toString();
  $element['advanced'] = [
    '#type' => 'details',
    '#title' => t('Advanced'),
    '#description' => t('Manage available attributes <a href="@config">here</a>.', [
      '@config' => $config_path,
    ]),
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
    '#states' => [
      'visible' => [
        'input[name$="[third_party_settings][linked_field][linked]"]' => [
          'checked' => TRUE,
        ],
      ],
    ],
  ];
  foreach ($available_attributes as $attribute => $info) {

    // Provide default label / description for attributes.
    if (!$info['label']) {
      $info['label'] = str_replace('-', ' ', Unicode::ucfirst($attribute));
    }
    if (!$info['description']) {
      $info['description'] = t('Enter value for <code>@attribute</code> attribute.', [
        '@attribute' => $attribute,
      ]);
    }
    $element['advanced'][$attribute] = [
      '#type' => 'textfield',
      '#title' => $info['label'],
      '#description' => $info['description'],
      '#default_value' => isset($settings['advanced'][$attribute]) ? $settings['advanced'][$attribute] : '',
    ];
  }
  $element['advanced']['text'] = [
    '#type' => 'textfield',
    '#title' => t('Text'),
    '#default_value' => isset($settings['advanced']['text']) ? $settings['advanced']['text'] : '',
    '#description' => t('Here you can enter a token which will be used as link text. Note that the actual field output will be overridden.'),
  ];
  if (\Drupal::moduleHandler()
    ->moduleExists('token')) {
    $element['token'] = [
      '#type' => 'item',
      '#theme' => 'token_tree_link',
      '#token_types' => 'all',
      '#states' => [
        'visible' => [
          'input[name$="[third_party_settings][linked_field][linked]"]' => [
            'checked' => TRUE,
          ],
        ],
      ],
    ];
  }

  // Make sure empty Linked Field configuration is not stored.
  $element['#element_validate'][] = 'linked_field_element_validate';
  return $element;
}