eav_field-2.x-dev/src/Entity/EavAttribute.php
src/Entity/EavAttribute.php
<?php
namespace Drupal\eav_field\Entity;
use Drupal\Core\Annotation\Translation;
use Drupal\Core\Entity\Annotation\ContentEntityType;
use Drupal\Core\Entity\ContentEntityBase;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Field\FieldTypePluginManager;
use Drupal\Core\Field\FormatterPluginManager;
use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem;
use Drupal\Core\Field\WidgetPluginManager;
/**
* @ContentEntityType(
* id = "eav_attribute",
* label = @Translation("EAV attribute"),
* base_table = "eav_attribute",
* data_table = "eav_attribute_field_data",
* entity_keys = {
* "id" = "aid",
* "uuid" = "uuid",
* "label" = "label",
* "langcode" = "langcode",
* "weight" = "weight",
* "status" = "status",
* },
* translatable = TRUE,
* fieldable = TRUE,
* field_ui_base_route = "entity.eav_attribute.collection",
* handlers = {
* "storage" = "\Drupal\eav_field\EavAttributeStorage",
* "form" = {
* "add" = "\Drupal\eav_field\Form\EavAttributeForm",
* "edit" = "\Drupal\eav_field\Form\EavAttributeForm",
* "delete" = "\Drupal\Core\Entity\ContentEntityDeleteForm",
* },
* "list_builder" = "\Drupal\eav_field\EavAttributeListBuilder",
* },
* links = {
* "add-form" = "/admin/structure/eav/attributes/add",
* "edit-form" = "/admin/structure/eav/attributes/{eav_attribute}/edit",
* "delete-form" = "/admin/structure/eav/attributes/{eav_attribute}/delete",
* "collection" = "/admin/structure/eav/attributes",
* },
* admin_permission = "administer eav attributes",
* )
*/
class EavAttribute extends ContentEntityBase implements EavAttributeInterface {
/**
* {@inheritDoc}
*/
public static function baseFieldDefinitions(EntityTypeInterface $entity_type): array {
$fields = parent::baseFieldDefinitions($entity_type); /** @var BaseFieldDefinition[] $fields */
$i = 0;
$fields['aid']
->setLabel(t('EAV attribute ID'))
->setDescription(t('EAV attribute ID'));
$fields['label'] = BaseFieldDefinition::create('string')
->setLabel(t('Label'))
->setRequired(TRUE)
->setDisplayOptions('form', [
'type' => 'string_textfield',
'weight' => $i++,
])
->setDisplayConfigurable('form', TRUE);
$fields['admin_label'] = BaseFieldDefinition::create('string')
->setLabel(t('Administrative label'))
->setDisplayOptions('form', [
'type' => 'string_textfield',
'weight' => $i++,
])
->setDisplayConfigurable('form', TRUE);
$fields['machine_name'] = BaseFieldDefinition::create('string')
->setLabel(t('Machine name'))
->setRequired(TRUE)
->addConstraint('UniqueField')
->setDisplayOptions('form', [
'type' => 'string_textfield',
'weight' => $i++,
])
->setDisplayConfigurable('form', TRUE);
$allowed_field_types = array_keys(EavValue::getFieldTypes());
$fields['value_type'] = BaseFieldDefinition::create('list_string')
->setLabel(t('Value field type'))
->setRequired(TRUE)
->setDefaultValue('string')
->setSettings([
'allowed_values' => array_combine($allowed_field_types, $allowed_field_types),
])
->setDisplayOptions('form', [
'type' => 'options_select',
'weight' => $i++,
])
->setDisplayConfigurable('form', TRUE);
$fields['value_storage_config'] = BaseFieldDefinition::create('map')
->setLabel(t('Value storage config'));
$fields['value_config'] = BaseFieldDefinition::create('map')
->setLabel(t('Value field config'));
$fields['value_widget_type'] = BaseFieldDefinition::create('list_string')
->setLabel(t('Widget'))
->setRequired(TRUE)
->setDefaultValue('string_textfield')
->setSetting('allowed_values_function', [static::class, 'getValueWidgetTypeAllowedValues'])
->setDisplayOptions('form', [
'type' => 'options_select',
'weight' => $i++,
])
->setDisplayConfigurable('form', TRUE);
$fields['value_widget_settings'] = BaseFieldDefinition::create('map')
->setLabel(t('Widget settings'));
$fields['value_formatter_type'] = BaseFieldDefinition::create('list_string')
->setLabel(t('Formatter'))
->setSetting('allowed_values_function', [static::class, 'getValueFormatterTypeAllowedValues'])
->setDisplayOptions('form', [
'type' => 'options_select',
'weight' => $i++,
])
->setDisplayConfigurable('form', TRUE);
$fields['value_formatter_settings'] = BaseFieldDefinition::create('map')
->setLabel(t('Formatter settings'));
$fields['description'] = BaseFieldDefinition::create('text_long')
->setLabel(t('Description'))
->setDisplayOptions('form', [
'type' => 'text_textfield',
'weight' => $i++,
])
->setDisplayConfigurable('form', TRUE);
$fields['primary'] = BaseFieldDefinition::create('boolean')
->setLabel(t('Is primary attribute'))
->setDefaultValue(FALSE)
->setDisplayOptions('form', [
'type' => 'boolean_checkbox',
'weight' => $i++,
])
->setDisplayConfigurable('form', TRUE);
$fields['weight'] = BaseFieldDefinition::create('integer')
->setLabel(t('Weight'))
->setDisplayOptions('form', [
'type' => 'number',
'weight' => $i++,
])
->setDisplayConfigurable('form', TRUE);
$fields['status'] = BaseFieldDefinition::create('boolean')
->setLabel(t('Active'))
->setDefaultValue(TRUE)
->setDisplayOptions('form', [
'type' => 'boolean_checkbox',
'weight' => $i++,
])
->setDisplayConfigurable('form', TRUE);
$fields['created'] = BaseFieldDefinition::create('created')
->setLabel(t('Created'))
->setDescription(t('The time that the attribute was created.'))
->setDefaultValueCallback(static::class . '::getRequestTime');
return $fields;
}
/**
* {@inheritDoc}
*/
public function preSave(EntityStorageInterface $storage): void {
parent::preSave($storage);
// Generate machine name
$machine_name = $this->getMachineName();
if (!$machine_name) {
$machine_name = \Drupal::transliteration()->transliterate(mb_strtolower($this->label()));
}
// Clear machine name
$machine_name = str_replace(['-', ' ', '.'], '_', $machine_name);
$machine_name = preg_replace('/[^a-z0-9_]/', '', $machine_name);
// Set machine name
$this->setMachineName($machine_name);
// Calculate weight
if ($this->getWeight() === NULL) {
$this->set('weight', self::getMaxWeight() + 1);
}
}
/**
* {@inheritDoc}
*/
public static function create(array $values = []): EavAttributeInterface {
/** @noinspection All */
return parent::create($values);
}
/**
* {@inheritDoc}
*/
public static function load($id): ?EavAttributeInterface {
return parent::load($id);
}
/**
* {@inheritDoc}
*/
public static function loadByProperties(array $values): array {
return \Drupal::entityTypeManager()->getStorage('eav_attribute')->loadByProperties($values);
}
/**
* {@inheritDoc}
*/
public static function loadByMachineName(string $machine_name): ?EavAttributeInterface {
static $cache = [];
if (!isset($cache[$machine_name])) {
$attributes_ids = \Drupal::entityQuery('eav_attribute')
->condition('machine_name', $machine_name)
->accessCheck(FALSE)
->execute();
if ($attributes_ids) {
$cache[$machine_name] = current($attributes_ids);
}
}
return isset($cache[$machine_name]) ? self::load($cache[$machine_name]) : NULL;
}
/**
* {@inheritDoc}
*/
public static function loadByLabel(string $label): ?EavAttributeInterface {
static $cache = [];
if (!isset($cache[$label])) {
$attributes_ids = \Drupal::entityQuery('eav_attribute')
->condition('label', $label)
->accessCheck(FALSE)
->execute();
if ($attributes_ids) {
$cache[$label] = current($attributes_ids);
}
}
return isset($cache[$label]) ? self::load($cache[$label]) : NULL;
}
/**
* {@inheritDoc}
*/
public function loadUnchanged(): ?EavAttributeInterface {
return $this->entityTypeManager()->getStorage('eav_attribute')->loadUnchanged($this->id());
}
/**
* {@inheritDoc}
*
* @return EavAttributeInterface[]
*/
public static function loadMultiple(array $ids = NULL): array {
return parent::loadMultiple($ids);
}
/**
* {@inheritDoc}
*/
public function getAdministrativeLabel(): string {
return $this->get('admin_label')->value ?: $this->label();
}
/**
* {@inheritDoc}
*/
public function getMachineName(): ?string {
return $this->get('machine_name')->value;
}
/**
* {@inheritDoc}
*/
public function setMachineName(string $machine_name): self {
return $this->set('machine_name', $machine_name);
}
/**
* {@inheritDoc}
*/
public function getWeight(): ?int {
return $this->get('weight')->value;
}
/**
* {@inheritDoc}
*/
public function setWeight(int $weight): EavAttributeInterface {
return $this->set('weight', $weight);
}
/**
* {@inheritDoc}
*/
public function getValueType(): string {
return $this->get('value_type')->value;
}
/**
* {@inheritDoc}
*/
public function setValueType(string $value_type): EavAttributeInterface {
return $this->set('value_type', $value_type);
}
/**
* {@inheritDoc}
*/
public function getValueFieldName(): string {
return $this->getValueType() . '_value';
}
/**
* {@inheritDoc}
*/
public function getValueStorageConfigArray(bool $with_defaults = TRUE): array {
$value_storage_config_array = $this->get('value_storage_config')->getValue()[0] ?? [];
if ($with_defaults) {
$default_values = [
'field_name' => $this->getValueFieldName(),
'entity_type' => 'eav_value',
'type' => $this->getValueType(),
];
$field_type_manager = \Drupal::service('plugin.manager.field.field_type'); /** @var FieldTypePluginManager $field_type_manager */
$default_settings = $field_type_manager->getDefaultStorageSettings($this->getValueType());
$value_storage_config_array = $default_values + $value_storage_config_array + ['settings' => $default_settings];
}
return $value_storage_config_array;
}
/**
* {@inheritDoc}
*/
public function getValueCardinality(): int {
$value_storage_config_array = $this->getValueStorageConfigArray();
return $value_storage_config_array['cardinality'] ?? 1;
}
/**
* {@inheritDoc}
*/
public function valueIsMultiple(): bool {
$value_cardinality = $this->getValueCardinality();
return ($value_cardinality > 1 || $value_cardinality == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
}
/**
* {@inheritDoc}
*/
public function getValueConfigArray(bool $with_defaults = TRUE): array {
$value_config_array = $this->get('value_config')->getValue()[0] ?? [];
if ($with_defaults) {
$default_values = [
'field_name' => $this->getValueFieldName(),
'entity_type' => 'eav_value',
'bundle' => 'eav_value',
];
$field_type_manager = \Drupal::service('plugin.manager.field.field_type'); /** @var FieldTypePluginManager $field_type_manager */
$default_settings = $field_type_manager->getDefaultFieldSettings($this->getValueType());
$value_config_array = $default_values + $value_config_array + ['settings' => $default_settings];
}
return $value_config_array;
}
/**
* {@inheritDoc}
*/
public function getValueFieldDefaultValues(): ?array {
return $this->getValueConfigArray()['default_value'] ?? NULL;
}
/**
* {@inheritDoc}
*/
public function getValueWidgetType(): string {
return $this->get('value_widget_type')->value;
}
/**
* {@inheritDoc}
*/
public function getValueWidgetSettings(): array {
return $this->get('value_widget_settings')->getValue()[0] ?? [];
}
/**
* {@inheritDoc}
*/
public function getValueFormatterType(): ?string {
return $this->get('value_formatter_type')->value;
}
/**
* {@inheritDoc}
*/
public function getValueFormatterSettings(): array {
return $this->get('value_formatter_settings')->getValue()[0] ?? [];
}
/**
* {@inheritDoc}
*/
public function isActive(): bool {
return (bool)$this->get('status')->value;
}
/**
* {@inheritDoc}
*/
public function isPrimary(): bool {
return (bool)$this->get('primary')->value;
}
/**
* {@inheritDoc}
*/
public function getValueFieldDefinition(): BaseFieldDefinition {
$entity_field_manager = \Drupal::service('entity_field.manager'); /** @var EntityFieldManagerInterface $entity_field_manager */
/** @noinspection All */
return $entity_field_manager->getFieldDefinitions('eav_value', 'eav_value')[$this->getValueFieldName()];
}
/**
* {@inheritDoc}
*/
public function configureValueFieldDefinition(): BaseFieldDefinition {
$field_definition = $this->getValueFieldDefinition();
$field_storage_definition = $field_definition->getFieldStorageDefinition();
$field_config_array = $this->getValueConfigArray();
$field_storage_config_array = $this->getValueStorageConfigArray();
// Configure field storage
if (!empty($field_storage_config_array['settings'])) {
$field_storage_definition->setSettings($field_storage_config_array['settings']);
}
$field_storage_definition->setCardinality($field_storage_config_array['cardinality'] ?? 1);
$field_definition->setCardinality($field_storage_config_array['cardinality'] ?? 1);
// Configure field
$field_definition->setLabel($this->label());
if ($field_storage_definition->getCardinality() != 1) {
$field_definition->setLabel(t('Values'));
}
if (!empty($field_config_array['settings'])) {
$field_definition->setSettings($field_config_array['settings']);
}
if (isset($field_config_array['default_value'])) {
$field_definition->setDefaultValue($field_config_array['default_value']);
}
if (isset($field_config_array['description'])) {
$field_definition->setDescription($field_config_array['description']);
}
if (isset($field_config_array['required'])) {
$field_definition->setRequired($field_config_array['required']);
}
$options_allowed_values_static_cache = &drupal_static('options_allowed_values', []);
$valie_field_name = $this->getValueFieldName();
unset(
$options_allowed_values_static_cache['eav_value:' . $valie_field_name],
$options_allowed_values_static_cache['eav_value:' . $valie_field_name . ':entity']
);
return $field_definition;
}
/**
* {@inheritDoc}
*/
public function getCategoriesIds(): array {
return array_map(function (EntityReferenceItem $item) {
return (int)$item->target_id;
}, iterator_to_array($this->get('category')));
}
/**
* {@inheritDoc}
*/
public function setCategories(array $categories): EavAttributeInterface {
return $this->set('category', $categories);
}
/**
* {@inheritDoc}
*/
public function getDescription(): ?array {
if (!($description_items = $this->get('description'))->isEmpty()) {
return $description_items->first()->getValue();
}
return NULL;
}
/**
* {@inheritDoc}
*/
public static function getMaxWeight(): int {
$query = \Drupal::database()->select('eav_attribute_field_data', 'a');
$query->addExpression('MAX(a.weight)');
return (int)$query->execute()->fetchField();
}
/**
* {@inheritDoc}
*/
public static function getValueWidgetTypeAllowedValues(FieldStorageDefinitionInterface $field_storage_definition, EavAttributeInterface $attribute = NULL, bool &$cacheable = TRUE): array {
$cacheable = FALSE;
$widget_manager = \Drupal::service('plugin.manager.field.widget'); /** @var WidgetPluginManager $widget_manager */
$field_type = $attribute ? $attribute->getValueType() : NULL;
return $widget_manager->getOptions($field_type);
}
/**
* {@inheritDoc}
*/
public static function getValueFormatterTypeAllowedValues(FieldStorageDefinitionInterface $field_storage_definition, EavAttributeInterface $attribute = NULL, bool &$cacheable = TRUE): array {
$cacheable = FALSE;
$formatter_manager = \Drupal::service('plugin.manager.field.formatter'); /** @var FormatterPluginManager $formatter_manager */
$field_type = $attribute ? $attribute->getValueType() : NULL;
return $formatter_manager->getOptions($field_type);
}
/**
* {@inheritDoc}
*/
public static function sort(EavAttributeInterface $a, EavAttributeInterface $b): int {
return $a->getWeight() <=> $b->getWeight();
}
/**
* Return request timestamp.
*/
public static function getRequestTime(): int {
return \Drupal::time()->getRequestTime();
}
}
