When migrating node translations the following error occurs:

Fatal error: Call to a member function getThirdPartySetting() on null in modules/contrib/scheduler/scheduler.module on line 333

I'm on Drupal 8.4;

The following code expects a valid entity:

  // If the node type is not enabled for Scheduler then do nothing.
  if (!$entity->getThirdPartySetting('scheduler', 'publish_enable', $config->get('default_publish_enable'))) {
    return;
  };

A similar issue can be found here: #2868294: Call to a member function getThirdPartySetting() on null in ContentTranslationManager

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

mpp created an issue. See original summary.

mpp’s picture

jonathan1055’s picture

Issue summary: View changes

That's interesting. Thanks for the patch and link to the other issue.

It would seem that your patch should fix the problem, and obviously won't cause any current tests to fail. But I'd like to try and replicate it before I fix it (always a good idea). Do you know how the reproduction steps could be made simple? Where you migrating from a 7.x to 8.x site?

Jonathan

mpp’s picture

Indeed, I was migrating a node translation from Drupal 7.

jonathan1055’s picture

Having thought about this a bit more, is it actually the contrib module's responsibility to ensure that $node->type->entity returns a valid entity object? There may be many 3rd-party implementations of hook_ENTITY_TYPE_presave() for node entities and I would expect it to be the initiating function's duty to ensure the $node object is complete? If we fix this in Scheduler, is it just hiding the problem, and will it have to be fixed in every other hook_node_presave() that might be invoked during node translation migration? Just asking the question ...

mpp’s picture

According to its signature the method expects an EntityInterface:

function hook_ENTITY_TYPE_presave(Drupal\Core\Entity\EntityInterface $entity) {

So normally you can only perform operations on that interface, in this case I'd assume the operation getEntityType() would suffice.

Now it appears that core has a number of instances where it doesn't respect the interface and just grabs publicly available properties:

function menu_ui_get_menu_link_defaults(NodeInterface $node) {
  // Prepare the definition for the edit form.
  /** @var \Drupal\node\NodeTypeInterface $node_type */
  $node_type = $node->type->entity;
...
}

function menu_ui_form_node_form_alter(&$form, FormStateInterface $form_state) {
  // Generate a list of possible parents (not including this link or descendants).
  // @todo This must be handled in a #process handler.
  $node = $form_state->getFormObject()->getEntity();
  $defaults = menu_ui_get_menu_link_defaults($node);
  /** @var \Drupal\node\NodeTypeInterface $node_type */
  $node_type = $node->type->entity;
...
}

Since the ENTITY_TYPE in your case is node (scheduler_node_presave) you 'could' presume the $node parameter is a NodeTypeInterface but still, accessing properties directly seems fishy.

taggartj’s picture

Had the same issue
Error: Call to a member function getThirdPartySetting() on null in /app/web/modules/contrib/scheduler/scheduler.module on line 333 #0 [internal function]: scheduler_node_presave(Object(Drupal\node\Entity\Node))

After testing this patch in PHP 7.1
https://www.drupal.org/files/issues/scheduler_fatal_error_call_to_member...

aka composer
patches":
"drupal/scheduler": {
"site install fix": "https://www.drupal.org/files/issues/scheduler_fatal_error_call_to_member..."
}

allowed me to get back in business !
thanks @ mpp
as you saved me time to make my own lol.

also Thanks for the hooks it made workbench integration not so bad.

function hook_scheduler_allow_publishing(NodeInterface $node) {
  if (!empty($node->publish_on) && !empty($node->moderation_state)) {
    if ($node->moderation_state->target_id == 'schedule_to_publish') {
      $time = time();
      if ($time >= $node->publish_on->value) {
        // Simply set the work bench state and save.
        $node->set('moderation_state', 'published');
        $node->save();
        return TRUE;
      }
    }
  }
  return FALSE;
}

jonathan1055’s picture

Hi taggartj,
What kind of things were you doing when the error happened? I'd like to replicate this.

@mmp,
Yes I see that it might be better if we use the functions in the EntityInterface I will try this.

jonathan1055’s picture

I tried to use methods available in $node to detect if this parameter is as expected, for example $node->getEntityTypeId(), $node->getType() and $node->getEntityType() to determine if method getThirdPartySetting() exists. I could not get it working as desired so decided to be safe and simply check for NULL as before.

  • jonathan1055 committed dcde416 on 8.x-1.x authored by mpp
    Issue #2902512 by mpp, jonathan1055: Call to a member function...
jonathan1055’s picture

Status: Needs review » Fixed

I'm going to call this fixed for now. However, it would be useful to add a test to cover the problem.

  • jonathan1055 committed 40b4ff3 on 8.x-1.x
    Issue #2902512 by jonathan1055: Use !empty instead of greater than 0 to...

Status: Fixed » Closed (fixed)

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