archivesspace-8.x-1.x-dev/src/Plugin/Field/FieldType/ASExtent.php
src/Plugin/Field/FieldType/ASExtent.php
<?php
namespace Drupal\archivesspace\Plugin\Field\FieldType;
use Drupal\Core\Field\FieldItemBase;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\TypedData\DataDefinition;
/**
* Provides a ArchivesSpace-based Extent field.
*
* @FieldType(
* id = "as_extent",
* label = @Translation("ArchivesSpace Extent"),
* module = "archivesspace",
* category = @Translation("ArchivesSpace"),
* description = @Translation("Implements an ArchivesSpace-based extent field"),
* default_formatter = "as_extent_default",
* default_widget = "as_extent_default",
* )
*/
class ASExtent extends FieldItemBase {
/**
* {@inheritdoc}
*/
public static function schema(FieldStorageDefinitionInterface $field_definition) {
return [
// Columns contains the values that the field will store.
'columns' => [
'portion' => [
'type' => 'text',
'size' => 'tiny',
'not null' => TRUE,
],
'number' => [
'type' => 'text',
'size' => 'tiny',
'not null' => TRUE,
],
'extent_type' => [
'type' => 'text',
'size' => 'tiny',
'not null' => TRUE,
],
'container_summary' => [
'type' => 'text',
'size' => 'medium',
],
'physical_details' => [
'type' => 'text',
'size' => 'medium',
],
'dimensions' => [
'type' => 'text',
'size' => 'tiny',
],
],
];
}
/**
* {@inheritdoc}
*/
public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
$properties = [];
$properties['portion'] = DataDefinition::create('string')
->setLabel(t('Portion'))
->setRequired(TRUE);
$properties['number'] = DataDefinition::create('string')
->setLabel(t('Number'))
->setRequired(TRUE);
$properties['extent_type'] = DataDefinition::create('string')
->setLabel(t('Type'))
->setRequired(TRUE);
$properties['container_summary'] = DataDefinition::create('string')
->setLabel(t('Container Summary'));
$properties['physical_details'] = DataDefinition::create('string')
->setLabel(t('Physical Details'));
$properties['dimensions'] = DataDefinition::create('string')
->setLabel(t('Dimensions'));
return $properties;
}
/**
* {@inheritdoc}
*/
public function isEmpty() {
$item = $this->getValue();
// All must have a value.
if (
isset($item['portion']) && !empty($item['portion']) &&
isset($item['number']) && !empty($item['number']) &&
isset($item['extent_type']) && !empty($item['extent_type'])
) {
return FALSE;
}
return TRUE;
}
/**
* {@inheritdoc}
*/
public static function defaultFieldSettings() {
return [
'extent_types' => [
'linear_feet' => 'Linear Feet',
'cubic_feet' => 'Cubic Feet',
'cassettes' => 'Cassettes',
'cubic_feet' => 'Cubic Feet',
'files' => 'Files',
'gigabytes' => 'Gigabytes',
'leaves' => 'Leaves',
'linear_feet' => 'Linear Feet',
'megabytes' => 'Megabytes',
'photographic_prints' => 'Photographic Prints',
'photographic_slides' => 'Photographic Slides',
'reels' => 'Reels',
'sheets' => 'Sheets',
'terabytes' => 'Terabytes',
'volumes' => 'Volumes',
],
'portion_values' => [
'whole' => 'Whole',
'part' => 'Part',
],
] + parent::defaultFieldSettings();
}
/**
* {@inheritdoc}
*/
public function fieldSettingsForm(array $form, FormStateInterface $form_state) {
$element = [];
$element['extent_types'] = [
'#type' => 'textarea',
'#title' => $this->t('Extent Types'),
'#default_value' => $this->encodeTextSettingsField($this->getSetting('extent_types')),
'#element_validate' => [[get_class($this), 'validateValues']],
'#required' => TRUE,
'#min' => 1,
'#description' => '<p>' . $this->t('Enter one value per line, in the format key|label.') .
'<br/>' . $this->t('The key is the stored value. The label will be used in displayed values and edit forms.') .
'<br/>' . $this->t('The label is optional: if a line contains a single string, it will be used as key and label.') .
'</p>',
];
return $element;
}
/**
* Retrieves extent types settings for formatters to use.
*
* @return array
* Available extent_types key/value pairs
*/
public function getExtentTypes() {
return $this->getSetting('extent_types');
}
/**
* Encodes key/value pairs into pipe-delimited text.
*
* @param array $settings
* Key/value pairs.
*
* @return string
* Pipe-delimited key/value pairs
*/
protected function encodeTextSettingsField(array $settings) {
$output = '';
foreach ($settings as $key => $value) {
$output .= "$key|$value\n";
}
return $output;
}
/**
* Extracts pipe-delimited key/value pairs.
*
* @param string $string
* The raw string to extract values from.
*
* @return array|null
* The array of extracted key/value pairs, or NULL if the string is invalid.
*
* @see \Drupal\options\Plugin\Field\FieldType\ListItemBase::extractAllowedValues()
*/
protected static function extractPipedValues($string) {
$values = [];
$list = explode("\n", $string);
$list = array_map('trim', $list);
$list = array_filter($list, 'strlen');
foreach ($list as $text) {
// Check for an explicit key.
$matches = [];
if (preg_match('/(.*)\|(.*)/', $text, $matches)) {
// Trim key and value to avoid unwanted spaces issues.
$key = trim($matches[1]);
$value = trim($matches[2]);
}
// Otherwise use the value as key and value.
else {
$key = $value = $text;
}
$values[$key] = $value;
}
return $values;
}
/**
* Callback for #element_validate.
*
* @param array $element
* An associative array containing the properties and children of the
* generic form element.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form for the form this element belongs to.
*
* @see \Drupal\Core\Render\Element\FormElement::processPattern()
*/
public static function validateValues(array $element, FormStateInterface $form_state) {
$values = static::extractPipedValues($element['#value']);
if (!is_array($values)) {
$form_state->setError($element, $this->t('Allowed values list: invalid input.'));
}
else {
// We may want to validate key values and notify in the future
// $form_state->setError($element, $error);.
$form_state->setValueForElement($element, $values);
}
}
}
