Problem/Motivation

The intention of sps_entity_create() is to provide an entity creation callback as defined by the Entity API while not knowing of the wrapped entity controller implements a creation method or not.
However, having a custom callback but simply call the create method on the controller there isn't any better than not having the function at all ;)

function sps_entity_create($values, $entity_type) {
  return entity_get_controller($entity_type)->create($values);
}

Proposed resolution

Get rid of the custom callback and add the create method in EntityControllerWrapper.
The method checks if the wrapped controller has the create method and forwards the call if possible.
Otherwise we simply cast the passed in values to an object and return this.
This should work at least for nodes.

Remaining tasks

Reviews needed.

User interface changes

None

API changes

  • Removed sps_entity_create()
  • Added EntityControllerWrapper::create()
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

saltednut’s picture

Status: Needs review » Reviewed & tested by the community

We were trying to use Inline Entity Form to create Nodes but running into this error.

Warning: call_user_func_array() expects parameter 1 to be a valid callback, class 'NodeController' does not have a method 'create' in Drupal\sps\EntityController\EntityControllerWrapper->__call() (line 67 of /sps/lib/Drupal/sps/EntityController/EntityControllerWrapper.php).

The patch applies to dev and the problem is fixed after clearing cache. (I get an xdebug error with Drupal looking for the missing sps_entity_create() function if I don't clear caches)

@das-peter - thank you for this patch. I would run out of fingers and toes if I tried to count the number of times your patches have saved me over the past few years!

saltednut’s picture

Status: Reviewed & tested by the community » Needs work

This fixes the problem for nodes but it actually broke Beans on my site.

Perhaps something to do with converting the values to an object?

Example:

Recoverable fatal error: Argument 3 passed to bean_form() must be an instance of Bean, boolean given in bean_form() (line 193 of /modules/contrib/bean/includes/bean.pages.inc). 
saltednut’s picture

Actually, adding EntityControllerWrapper::create()works and fixed my Inline Entity Form but removing sps_entity_create() seems to be destructive at least for Beans.

das-peter’s picture

@brantwynn Do beans define their own 'creation callback' in hook_entity_info()?

saltednut’s picture

@das-peter Strangely enough, it does not.

das-peter’s picture

Status: Needs work » Needs review

Just played around with this again and I think I know now what the problem is or at least could be.
The problem is that the modified class isn't picked up in certain places (thus missing the create method) because it doesn't fully implement EntityAPIControllerInterface - which declares the originally.
To avoid having to implement the whole interface in a generic way the approach from #3 seems to be better.
We provide our own creation method but if there's an original creation method we call it.
What I'm not sure of is what should happen if the entity type provides it's own logic in a callback function - can / should we preserve the original callback function and call it in our create method when the parent lacks of a create method?