civicrm_entity-8.x-3.0-beta1/src/Entity/CivicrmEntity.php

src/Entity/CivicrmEntity.php
<?php

namespace Drupal\civicrm_entity\Entity;

use Drupal\civicrm_entity\Plugin\Field\ActivityEndDateFieldItemList;
use Drupal\civicrm_entity\Plugin\Field\BundleFieldItemList;
use Drupal\civicrm_entity\SupportedEntities;
use Drupal\Core\Entity\ContentEntityBase;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\TypedData\Plugin\DataType\DateTimeIso8601;
use Drupal\datetime\Plugin\Field\FieldType\DateTimeItem;
use Symfony\Component\Validator\ConstraintViolation;

/**
 * Entity class for CiviCRM entities.
 *
 * This entity class is not annotated. Plugin definitions are created during
 * the hook_entity_type_build() process. This allows for dynamic creation of
 * multiple entity types that use one single class, without creating redundant
 * class files and annotations.
 *
 * @see civicrm_entity_entity_type_build().
 */
class CivicrmEntity extends ContentEntityBase {

  /**
   * Flag to denote if the entity is currently going through Drupal CRUD hooks.
   *
   * We need to trigger the Drupal CRUD hooks when entities are edited in Civi,
   * but we need a way to ensure they aren't double triggered when already
   * going through the Drupal CRUD process.
   *
   * @var bool
   */
  // @codingStandardsIgnoreStart
  public $drupal_crud = FALSE;
  // @codingStandardsIgnoreEnd

  /**
   * {@inheritdoc}
   */
  public function save() {
    // Set ::drupal_crud to indicate save is coming from Drupal.
    try {
      $this->drupal_crud = TRUE;
      $result = parent::save();
    }
    finally {
      $this->drupal_crud = FALSE;
    }

    return $result;
  }

  /**
   * {@inheritdoc}
   */
  public function delete() {
    // Set ::drupal_crud to indicate delete is coming from Drupal.
    try {
      $this->drupal_crud = TRUE;
      parent::delete();
    }
    finally {
      $this->drupal_crud = FALSE;
    }
  }

  /**
   * {@inheritdoc}
   */
  public static function preCreate(EntityStorageInterface $storage, array &$values) {
    // If the `bundle` property is missing during the create operation, Drupal
    // will error – even if our bundle is computed on other required fields.
    // This ensures the values array has the bundle property set.
    $entity_type = $storage->getEntityType();
    if ($entity_type->hasKey('bundle')) {
      $bundle_property = $entity_type->get('civicrm_bundle_property');
      /** @var \Drupal\civicrm_entity\CiviCrmApiInterface $civicrm_api */
      $civicrm_api = \Drupal::service('civicrm_entity.api');
      $options = $civicrm_api->getOptions($entity_type->get('civicrm_entity'), $bundle_property);

      if (isset($values[$entity_type->getKey('bundle')]) && $values[$entity_type->getKey('bundle')] === $entity_type->id()) {
        $raw_bundle_value = key($options);
      }
      else {
        $raw_bundle_value = $values[$bundle_property];
      }

      $bundle_value = $options[$raw_bundle_value];
      $transliteration = \Drupal::transliteration();
      $machine_name = SupportedEntities::optionToMachineName($bundle_value, $transliteration);
      $values[$entity_type->getKey('bundle')] = $machine_name;
    }
  }

  /**
   * {@inheritdoc}
   */
  public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
    $fields = [];
    $civicrm_entity_info = SupportedEntities::getInfo()[$entity_type->id()];
    $civicrm_required_fields = !empty($civicrm_entity_info['required']) ? $civicrm_entity_info['required'] : [];
    $field_definition_provider = \Drupal::service('civicrm_entity.field_definition_provider');
    $civicrm_fields = \Drupal::service('civicrm_entity.api')->getFields($entity_type->get('civicrm_entity'), 'create');

    foreach ($civicrm_fields as $name => $civicrm_field) {
      // Apply any additional field data provided by the module.
      if (!empty($civicrm_entity_info['fields'][$name])) {
        $civicrm_field = $civicrm_entity_info['fields'][$name] + $civicrm_field;
      }

      $fields[$name] = $field_definition_provider->getBaseFieldDefinition($civicrm_field);
      $fields[$name]->setRequired(isset($civicrm_required_fields[$name]));

      if (str_starts_with($name, 'custom_') && $values = \Drupal::service('civicrm_entity.api')->getCustomFieldMetadata($name)) {
        $fields[$name]->setSetting('civicrm_entity_field_metadata', $values);
        $fields[$name]->setRequired((bool) $civicrm_field['is_required']);
      }
    }

    // Placing the bundle field here is a bit of a hack work around.
    // \Drupal\Core\Entity\ContentEntityStorageBase::initFieldValues will apply
    // default values to all empty fields. The computed bundle field will
    // provide a default value as well, for its related CiviCRM Entity field.
    // By placing this field last, we avoid conflict on setting of the default
    // value.
    if ($entity_type->hasKey('bundle')) {
      $fields[$entity_type->getKey('bundle')] = BaseFieldDefinition::create('string')
        ->setLabel($entity_type->getBundleLabel())
        ->setRequired(TRUE)
        ->setReadOnly(TRUE)
        ->setClass(BundleFieldItemList::class);
    }

    // Provide a computed base field that takes the activity start time and
    // appends the duration to calculated and end time.
    if ($entity_type->id() === 'civicrm_activity') {
      $fields['activity_end_datetime'] = BaseFieldDefinition::create('datetime')
        ->setLabel(t('Activity End Date'))
        ->setSetting('datetime_type', DateTimeItem::DATETIME_TYPE_DATETIME)
        ->setComputed(TRUE)
        ->setDisplayOptions('view', [
          'type' => 'datetime_default',
          'weight' => 0,
        ])
        ->setDisplayConfigurable('form', FALSE)
        ->setClass(ActivityEndDateFieldItemList::class);
    }
    $module_handler = \Drupal::getContainer()->get('module_handler');
    if ($module_handler->moduleExists('path')) {
      $config = \Drupal::config('civicrm_entity.settings');
      $enabled_entity_types = $config->get('enabled_entity_types') ?: [];
      if (in_array($entity_type->id(), $enabled_entity_types)) {
        $fields['path'] = BaseFieldDefinition::create('path')
          ->setLabel(t('URL alias'))
          ->setDisplayOptions('form', ['type' => 'path', 'weight' => 30])
          ->setDisplayConfigurable('form', TRUE)
          ->setComputed(TRUE);
      }
    }
    return $fields;
  }

  /**
   * {@inheritdoc}
   */
  public function validate() {
    $violations = parent::validate();

    $params = $this->civicrmApiNormalize();

    $civicrm_api = \Drupal::getContainer()->get('civicrm_entity.api');
    $civicrm_entity_type = $this->getEntityType()->get('civicrm_entity');
    $civicrm_violations = $civicrm_api->validate($civicrm_entity_type, $params);
    if (!empty($civicrm_violations)) {
      foreach (reset($civicrm_violations) as $civicrm_field => $civicrm_violation) {
        $definition = $this->getFieldDefinition($civicrm_field);
        // Use Drupal's translation system to safely format the message.
        $field_label = $definition->getLabel();
        $message = $civicrm_violation['message'] ?? '';
        // Create a TranslatableMarkup object to safely handle the replacement.
        $translated_message = new \Drupal\Core\StringTranslation\TranslatableMarkup($message, [':' . $civicrm_field => $field_label]);
        $violation = new ConstraintViolation(
          $translated_message,
          $translated_message,
          [],
          '',
          $civicrm_field,
          $params[$civicrm_field] ?? NULL
        );
        $violations->add($violation);
      }
    }

    return $violations;
  }

  /**
   * Normalize CiviCRM API data.
   */
  public function civicrmApiNormalize() {
    $params = [];
    /** @var \Drupal\Core\Field\FieldItemListInterface $items */
    foreach ($this->getFields() as $field_name => $items) {
      $items->filterEmptyItems();

      if ($field_name == 'path' && (!$this->hasLinkTemplate('canonical') || !$this->hasLinkTemplate('edit-form'))) {
        continue;
      }

      if ($items->isEmpty()) {
        continue;
      }

      $storage_definition = $items->getFieldDefinition()->getFieldStorageDefinition();

      if (!$storage_definition->isBaseField()) {
        // Do not try to pass any FieldConfig (or else) to CiviCRM API.
        continue;
      }

      if ($storage_definition->getType() == 'metatag_computed') {
        continue;
      }

      $main_property_name = $storage_definition->getMainPropertyName();
      $list = [];
      /** @var \Drupal\Core\Field\FieldItemInterface $item */
      foreach ($items as $delta => $item) {
        $main_property = $item->get($main_property_name);
        if ($main_property instanceof DateTimeIso8601 && !is_array($main_property->getValue())) {
          // CiviCRM wants the datetime in the timezone of the user, but Drupal
          // stores it in UTC.
          $value = (new \DateTime($main_property->getValue(), new \DateTimeZone('UTC')))->setTimezone(new \DateTimeZone(date_default_timezone_get()))->format('Y-m-d H:i:s');
        }
        else {
          $value = $main_property->getValue();
        }
        $list[$delta] = $value;
      }

      // Remove the wrapping array if the field is single-valued.
      if ($storage_definition->getCardinality() === 1) {
        $list = reset($list);
      }
      if (!empty($list)) {
        $params[$field_name] = $list;
      }
    }

    return $params;
  }

  /**
   * Get raw value.
   */
  public function getRawValue($field) {
    return $this->values[$field] ?? '';
  }

}

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

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