Warning: Undefined array key "target_type"

Created on 12 October 2023, 9 months ago
Updated 13 January 2024, 6 months ago

Problem/Motivation

Hi, I've set up a plugin as shown on Dialogue on how to implement a 4.0 plugin - with partial code 💬 Dialogue on how to implement a 4.0 plugin - with partial code Active

This is the contents of my plugin

<?php

namespace Drupal\computed_field_sale_badge\Plugin\ComputedField;

use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\computed_field\Field\ComputedFieldDefinitionWithValuePluginInterface;
use Drupal\computed_field\Plugin\ComputedField\ComputedFieldBase;



/**
 * @ComputedField(
 *   id = "computed_field_sale_badge_sale_badge",
 *   label = @Translation("Sale Badge"),
 *   field_type = "text",
 * )
 */

class SaleBadge extends ComputedFieldBase {

  /**
   * {@inheritdoc}
   */
  public function computeValue(EntityInterface $host_entity, ComputedFieldDefinitionWithValuePluginInterface $computed_field_definition): array {
    $value = '';

    if ($host_entity->hasField('list_price') && !$host_entity->get('list_price')->isEmpty()) {
      $listprice = $host_entity->get('list_price')->first()->toPrice();
      $price = $host_entity->get('price')->first()->toPrice();
      $saletext = t('Sale');

      if ($listprice > $price) {
        $value = '<div class="onsale">' . $saletext . '</div>';
      }
    }

    return [
      0 => [
        'value' => $value,
        'format' => 'full_html',
      ],
    ];
  }

}

Its a calculated field to show a badge on products that are on sale based on the product variation price. This worked fine in older versions of the module and does work as expected with version 4 following the above thread.

However I'm also getting the error

Warning: Undefined array key "target_type" in Drupal\computed_field\Entity\ComputedField->getSetting() (line 38 of modules/contrib/computed_field/src/Field/ComputedFieldSettingsTrait.php)

Can anybody shed some light on this?

Kind regards,

Steps to reproduce

Create and install custom plugin and enable error logging.

Using Drupal 10.1.5 and Drupal commerce 8.x-2.36

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

🐛 Bug report
Status

Fixed

Version

4.0

Component

Code

Created by

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

Comments & Activities

  • Issue created by @mellowtothemax
  • Assigned to Shreya_98
  • Open in Jenkins → Open on Drupal.org →
    Core: 10.1.4 + Environment: PHP 8.1 & MySQL 8
    last update 9 months ago
    3 pass
  • @shreya_th opened merge request.
  • Issue was unassigned.
  • Status changed to Needs review 9 months ago
  • 🇮🇳India Shreya_98

    Hi @joachim,
    I have fixed this issue and also created MR for this issue i.e. Undefined array key "target_type". Kindly review the changes .

  • 🇺🇦Ukraine paulrad

    Hi, @mellowtothemax!
    If @Shreya_th resolved your issue, consider moving it to RTBC status.

  • Status changed to RTBC 9 months ago
  • Status changed to Postponed: needs info 8 months ago
  • 🇬🇧United Kingdom joachim

    Could you provide a backtrace to see who is calling this?

    A text type field shouldn't be asked for this setting!

  • 🇩🇪Germany marcusx

    Have the same error on a commerce product variant. The backtrace looks like this:

    Warning: Undefined array key "target_type" in Drupal\computed_field\Entity\ComputedField->getSetting() (line 38 of /var/www/html/web/modules/contrib/computed_field/src/Field/ComputedFieldSettingsTrait.php)
    #0 /var/www/html/web/core/includes/bootstrap.inc(347): _drupal_error_handler_real(2, 'Undefined array...', '/var/www/html/w...', 38)
    #1 /var/www/html/web/modules/contrib/computed_field/src/Field/ComputedFieldSettingsTrait.php(38): _drupal_error_handler(2, 'Undefined array...', '/var/www/html/w...', 38)
    #2 /var/www/html/web/modules/contrib/commerce/modules/product/src/ProductAttributeFieldManager.php(89): Drupal\computed_field\Entity\ComputedField->getSetting('target_type')
    #3 [internal function]: Drupal\commerce_product\ProductAttributeFieldManager->Drupal\commerce_product\{closure}(Object(Drupal\computed_field\Entity\ComputedField))
    #4 /var/www/html/web/modules/contrib/commerce/modules/product/src/ProductAttributeFieldManager.php(91): array_filter(Array, Object(Closure))
    #5 /var/www/html/web/modules/contrib/commerce/modules/product/src/ProductAttributeFieldManager.php(142): Drupal\commerce_product\ProductAttributeFieldManager->getFieldDefinitions('class')
    #6 /var/www/html/web/modules/contrib/commerce/modules/product/src/ProductAttributeFieldManager.php(107): Drupal\commerce_product\ProductAttributeFieldManager->buildFieldMap()
    #7 /var/www/html/web/modules/contrib/commerce/modules/product/src/Entity/ProductVariation.php(290): Drupal\commerce_product\ProductAttributeFieldManager->getFieldMap('class')
    #8 /var/www/html/web/modules/contrib/commerce/modules/product/src/ProductViewBuilder.php(95): Drupal\commerce_product\Entity\ProductVariation->getAttributeFieldNames()
    #9 /var/www/html/web/core/lib/Drupal/Core/Entity/EntityViewBuilder.php(292): Drupal\commerce_product\ProductViewBuilder->alterBuild(Array, Object(Drupal\commerce_product\Entity\Product), Object(Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay), 'full')
    #10 /var/www/html/web/core/lib/Drupal/Core/Entity/EntityViewBuilder.php(239): Drupal\Core\Entity\EntityViewBuilder->buildMultiple(Array)
    #11 [internal function]: Drupal\Core\Entity\EntityViewBuilder->build(Array)
    #12 /var/www/html/web/core/lib/Drupal/Core/Security/DoTrustedCallbackTrait.php(101): call_user_func_array(Array, Array)
    #13 /var/www/html/web/core/lib/Drupal/Core/Render/Renderer.php(788): Drupal\Core\Render\Renderer->doTrustedCallback(Array, Array, 'Render #pre_ren...', 'exception', 'Drupal\\Core\\Ren...')
    #14 /var/www/html/web/core/lib/Drupal/Core/Render/Renderer.php(374): Drupal\Core\Render\Renderer->doCallback('#pre_render', Array, Array)
    #15 /var/www/html/web/core/lib/Drupal/Core/Render/Renderer.php(204): Drupal\Core\Render\Renderer->doRender(Array, false)
    #16 /var/www/html/web/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(242): Drupal\Core\Render\Renderer->render(Array, false)
    #17 /var/www/html/web/core/lib/Drupal/Core/Render/Renderer.php(580): Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}()
    #18 /var/www/html/web/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(243): Drupal\Core\Render\Renderer->executeInRenderContext(Object(Drupal\Core\Render\RenderContext), Object(Closure))
    #19 /var/www/html/web/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(132): Drupal\Core\Render\MainContent\HtmlRenderer->prepare(Array, Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Routing\CurrentRouteMatch))
    #20 /var/www/html/web/core/lib/Drupal/Core/EventSubscriber/MainContentViewSubscriber.php(90): Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse(Array, Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Routing\CurrentRouteMatch))
    #21 [internal function]: Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray(Object(Symfony\Component\HttpKernel\Event\ViewEvent), 'kernel.view', Object(Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher))
    #22 /var/www/html/web/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php(142): call_user_func(Array, Object(Symfony\Component\HttpKernel\Event\ViewEvent), 'kernel.view', Object(Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher))
    #23 /var/www/html/vendor/symfony/http-kernel/HttpKernel.php(174): Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object(Symfony\Component\HttpKernel\Event\ViewEvent), 'kernel.view')
    #24 /var/www/html/vendor/symfony/http-kernel/HttpKernel.php(81): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1)
    #25 /var/www/html/web/modules/contrib/force_password_change/src/Service/ForcePasswordChangeRedirectMiddleware.php(43): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
    #26 /var/www/html/web/core/lib/Drupal/Core/StackMiddleware/Session.php(58): Drupal\force_password_change\Service\ForcePasswordChangeRedirectMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
    #27 /var/www/html/web/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(48): Drupal\Core\StackMiddleware\Session->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
    #28 /var/www/html/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(106): Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
    #29 /var/www/html/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(85): Drupal\page_cache\StackMiddleware\PageCache->pass(Object(Symfony\Component\HttpFoundation\Request), 1, true)
    #30 /var/www/html/web/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(48): Drupal\page_cache\StackMiddleware\PageCache->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
    #31 /var/www/html/web/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(51): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
    #32 /var/www/html/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
    #33 /var/www/html/web/core/lib/Drupal/Core/DrupalKernel.php(718): Stack\StackedHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
    #34 /var/www/html/web/index.php(19): Drupal\Core\DrupalKernel->handle(Object(Symfony\Component\HttpFoundation\Request))
    #35 {main}
    .
    
  • 🇬🇧United Kingdom joachim

    Thanks!

    The code is this:

          $definitions = $this->entityFieldManager->getFieldDefinitions('commerce_product_variation', $variation_type_id);
          $definitions = array_filter($definitions, function ($definition) {
            /** @var \Drupal\Core\Field\FieldDefinitionInterface $definition */
            $field_type = $definition->getType();
            $target_type = $definition->getSetting('target_type');
            return $field_type == 'entity_reference' && $target_type == 'commerce_product_attribute_value';
    

    And WHY is this asking for a setting before it knows the type of the field???

  • 🇬🇧United Kingdom joachim

    Look like consuming code like Commerce is relying on this UNDOCUMENTED behaviour in FieldStorageConfig:

      public function getSetting($setting_name) {
        // @todo See getSettings() about potentially statically caching this.
        // We assume here that one call to array_key_exists() is more efficient
        // than calling getSettings() when all we need is a single setting.
        if (array_key_exists($setting_name, $this->settings)) {
          return $this->settings[$setting_name];
        }
        $settings = $this->getSettings();
        if (array_key_exists($setting_name, $settings)) {
          return $settings[$setting_name];
        }
        else {
          return NULL;
        }
      }
    

    So we should mimic that and get it documented in core.

  • Status changed to Active 8 months ago
  • 🇬🇧United Kingdom joachim
  • Status changed to Fixed 6 months ago
  • 🇬🇧United Kingdom joachim

    Fixed with a slightly simpler fix, but crediting @Shreya_th for the fix & everyone else for helping figure it out and review.

    Thanks everyone!

  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.69.0 2024