There are chances that getOwner can return a null value if the referenced user has been deleted. The Comment entity does the following to ensure a user object is returned, even if it is just an anonymous user.

  /**
   * {@inheritdoc}
   */
  public function getOwner() {
    $user = $this->get('uid')->entity;
    if (!$user || $user->isAnonymous()) {
      $user = User::getAnonymousUser();
      $user->name = $this->getAuthorName();
      $user->homepage = $this->getHomepage();
    }
    return $user;
  }

We can provide the same checks, if !$user return User::getAnonymousUser. Would make a lot of checks simpler.

See Order

  /**
   * {@inheritdoc}
   */
  public function getCustomer() {
    $customer = $this->get('uid')->entity;
    // Handle deleted customers.
    if (!$customer) {
      $customer = User::getAnonymousUser();
    }
    return $customer;
  }
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

mglaman created an issue. See original summary.

mglaman’s picture

Issue summary: View changes
Issue tags: +Novice
jorgik’s picture

Hi @mglaman, here is the path. Could you please check it.

jorgik’s picture

Status: Active » Needs review
jorgik’s picture

Added some changes in tests, it was made the same way as in OrderTest for non-existent/deleted user ID case.

mglaman’s picture

Nice! And you updated the tests, great. This looks good, I'll take some time to review and make sure we didn't miss any entities.

bojanz’s picture

We have this in Product/Store:

      // If no owner has been set explicitly, make the anonymous user the owner.
      if (!$translation->getOwner()) {
        $translation->setOwnerId(0);
      }

Guessing it will no longer trigger. This was a fix for a crash (where saving a NULL as the uid wasn't accepted), our test coverage is either incomplete, or the crash is no longer a problem. Will need to doublecheck.

jorgik’s picture

I suppose that for User::getAnonymousUser(); a crash it's not a problem for now. Do I need to change something according to that in the patch?

jsacksick’s picture

Ok, so the attached patch introduced an EntityOwnerTrait in Commerce that basically uses core's EntityOwnerTrait and simply override getOwner() so we don't have to duplicate this logic everywhere.

I also replaced:

      // If no owner has been set explicitly, make the anonymous user the owner.
      if (!$translation->getOwner()) {
        $translation->setOwnerId(0);
      }

by

      // Explicitly set the owner ID to 0 if the translation owner is anonymous
      // (This will ensure we don't store a broken reference in case the user
      // no longer exists).
      if ($translation->getOwner()->isAnonymous()) {
        $translation->setOwnerId(0);
      }

and added tests coverage for that logic that we were missing.

Should we rename our EntityOwnerTrait to CommerceEntityOwnerTrait? Or just keep it as is?
EntityOwnerTrait has been introduced in Drupal core 8.7 so it's safe to use.

jsacksick’s picture

FileSize
621 bytes
20.24 KB

  • jsacksick committed 998de9b on 8.x-2.x
    Issue #3073942 by jsacksick, jorgik: Commerce entities implementing...
jsacksick’s picture

Status: Needs review » Fixed

Thanks, Committed!

jsacksick’s picture

Status: Fixed » Active

Warning: call_user_func() expects parameter 1 to be a valid callback, class 'Drupal\commerce_product\Entity\Product' does not have a method 'getCurrentUserId' in Drupal\Core\Field\FieldConfigBase->getDefaultValue() (line 397 of core/lib/Drupal/Core/Field/FieldConfigBase.php).

I opened a products view, and got this warning, so this means we probably need an update hook.

jsacksick’s picture

I've been trying to fix this via an update hook and couldn't really manage, (because base fields are overridden on my install...

So I'm wondering if our EntityOwnerTrait shouldn't provide a getCurrentUserId() method for BC reason.

And if we do, should we still do the following?

  $definition_update_manager = \Drupal::entityDefinitionUpdateManager();
  $storage_definition = $definition_update_manager->getFieldStorageDefinition('uid', 'commerce_product');
  $storage_definition
    ->setDefaultValueCallback(Product::class . '::getDefaultEntityOwner');
  $definition_update_manager->updateFieldStorageDefinition($storage_definition);

  $storage_definition = $definition_update_manager->getFieldStorageDefinition('uid', 'commerce_product_variation');
  $storage_definition
    ->setDefaultValueCallback(ProductVariation::class . '::getDefaultEntityOwner');
  $definition_update_manager->updateFieldStorageDefinition($storage_definition);
jsacksick’s picture

Status: Active » Needs review
jsacksick’s picture

Same patch, with update hooks for each entity type.

With that patch, I'm still experiencing issues because of the base fields overrides (that is without the getCurrentUserId() method.

jsacksick’s picture

FileSize
4.1 KB

Wrong update hook name for the payment hook.

jsacksick’s picture

FileSize
4.13 KB

Updated the deprecation notice to mention Commerce instead of core.

jsacksick’s picture

Not committing this yet until I figure out what to do with base field overrides.

mglaman’s picture

Not committing this yet until I figure out what to do with base field overrides.

They're config, so we could just edit, correct? We should add a test module that installs a current base field override and then we can test the upgrade.

jsacksick’s picture

Ok, the attached patch is taking care of the base field overrides which removes the need for getCurrentUserId(). I manually tested it on a dev install and the warning was gone after running the update and after clearing caches.

jsacksick’s picture

FileSize
6.74 KB

Hopefully the last iteration.

  • jsacksick committed 077c517 on 8.x-2.x
    Issue #3073942 follow-up by jsacksick: Update the base field definition...
jsacksick’s picture

Status: Needs review » Fixed

I was able to test this locally, so I went ahead and committed it.

jsacksick’s picture

Status: Fixed » Closed (fixed)

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