Salesforce Mapped Objects local task not appearing on Webform Submission pages

Created on 15 March 2022, about 3 years ago
Updated 2 April 2024, about 1 year ago

Problem/Motivation

When viewing any submission view (/admin/structure/webform/manage/{webform}/submission/{webform_submission}/...) the Salesforce Local Task tab should appear for a Webform that is having it's submissions mapped to a Salesforce Object.

A previous issue fixed an error caused by the code - https://www.drupal.org/project/salesforce/issues/2960813 β†’

I'm not sure if something has changed in the latest version of Webforms that is now breaking the code in the Salesforce Mapping UI module or whether it has always been like this?

The problem is because when the parameters are retrieved for the Webform Submission route current() is called and only one of them is returned:

    // There must be a better way to get the entity from a route match.
    $param = current(\Drupal::routeMatch()->getParameters()->all());

In the case of the Webform Submission View route this returns the view mode string 'html', 'table' etc, or the webform id for the 'Edit', 'Resend', etc as a string. All of which cause the MappedObjectController::access method to return AccessResult::forbidden().

I assume that this was done to reduce the number of potential false positive access grants when displaying the link on a route that has multiple parameters, one of which may be a mapped entity?

For us however where we are only mapping webform submissions to Salesforce objects it breaks the adding of the additional link tasks. You can still access the Salesforce Mapped Object page through the operations in the webform listing but that is less user friendly when reviewing submissions.

Steps to reproduce

Map a Salesforce Object to a Webform's Webform Submission.

View the results page for that Webform - the Salesforce link will appear in Operations.

View a Submission page itself and the Salesforce task will not appear alongside the 'View', 'Edit', 'Resend' tabs.

Proposed resolution

The basic solution we found for this was to take all the route parameters and check them all not just whatever current() returns.

    // There must be a better way to get the entity from a route match.
    $params = \Drupal::routeMatch()->getParameters()->all();
    if (!is_array($params)) {
      $params = [$params];
    }
    foreach ($params as $param) {
      if (!is_object($param)) {
        continue;
      }
      $implements = class_implements($param);
      if (empty($implements['Drupal\Core\Entity\EntityInterface'])) {
        continue;
      }
      // Only allow access for entities with mappings.
      if ( $this->entityTypeManager()
        ->getStorage('salesforce_mapping')
        ->loadByEntity($param)
      ) {
        return AccessResult::allowed();
      }
    }
    return AccessResult::forbidden();
πŸ› Bug report
Status

Needs review

Version

5.0

Component

salesforce_mapping_ui.module

Created by

πŸ‡¬πŸ‡§United Kingdom altcom_neil

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

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

Production build 0.71.5 2024