xero-8.x-2.x-dev/src/Plugin/Field/FieldWidget/XeroAutocompleteWidget.php
src/Plugin/Field/FieldWidget/XeroAutocompleteWidget.php
<?php
namespace Drupal\xero\Plugin\Field\FieldWidget;
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\Core\Field\Attribute\FieldWidget;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\Plugin\Field\FieldWidget\StringTextfieldWidget;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\TypedData\TypedDataTrait;
use Drupal\xero\Plugin\Field\FieldType\XeroReference;
/**
* Provides an autocomplete textfield to look up a record on Xero.
*
* @internal
*/
#[FieldWidget(
id: 'xero_autocomplete',
label: new TranslatableMarkup('Xero autocomplete'),
field_types: ['xero_reference'],
)]
class XeroAutocompleteWidget extends StringTextfieldWidget {
use TypedDataTrait;
/**
* {@inheritdoc}
*/
public static function defaultSettings() {
return [
'xero_type' => '',
'ignore_case' => FALSE,
];
}
/**
* Get the Xero data type definition.
*
* @param string $type
* The Xero type setting provided by this widget.
*
* @return \Drupal\Core\TypedData\DataDefinitionInterface|bool
* The Xero data type definition or FALSE.
*/
protected function getXeroDefinition(string $type) {
$types = XeroReference::getTypes();
if (!in_array($type, $types)) {
return FALSE;
}
try {
return $this->getTypedDataManager()->getDefinition($type);
}
catch (PluginNotFoundException $e) {
return FALSE;
}
}
/**
* {@inheritdoc}
*/
public function settingsSummary() {
$settings = [];
$label = $this->t('Not set');
$type_name = $this->getSetting('xero_type');
$definition = $this->getXeroDefinition($type_name);
if ($definition) {
$label = $definition['label'];
}
$settings[] = $this->t('Xero type: @name', ['@name' => $label]);
return $settings;
}
/**
* {@inheritdoc}
*/
public function settingsForm(array $form, FormStateInterface $form_state) {
$options = $this->getTypeOptions();
$form['xero_type'] = [
'#type' => 'select',
'#title' => $this->t('Xero Type'),
'#description' => $this->t('Select the Xero data type to use for this form.'),
'#options' => $options,
'#default_value' => $this->getSetting('xero_type'),
];
$form['ignore_case'] = [
'#type' => 'checkbox',
'#title' => $this->t('Ignore case sensitivity'),
'#description' => $this->t('If checked, the autocomplete will be ignore case sensitivity.'),
'#default_value' => $this->getSetting('ignore_case'),
];
return $form;
}
/**
* {@inheritdoc}
*/
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
$defaultValue = '';
$defaultGuid = $items[$delta]->guid ?? '';
if ($defaultGuid) {
$defaultLabel = $items[$delta]->label ?? '';
if ($defaultLabel) {
$defaultValue = $this->t('@guid (@label)', [
'@label' => $defaultLabel,
'@guid' => $defaultGuid,
]);
}
else {
$defaultValue = $this->t('@guid', ['@guid' => $defaultGuid]);
}
}
$element['value'] = $element + [
'#type' => 'textfield',
'#autocomplete_route_name' => 'xero.autocomplete',
'#autocomplete_route_parameters' => [
'type' => $this->getSetting('xero_type'),
],
'#default_value' => $defaultValue,
'#size' => 60,
];
if ($this->getSetting('ignore_case')) {
$element['value']['#autocomplete_query_parameters'] = ['ignore-case'];
}
return $element;
}
/**
* {@inheritdoc}
*/
public function massageFormValues(array $values, array $form, FormStateInterface $form_state) {
// The item values keyed by field name.
$return_values = [];
$xero_type = $this->getSetting('xero_type');
foreach ($values as $values_data) {
$item = [
'type' => $xero_type,
];
if (is_array($values_data)) {
$value = $values_data['value'];
}
else {
$value = $values_data;
}
preg_match('/([a-zA-Z0-9\-]+)(\s\((.+)\))?/', $value, $matches);
$item['guid'] = $matches[1] ?? '';
$item['label'] = isset($matches[3]) ? trim($matches[3]) : '';
$return_values[] = $item;
}
return $return_values;
}
/**
* Get the xero type options.
*
* @return array
* An array of options for a select list.
*/
protected function getTypeOptions() {
$options = [];
$types = XeroReference::getTypes();
foreach ($types as $type_name) {
$definition = $this->getXeroDefinition($type_name);
if ($definition) {
$options[$type_name] = $definition['label'];
}
}
return $options;
}
}
