I propose the entity template set $entity_type and remove the need for an intermediary custom base class for each entity type. This way all Drupal entities will be supported.

Background

This module does a lot of really great things to help speed up development. However, there is one thing that confuses me on how it works. And that is how this module doesn't support all Drupal entities out of the box. That is, unless you create a custom base class that minimally contains a __construct method to load the entity.

It's nice that this modules provides this base class for nodes and users, and the additional modules provide commerce, message, and organic group entities. But what was very confusing is that it doesn't work out of the box for taxonomy terms or other custom entities (such as ones created with ECK). This is confusing because entity_metadata_wrapper() supports them, as do other functions from the entity module (entity_load(), entity_load_single(), etc).

What was even more confusing is that the module let me create custom wrappers for taxonomy terms and ECK entities. But they didn't work because they couldn't load the entities. There wasn't any warning when I created the wrappers with drush, and the project page even seemed to indicate that all entities were supported.

6. This process works for other entity types, as well: Users, Commerce Products, OG Memberships, Messages etc. Just follow the command pattern: drush wrap ENTITY_TYPE

When I dug into the code, I was further confused because the "supported" entities seemed to be custom entity loading within their __construct() methods (node_load, user_load, etc.). Why is the code using these specific loading methods instead of using Entity API's unified method of loading entities: entity_load_single()? I see that WdEntityWrapper falls back to this, but it also requires that you have set the entity type as the first parameter. This is actually a violation of good OOP practices because the children classes (WdNodeWrapper, WdUserWrapper, etc.) don't have this as the first parameter!

Using entity_load_single() in WdEntityWrapper for all loading lets us now support all Drupal entities.

Proposal

  1. Change WdEntityWrapper __construct() to use a single parameter, $entity. This is what the children classes do already.
  2. Update the entity class template to set $entity_type rather than requiring an intermediary base class just to do the loading.
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

pianomansam’s picture

Status: Active » Needs review
FileSize
6.1 KB

Here is a quick patch file that does what I suggest. I've tested it on non-supported entities and nodes.

pianomansam’s picture

Status: Needs review » Needs work

The last submitted patch, 1: 2464623-1-wrappers-delight-support-all-entities.patch, failed testing.

zengenuity’s picture

This seems like a good change. I'm going to wrap it in with another update I'm working on to add a command to generate entity base classes, so it may be a few weeks before I commit this.

brockfanning’s picture

I agree this would be a good change. One thing that might be an issue is the static create() method. In WdEntityWrapper it creates a new WdEntityWrapper object. If I understand right, with this change, the new object would have no idea what entity type to use. Probably an easy fix, but just bringing it up.

zengenuity’s picture

@brockfanning is correct that the create functionality is an issue. I've reworked the patch to make that functional, and also fixed a several other spots in the provided base classes where it was failing after the changes.

The main issue with this change is that it's going to break sites with a custom entity base class. Since there are only 53 reported installs of this module, and since it only affects users who have written a custom base class and not ones that are only using generated bundle classes, I'm fine with making the API-breaking change. I'll put instructions for fixing at the top of the release notes. (People need to add the $entity_type variable, and remove their constructor, as was done with the provided base classes.)

The specific issue that will break current sites is that I had to reverse the parameters in WdEntityWrapper's constructor. You can now optionally pass an entity type in. If you do, it uses that. Otherwise, it reads from the variable that @pianomansam added.

I just ran a test with this patch applied, and I was able to create an entity with ECK, and then immediately generate wrapper classes for the bundles, without writing any base class. The generated wrapper classes work well, though they do not have methods for the properties of the entity. I'm going to work on that in #2455063: Add scaffold tool for new entity base classes.

zengenuity’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 6: 2464623-6-wrappers-delight-support-all-entities.patch, failed testing.

zengenuity’s picture

Version: 7.x-1.0 » 7.x-1.x-dev

Status: Needs work » Needs review
zengenuity’s picture

Actually, now I've thought of a way to support base entity wrappers written before the constructor change. I've added this code to the beginning of WdEntityWrapper::__construct().

<?php
// Provide a workaround for code written in the pre Issue #2464623 style.
// This constructor used to have arguments ($entity_type, $entity)
if (!is_null($entity_type) && is_string($entity) && (is_object($entity_type) || is_numeric($entity_type))) {
  $actual_entity = $entity_type;
  $entity_type = $entity;
  $entity = $actual_entity;
}
?>

I just dropped this latest version into a project where I wrote several custom entity base wrapper classes as well as used node, user and OG membership bundle wrappers, and it didn't blow up. Functionality all seems intact. Also passes tests on the rewritten base classes included in the patch.

zengenuity’s picture

I would appreciate it if some people could test these changes with existing projects or in-development projects where you already have some code written against the module, and report back whether it upgrades cleanly. I think it should at this point.

brockfanning’s picture

I'm only in the in-development stage at this point, but I tried updating the module code with this patch, and things still worked. I also tried regenerating all the bundle classes I had generated previously and re-adding my custom changes, and it still worked well.

pianomansam’s picture

My two custom ECK entities, nodes, and taxonomy term all updated correctly and continue to work.

zengenuity’s picture

Status: Needs review » Fixed

That's good enough for me. Committed. Thanks. I'll roll out out a new stable release with this change once I get the base entity class scaffolding tool done.

pianomansam’s picture

Great! Think you could roll #2464707: Image url helper function doesn't use image_style_url() into the update too?

zengenuity’s picture

Yes, that made it into the release: https://www.drupal.org/node/2468523

Status: Fixed » Closed (fixed)

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