Skip to content

Entity's label() method should use the 'label callback' property to allow more flexibility. #6877

@bennybobw

Description

@bennybobw

Allow Entities to Be More Extensible.

There are some issues in Backdrop with extensibility around certain entity methods and callbacks that were changed in D7 vs Backdrop.

Namely, it's proving to be tricky because of some changes in how Backdrop handles setting langcode property and the label() callback. A key thing to know about the entity_translation module is that it allows translations to be saved per field rather than per node, unlike the i18n module in Backdrop. This functionality is key for one of our clients because they have many fields that they want to remain constant over entities and not be translatable.

The issues I'm running into now mainly revolve around the removal of entity_language() and the entity label callback properties in Backdrop. For example, entity_translation works hand-in-hand with the title module to allow the title property to be translated. The issue I'm running into here is that the Drupal 7 entity api had a property called label callback that modules could define. The title module sets that for entities where it has overriden the title field and the callback then allows it to return the title in the correct language.

In backdrop, the label() callback for entities doesn't appear to have any kinds of hooks in it, so for instance in web/core/modules/node/node.entity.inc the label callback looks like this:

  /**
   * Implements EntityInterface::label().
   */
  public function label() {
    return $this->title;
  }

So not modifiable by any other modules unfortunately. I've come up with some clever workarounds for this type of thing but I'm afraid I'm going to run into more issues.

I'm running into a similar issue with setting up automatic path aliases for translations. Inside path_generate_entity_alias the langcode is previously set in the path form element like this:

function path_form_element(Entity $entity) {
  $langcode = isset($entity->langcode) ? $entity->langcode : LANGUAGE_NONE;

Setting the langcode for path alias in Drupal 7 was done with a callback called entity_language which in turn called a handler. This handler is set and implemented by entity_translation so that on forms where we're saving a "translation" we can set it to something other than the entity's main language.

function pathauto_entity_language($entity_type, $entity, $check_language_property = TRUE) {
  $langcode = NULL;

  if (function_exists('entity_language')) {
    $langcode = entity_language($entity_type, $entity);
  }
  elseif ($check_language_property && !empty($entity->language)) {
    $langcode = $entity->language;
  }
  //snip
}

// inside includes/common.inc
function entity_language($entity_type, $entity) {
  $info = entity_get_info($entity_type);

  // Invoke the callback to get the language. If there is no callback, try to
  // get it from a property of the entity, otherwise NULL.
  if (isset($info['language callback']) && function_exists($info['language callback'])) {
    $langcode = $info['language callback']($entity_type, $entity);
  }
  //snip
}

Proposed solution

We've kicked around some ideas over in a Zulip thread

My current solution would be to update the core entities so $langcode becomes a method with a hook e.g. $entity->langcode(). And same with label() -- that we provide a hook so other modules can adjust that value as needed. I'd also like to identify any other core properties/methods that would benefit from extensibility like this.

Alternatives that have been considered

There are a couple of related issues to this. @argiepiano is suggesting over in #6075 that we swap out all calls in core to core entities with entity_create so that other modules could override core entity classes. There are some concerns around allowing modules to override core entities, namely that only one module could do it at a time and that it could easily break a lot of stuff.

I suggested changing $entity->langcode so it has magic setters and getters so we didn't have to change core/contrib code to $entity->langcode at all, but @quicksketch said he doesn't like to use those because it makes debugging difficult (makes sense).

Herb said in Zuplip:

You'd also have the problem that any contrib or custom module might also reference $entity->langcode. That's a breaking change that would probably be for Backdrop 2.x in my opinion

Personally, I think we could get around this by just setting the langcode property on entity_load and then contrib modules could update as necessary.

This issue discusses removing 'label keys' in the taxonomy and node entity_info definitions, which IMO is a breaking change to the entity api #6867
Here's an issue discussing the removal of entity_language backdrop-contrib/title#15

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions