Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Robust entity handling #337

Open
jonathanjfshaw opened this issue Jan 4, 2017 · 6 comments
Open

Robust entity handling #337

jonathanjfshaw opened this issue Jan 4, 2017 · 6 comments

Comments

@jonathanjfshaw
Copy link
Contributor

The handling of Drupal entities in Behat Drupal could be consolidated and made more robust.

  1. Drupal behat passes complex objects around to represent Drupal entities, back and forth between the driver and extension as well as within each, and these have no predefined structure or interface. As @pfrenssen said let's "transform $entity from a stdClass into a real class".

The entity object we pass around is basically a collection of desired field names and values, and so it gets messy when we went to add non-field values like entity type and these sit amidst the fields with no defined way of distinguishing them, and potentially colliding with them. Ideally we could have some kind of interface that defines properties: entity_type, bundle, id, canonical url, edit url, and fields. So it's $entity->fields that has the collection of desired fields that currently sits at $entity.

  1. Originally Drupal behat only supported nodes, terms and users. The new EntityContext (Create EntityContext #300) adds support for any other kind of entity. But none of these share any code. We have 4 separate paths for everything involving creating, cleaning up, and hooking into these entities. Let's create a new entity service that contains generic code for all these things, and a way for specific entity types (both ones we supply like Nodes, Terms and Users as well as arbitrary custom/contrib entities) to extend/replace/override the generic code. This should improve maintainability and extensibility.
@pfrenssen
Copy link
Collaborator

This is exactly what I had in mind, thanks for starting this!

@pfrenssen
Copy link
Collaborator

@jonathanjfshaw are you working on this? I'm willing to give this a go. My idea is to start this from the ground up, in DrupalDriver.

@jonathanjfshaw
Copy link
Contributor Author

jonathanjfshaw commented Jan 4, 2017 via email

@ademarco
Copy link
Contributor

Not sure if it's the same idea you guys had but I was wondering we could kind of "backport" Drupal 8-style entities in the Drupal Driver for Drupal 6 and 7 so that we create a coherent way of dealing with entities across all core versions.

I guess this should be an issue on the DrupalDriver side right? Is there already one?

@jonathanjfshaw
Copy link
Contributor Author

Yes, we should have an issue driver-side, but I don't think we do yet.

And yes, we need objects that live on the driver, but can be addressed from the extension in a version-agnostic way. Which takes us very close to "backporting D8-style entities".

An important difference though is that even for D8 the objects we need are actually a wrapper around the D8 entity - let's say an "entity handler" object. As I imagine it they would have a $fieldStrings property that held the array of field values that came from the extension, and a $entity property that held the actual Drupal object (entity object in D8, maybe something else more primitive in D6) created based on those fields. Because the contents of the $entity property would vary across core versions, we'd need other properties like $url that were set in version-dependent ways to produce version-independent results; but always mirroring what we'd expect from D8.

Discovery is the thing that is most complex here. How do developers create additional classes that live outside of the Driver and add support for new entity types, or override the driver's default objects; how to override for just 1 or 2 bundles of an entity type, or just in a specific step or scenario? Particularly how do you do this for a single scenario, using a tag, while using the step definitions from the extension?

My current thinking is to have an "entity manager" service in the driver, instantiated as a property on the rawDrupalContext . This would have a registry of custom entity handlers that you could add classes to in the construct method of your custom context, or in a scenario hook. When you called "$this->entityManager->getNew('node')" it would give you a new node handler object, using your custom handler if you had one currently registered, or the default Driver one if not.

A manual registry like this might seem crude compared to D8's plugin and annotations systems, but it's simple to create and we need something like it to allow for overriding anyway, while on the driver side it allows for discovery of the default handler to happen in exactly the path-based try-and-fallback way it does now for the driver's field handlers.

@jonathanjfshaw
Copy link
Contributor Author

Done right we could also discard all the complex code for hooking into @beforeUserCreate.
If people want to do things like that, they'd just create a custom User handler extending the provided one and add their own logic in it's create() method.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants