Created on 11 January 2025, 4 months ago

Problem/Motivation

I want to relate the created webform submission and the created order in views.

Steps to reproduce

Make a views with webform submissions and try to relate the created order by webform product module.
You do not found it in relations.

Proposed resolution

Maybe we need to save the order_id in the webform_submission table into the entity_id_commerce_order field and make a hook_views_data to make a relation between webform_submission.entity_id_commerce_order and commerce_order.order_id .

If this is a good solution i can make a MR to this.

Regards,
Ibis

✨ Feature request
Status

Active

Version

3.1

Component

Code

Created by

πŸ‡­πŸ‡ΊHungary ibis

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

Comments & Activities

  • Issue created by @ibis
  • πŸ‡­πŸ‡ΊHungary ibis

    There are a patch for this function, using hook_views_data_alter.

  • πŸ‡­πŸ‡ΊHungary nagy.balint

    Hi!

    I did not test it yet, but if it works, then it is a good approach.

    We just need to move ->set('entity_id_commerce_order', $order->id());
    out of
    if ($this->configuration[self::ORDER_ID]) {

    and the 'entity_id_commerce_order' could be in self::, for example
    const ENTITY_ID_COMMERCE_ORDER = 'entity_id_commerce_order';
    just to follow the existing practice.

    so this value would always save, and then this further simplifies the set up process, as we would not need to even set up the Order ID and Order URL components.

  • πŸ‡­πŸ‡ΊHungary ibis

    Hi Balint,

    Thank you for your answer!
    Yes, of course. I also wondered why this data is needed in the webform_submission_data table, since the order id has a place in the webform_submission table and the order URL can be retrieved from the resulting order.
    But the ->set('entity_id_commerce_order', $order->id()) is essential row in this use case, because if you store this only in config, then u cannot make the relation between webform_submission.entity_id_commerce_order and commerce_order.order_id with the hook_views_data_alter function.

    Regards,
    IstvΓ‘n

  • πŸ‡­πŸ‡ΊHungary nagy.balint

    So after some more research, I concluded that this approach will unfortunately not work.

    $webform_submission
          ->set('entity_id_commerce_order', $order->id());

    Cannot work because entity_id_commerce_order is not a base field on the webform_submission entity. And altering the base field info is not recommended.
    Maybe it works temporarily but it is definitely not reliable. In fact the tests fail with this change.

    Also we cannot simply add it in the Data array where the submitted values live, cause that would also be unreliable, maybe it would get lost on a resave of the submission data. Also the data is a serialized column and would not be able to use join on in the webform_product_views_data_alter

    Of course since Order has the submission reference, it might be possible to construct the views using the order and then relate that to the relationship, but not sure that we can store order in the submission as submission has no extra metadata storage.

    I am setting this back to Active in case further ideas come up.

  • πŸ‡­πŸ‡ΊHungary ibis

    Ok, then we need our own field in webform_submission entity, right?
    Something this would be good?

    // in file webform_product.module
    
    use Drupal\Core\Field\BaseFieldDefinition;
    
    /**
     * Implements hook_entity_base_field_info().
     */
    function webform_product_entity_base_field_info(\Drupal\Core\Entity\EntityTypeInterface $entity_type) {
      $fields = [];
      if ($entity_type->id() === 'webform_submission') {
        $fields['commerce_order'] = BaseFieldDefinition::create('entity_reference')
          ->setLabel(t('Commerce Order'))
          ->setDescription(t('The commerce order associated with this webform submission.'))
          ->setSetting('target_type', 'commerce_order')
          ->setDisplayConfigurable('form', TRUE)
          ->setDisplayConfigurable('view', TRUE);
      }
      return $fields;
    }
    

    An then in the handler:

    $webform_submission->set('commerce_order', $order->id());
    $webform_submission->save();
    

    What do you think?

  • πŸ‡­πŸ‡ΊHungary nagy.balint

    So far based on my research, it seems there is no other option.

    And we would need an uninstall hook similar to

    function webform_product_uninstall() {
      $schema = \Drupal::database()->schema();
      $table_name = 'webform_submission';
      $field_name = 'commerce_order';
    
      // Check if the field exists before attempting to drop it.
      if ($schema->fieldExists($table_name, $field_name)) {
        $schema->dropField($table_name, $field_name);
      }
    }

    It is generally not recommended though, so I am currently undecided how to proceed.

  • πŸ‡­πŸ‡ΊHungary nagy.balint

    I was also looking at something like

    $webform_submission->set('entity_type', $this->cart->getEntityTypeId());
            $webform_submission->set('entity_id', $this->cart->id());
    
    

    But storing the order id there. But it seemed weird since that is used to store which entity embeds the webform originally.

  • πŸ‡­πŸ‡ΊHungary nagy.balint

    That being said,

    I don't see a lot of possible side effects from the base field info alter, since the webform submission entity does not go anywhere and they will also never add a column called "order_id" so this could be a safe way to go.

  • πŸ‡­πŸ‡ΊHungary ibis

    Yes, i think so also: safer way to alter the base field info, than set the entity_id, because the entity_id is used by webform module to store the entity reference if you add a webform to an entity.
    But, if you do not want to alter the base field info then the another option is to create a helper table with submission_id and order_id fields and use it in hook_views_data. But these option is much more complicated than base field info altering.

  • πŸ‡­πŸ‡ΊHungary nagy.balint

    @ibis:

    I have not checked it yet, but if the order id remains as a component, then could it be used with https://www.drupal.org/project/webform_views β†’ to create the relation?

    Maybe it is not enough, but worth a check.

  • πŸ‡­πŸ‡ΊHungary ibis

    I tested it and out of the box not working. Together with views_field_view it's working, but if you want all data (submission + order) in one row, then you need an another approach.

  • πŸ‡­πŸ‡ΊHungary nagy.balint

    So If I understand correctly, we have two main ways:

    a) If the user adds this extra component and sets it up so the module stores the order id in there, then we can create a views handler similarly to how the webform_views module does it, to be able to show the order in the same row.

    This could work without modifying the webform submission base field info.

    b) We can implement a new submodule, webform_product_views, and implement this base field alter to add the extra field to the submission, in which case it is easier to implement the views relationship, and it does not require the user to add this extra component to the webform.
    The submodule in this case would be to limit the risk in case some installations don't require a views like that, and we would need to document it.

  • πŸ‡­πŸ‡ΊHungary ibis

    Yes, i think it so to. In my opinion the submodule way is better.

Production build 0.71.5 2024