cbr-1.0.0/src/Plugin/Field/FieldType/CBRNodeReferenceField.php

src/Plugin/Field/FieldType/CBRNodeReferenceField.php
<?php

namespace Drupal\cbr\Plugin\Field\FieldType;

use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\TypedData\ComplexDataDefinitionInterface;
use Drupal\Core\TypedData\TypedDataInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\node\Entity\Node;

/**
 * Defines the 'cbr_node_reference' entity field type.
 *
 * @FieldType(
 *   id = "cbr_node_reference",
 *   label = @Translation("CBR Node reference"),
 *   description = @Translation("An entity field containing an entity reference."),
 *   category = @Translation("Case-based Reasoning"),
 *   default_widget = "cbr_entity_reference_autocomplete",
 *   default_formatter = "cbr_entity_reference_label",
 *   list_class = "\Drupal\Core\Field\EntityReferenceFieldItemList",
 * )
 */
class CBRNodeReferenceField extends EntityReferenceItem implements CBRFieldInterface
{
    protected MessengerInterface $messenger;
    protected CacheBackendInterface $cache;

    /**
     * {@inheritdoc}
     */
    public function __construct(ComplexDataDefinitionInterface $definition, $name, TypedDataInterface $parent)
    {
        parent::__construct($definition, $name, $parent);
        $this->messenger = \Drupal::messenger();
        $this->cache = \Drupal::cache();
    }

    /**
     * {@inheritdoc}
     */
    public function fieldSettingsForm(array $form, FormStateInterface $form_state): array
    {
        return parent::fieldSettingsForm($form, $form_state) + CBRFieldHelper::cbrFieldSettingsForm($form, $form_state);
    }

    /**
     * {@inheritdoc}
     */
    public function storageSettingsForm(array &$form, FormStateInterface $form_state, $has_data)
    {
        $element['target_type'] = [
            '#type' => 'select',
            '#title' => t('Type of item to reference'),
            '#default_value' => 'node',
            '#options' => [
                'node' => t('Node'),
            ],
            '#required' => TRUE,
            '#disabled' => TRUE,
            '#size' => 1,
        ];
        return $element;
    }


    /**
     * {@inheritdoc}
     */
    public static function getPreconfiguredOptions()
    {
        $options = [];
        return $options;
    }

    /**
     * {@inheritdoc}
     */
    public function calculateSimilarity($nids1, $nids2, FieldConfig $field_config): float
    {
        if ($this->getFieldDefinition()->getTargetEntityTypeId() != 'node')
            return 0;

        //return 0, if no referenced entities
        if (empty($nids1)) {
            return 0;
        }

        //return 0, if no referenced entities
        if (empty($nids2)) {
            return 0;
        }

        $entity = Node::load($nids1[0]);
        $summerized_field_values = $this->loadSummarizedFieldValues($nids1, $field_config, $entity->bundle());
        $summerizied_field_values2 = $this->loadSummarizedFieldValues($nids2, $field_config, $entity->bundle());

        //loop all fields 
        $similarity = 0;
        $sum_weight = 0;
        foreach ($entity->getFields() as $field_item) {
            if ($field_item->first() !== null && $field_item->first() instanceof CBRFieldInterface) {
                $field_config = $field_item->getFieldDefinition()->getConfig($entity->bundle());
                $weight = $field_config->getConfig($entity->bundle())->getThirdPartySetting('cbr', 'weight', 1);

                if (isset($summerized_field_values[$field_item->getName()]) && isset($summerizied_field_values2[$field_item->getName()])) {
                    $value1 = $summerized_field_values[$field_item->getName()];
                    $value2 = $summerizied_field_values2[$field_item->getName()];
                    $similarity += $field_item->first()->calculateSimilarity($value1, $value2, $field_config) * $weight;
                    $sum_weight += $weight;
                }
            }
        }

        if ($sum_weight > 0) {
            $similarity = $similarity / $sum_weight;
        } else {
            $similarity = 0;
        }
        return $similarity;
    }

    //Get all field values for all referenced nodes and summarize them
    private function loadSummarizedFieldValues(array $nids, FieldConfig $field_config, string $bundle): array
    {
        $summerized_field_values = [];
        sort($nids);
        //check if already in cache
        $cache_key = 'cbr_node_reference_summerizied_field_values_' . implode('_', $nids);
        if ($cached_item = $this->cache->get($cache_key)) {
            $summerized_field_values = $cached_item->data;
        } else {
            $referenced_entities = Node::loadMultiple($nids);
            foreach ($referenced_entities as $entity) {
                foreach ($entity->getFields(false) as $field_item) {
                    //skip entitys which are not the same type
                    if ($bundle != $entity->bundle()) {
                        //show message
                        $this->messenger->addMessage($this->t('Skipping entity @entity_type @entity_id, because it is not of the same type as the first entity.', [
                            '@entity_type' => $entity->bundle(),
                            '@entity_id' => $entity->id(),
                        ]), MessengerInterface::TYPE_WARNING);
                        continue;
                    }
                    /* @var FieldConfig $field_config */
                    $field_config = $field_item->getFieldDefinition()->getConfig($entity->bundle());
                    if ($field_item->first() !== null && $field_item->first() instanceof CBRFieldInterface) {
                        $summerized_field_values[$field_item->getName()][] = $field_item->first()->getValueForSimilarityCalculation($field_config);
                    }
                }
            }

            //Summerize with the method implemented in the field type
            foreach ($summerized_field_values as $field_name => $field_values) {
                foreach ($referenced_entities as $nid => $entity) {
                    if ($referenced_entities[$nid]->get($field_name)->first() !== null && is_array($summerized_field_values[$field_name])) {
                        $summerized_field_values[$field_name] = $referenced_entities[$nid]->get($field_name)->first()->summerize($field_values);
                    }
                }
            }

            //generate cachetags - these tags are automatically invalidated when the referenced entity is changed
            $tags = array_map(function ($nid) {
                return 'node:' . $nid;
            }, $nids);

            //Save in cache
            $this->cache->set($cache_key, $summerized_field_values, CacheBackendInterface::CACHE_PERMANENT, $tags);
        }
        return $summerized_field_values;
    }

    /**
     * {@inheritdoc}
     */
    public function getValueForSimilarityCalculation(FieldConfig $field_config): array
    {
        $nids =  [];
        foreach ($this->parent as $field) {
            $nids[] = $field->getValue()['target_id'];
        }
        return $nids;
    }

    //Will never be used
    public function summerize(array $fields): mixed
    {
        return 0;
    }
}

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

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