Problem/Motivation

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

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

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

mellowtothemax created an issue. See original summary.

shreya_th’s picture

Assigned: Unassigned » shreya_th

shreya_th’s picture

Assigned: shreya_th » Unassigned
Status: Active » Needs review

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 .

mellowtothemax’s picture

Thanks this fixed it.

paulrad’s picture

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

mellowtothemax’s picture

Status: Needs review » Reviewed & tested by the community
joachim’s picture

Status: Reviewed & tested by the community » Postponed (maintainer needs more info)

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

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

marcusx’s picture

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}
.
joachim’s picture

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???

joachim’s picture

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: #3395748: getSetting()'s documentation should specify what happens when a setting doesn't exist.

joachim’s picture

Status: Postponed (maintainer needs more info) » Active
joachim’s picture

Status: Active » Fixed

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

Thanks everyone!

Status: Fixed » Closed (fixed)

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