Error: Call to a member function hasTransition() on null

Created on 11 February 2024, 5 months ago
Updated 12 February 2024, 4 months ago

Problem/Motivation

While trying to access the handlers of a Webform that includes Webform Workflow Elements, the following error happens:

Error: Call to a member function hasTransition() on null in Drupal\webform_workflows_element\Plugin\WebformHandler\StateChangeEmailWebformHandler->getSummary() (line 148 of /opt/web/modules/contrib/webform_workflows_element/src/Plugin/WebformHandler/StateChangeEmailWebformHandler.php)
#0 /opt/web/modules/contrib/webform/src/WebformEntityHandlersForm.php(100): Drupal\webform_workflows_element\Plugin\WebformHandler\StateChangeEmailWebformHandler->getSummary()
#1 /opt/web/core/lib/Drupal/Core/Entity/EntityForm.php(106): Drupal\webform\WebformEntityHandlersForm->form(Array, Object(Drupal\Core\Form\FormState))
#2 /opt/web/modules/contrib/webform/src/Form/WebformEntityAjaxFormTrait.php(69): Drupal\Core\Entity\EntityForm->buildForm(Array, Object(Drupal\Core\Form\FormState))
#3 [internal function]: Drupal\webform\WebformEntityHandlersForm->buildForm(Array, Object(Drupal\Core\Form\FormState))
#4 /opt/web/core/lib/Drupal/Core/Form/FormBuilder.php(536): call_user_func_array(Array, Array)
#5 /opt/web/core/lib/Drupal/Core/Form/FormBuilder.php(283): Drupal\Core\Form\FormBuilder->retrieveForm('webform_handler...', Object(Drupal\Core\Form\FormState))
#6 /opt/web/core/lib/Drupal/Core/Controller/FormController.php(73): Drupal\Core\Form\FormBuilder->buildForm(Object(Drupal\webform\WebformEntityHandlersForm), Object(Drupal\Core\Form\FormState))
#7 [internal function]: Drupal\Core\Controller\FormController->getContentResult(Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Routing\RouteMatch))
#8 /opt/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(123): call_user_func_array(Array, Array)
#9 /opt/web/core/lib/Drupal/Core/Render/Renderer.php(580): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
#10 /opt/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(124): Drupal\Core\Render\Renderer->executeInRenderContext(Object(Drupal\Core\Render\RenderContext), Object(Closure))
#11 /opt/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(97): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array)
#12 /opt/vendor/symfony/http-kernel/HttpKernel.php(169): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
#13 /opt/vendor/symfony/http-kernel/HttpKernel.php(81): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1)
#14 /opt/web/core/lib/Drupal/Core/StackMiddleware/Session.php(58): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#15 /opt/web/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(48): Drupal\Core\StackMiddleware\Session->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#16 /opt/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(106): Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#17 /opt/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(85): Drupal\page_cache\StackMiddleware\PageCache->pass(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#18 /opt/web/core/modules/ban/src/BanMiddleware.php(50): Drupal\page_cache\StackMiddleware\PageCache->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#19 /opt/web/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(48): Drupal\ban\BanMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#20 /opt/web/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(51): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#21 /opt/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#22 /opt/web/core/lib/Drupal/Core/DrupalKernel.php(718): Stack\StackedHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#23 /opt/web/index.php(19): Drupal\Core\DrupalKernel->handle(Object(Symfony\Component\HttpFoundation\Request))
#24 {main}

Proposed resolution

My proposed solution is to simply check for the $workflowType variable has been set and that it has the transition.

if (!isset($workflowType) && !$workflowType->hasTransition($transition_id)) {

๐Ÿ› Bug report
Status

Needs review

Version

1.0

Component

Code

Created by

๐Ÿ‡ช๐Ÿ‡นEthiopia tsega

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

Merge Requests

Comments & Activities

  • Issue created by @tsega
  • ๐Ÿ‡ช๐Ÿ‡นEthiopia tsega

    Adds the check for the $workflowType not to be null.

  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia chetan 11

    chetan 11 โ†’ made their first commit to this issueโ€™s fork.

  • Merge request !14fixed โ†’ (Open) created by chetan 11
  • Status changed to Needs review 4 months ago
  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia chetan 11

    Please check the above MR.

  • ๐Ÿ‡ช๐Ÿ‡นEthiopia tsega

    @chentan11 Thanks for the MR but honestly I'm 100% sure if we're addressing the same thing. Can you please explain what your changes are doing?

  • ๐Ÿ‡ช๐Ÿ‡นEthiopia tsega

    Just a few observations regarding your changes:

    1. Your base branch was 1.0.x one but it should be the tag 1.0.0-alpha3
    2. The removed check (lines 147-149) are exactly what is required to stop the execution of the second foreach, i.e if the $workflow variable is not continue (skip) to the next step of the 1st loop (line 144)
    3. What you have changed does not actually execute:
      if ($workflowType === null) {
        continue;
      
        foreach ($states as $state) {
          $exploded = explode(':', $state);
          if ($exploded[0] != $element_id) {
            if (!$workflowType->hasTransition($transition_id)) {
              continue;
            }
      
            $transition = $workflowType->getTransition($transition_id);
            $settings['states'][$transition_id] = $transition->label();
          }
          return $summary;
        }
      }
      

      Every time the $workflowType === null condition is met, i.e. the $workflowType is null, the continue keyword would skip the forloop and go back to line 144.

      The rest of the code block there will never execute.

    Possible Solution

    The check you introduced should be written as follows:

    // See Drupal coding standards recommendations https://www.drupal.org/docs/develop/coding-standards/write-e_all-compliant-code
     if (is_null($workflowType)) { 
        continue;
     }
    
    // The reset of code
    
Production build 0.69.0 2024