Website URL not exposed

Created on 21 August 2023, 10 months ago
Updated 25 April 2024, about 2 months ago

Problem/Motivation

I'm checking fields at /admin/structure/civicrm-entity/contact/display, but Website URL and other Contact Details fields aren't available for the Display.

I'd like to have these fields to access them from civicrm-entity--civicrm-contact.html.twig template file.

Steps to reproduce

{{ devel_dump(content) }}

Proposed resolution

For the workaround for theming, new class had to be created extending AbstractExtension with the following function called from Twig template:

    public function getContact($id) {
        \Drupal::service('civicrm')->initialize();
        try {
            $result = civicrm_api3('contact', 'get', [
                'id' => (int)$id,
                'api.website.get' => [],
                'api.Contribution.get' => [],
                'api.Relationship.get' => [],
                'api.CustomValue.get' => [],
                'api.Note.get' => [],
            ]);
        }
        catch (CiviCRM_API3_Exception $e) {
            throw $e;
        }

        $result = $result['values'] ? reset($result['values']) : [];
        ksort($result);
        return $result;
    }
✨ Feature request
Status

Closed: works as designed

Version

3.5

Component

Code

Created by

πŸ‡¬πŸ‡§United Kingdom kenorb

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @kenorb
  • πŸ‡ΊπŸ‡ΈUnited States markusa

    Website is a separate CiviCRM Entity. There is no url provided by the API, so we don't have a property. All the fields returned by an entity type's 'getfields' call (action create), have Drupal base field definitions automatically generated.

    A contact can have multiple Websites as well.

    In Drupal 7, I had a field type, "CiviCRM Entity Reference FIeld" .. which acted as a "remote reference field" or a "reverse reference field" .. The Inline Entity Form widget could be used as the field widget. Basically a standard entity reference field, but draws its values not from a Drupal field table, but from the CiviCRM database via API. We've explored porting this, but work remains in an early stage. Funding welcome :)

    A bespoke programmatic computed field would be another way to do this, in a small custom module.

  • πŸ‡¬πŸ‡§United Kingdom kenorb

    Ok, did it in custom module by extending the existing classes (relevant parts below):

    namespace Drupal\custom_civicrm;
    class CustomCiviEntityStorage extends \Drupal\civicrm_entity\CiviEntityStorage {
    
      private function getCiviCrmApi() {
        if (!$this->civicrmApi) {
          $this->civicrmApi = \Drupal::service('civicrm_entity.api');
        }
        return $this->civicrmApi;
      }
    
      // Copied from CiviEntityStorage.
      function doLoadMultiple(array $ids = NULL) {
    ...
        if (!empty($ids)) {
          $options = [
            'api.CustomValue.get' => [],
            'api.Relationship.get' => [],
            'api.website.get' => [],
            'id' => ['IN' => $ids],
            'options' => ['limit' => 0],
            'return' => $field_names,
            //'api.Contribution.get' => [],
            //'api.GroupContact.get' => [],
            //'api.Note.get' => [],
          ];
    ...
    

    Then extended CivicrmEntity to support these custom fields on load:

    namespace Drupal\custom_civicrm\Entity;
    
    class CustomCivicrmEntity extends \Drupal\civicrm_entity\Entity\CivicrmEntity {
    
      /**
       * {@inheritdoc}
       */
      function get($field_name) {
        switch ($field_name) {
          case 'api.CustomValue.get':
          case 'api.Relationship.get':
          case 'api.website.get':
            return $this->values[$field_name];
          default:
            return parent::get($field_name);
        }
      }
    
    }
    

    Then registered these classes in hook_entity_type_alter:

    function custom_civicrm_entity_type_alter(array &$entity_types) {
      if (isset($entity_types['civicrm_contact'])) {
        $entity_type_id = 'civicrm_contact';
        $civicrm_entity_info = \Drupal\civicrm_entity\SupportedEntities::getInfo()[$entity_type_id];
        $entity_types[$entity_type_id]->set('class', \Drupal\custom_civicrm\Entity\CustomCivicrmEntity::class);
        $entity_types[$entity_type_id]->set('handlers', [
          // ... here - same as original, exempt this one:
          'storage' => \Drupal\custom_civicrm\CustomCiviEntityStorage::class,
    // ...
      if (isset($entity_types['civicrm_event'])) {
        // Same can be used for civicrm_event.
      }
    }
    

    Then in Twig template I could use:


    {% set civicrm_entity = content.contact_type['#object'] %}
    {% set website_url = civicrm_entity.get('api.website.get').values[0].url %}
    {% set custom_value civicrm_entity.get('api.CustomValue.get').values %}
    {% set relations = civicrm_entity.get('api.Relationship.get').values %}

  • Status changed to Closed: works as designed about 2 months ago
  • πŸ‡ΊπŸ‡ΈUnited States markusa
Production build 0.69.0 2024