Establish host variations as an architectural concept

Created on 5 February 2024, 11 months ago
Updated 7 February 2024, 11 months ago

Problem/Motivation

When working on ✨ Allow admins to change host entity for existing registration Active I have been faced with the task of determining which other hosts it might be suitable to change a registration to. The solution I've had to implement is kind of complicated, using event subscribers.

But actually in 90% of use cases the answer is relatively simple: you can change the registration to any other host within the same overall event. But this is not a concept that Registration core currently has.

This is a limitation of sorts in the current architecture. Registration core does not distinguish between 2 meanings of 'host'
- the 'package' or variation that specifies exactly what the user has selected to register; and
- the 'event' - the basic context or thing a user thinks they are registering for.

Commerce Registration effectively introduces the distinction implicitly, but hardcodes it as the distinction between product and product variation.

I hit against similar edge cases when I want to use the group module to have groups as events, but then make them registerable using commerce reistation with different variations or flavours for each event. So in my case it's 1 product variation per product, multiple products per group; could perfectly well be multiple variations per product, 1 product per group. It's not that the registration module as it's currently designed blocks me from doing what I need to do, but I can see myself straining at the architectural limits. For example, if I want to provide a "register" button on my group for each available registerable variation, I have to to create quite a lot of custom logic.

I suggest that we introduce a distinction between "host" (package/variation) and "context" (event) a basic architectural concept of the module.

This would significantly simplify ✨ Allow admins to change host entity for existing registration Active and in my project allow my group->product->variation custom logic to be more elegantly integrated at a higher level.

Proposed resolution

In Registration core provide:

Add a HostContextEntityInterface and HostContextEntity class, with methods:
- all of the methods of HostEntityInterface, but with the semantic changed so they apply to the context entity in some cases (e.g. label, id) and any host belonging to the context in other cases (e.g. is userRegistered, hasSpaces).
- an additional method getHosts() that gets all of the hosts for the context

Add a createHostContextEntity() method to RegistrationHostEntityHandler.

Add a getContext() method to HostEntityInterface and HostEntity that returns a wrapped instance of HostContextEntity. In HostEntity the HostContextEntity is based around the same entity as the HostEntity; the host is also the context, it's 1:1.

In Registration Commerce provide:

A ProductVariationHostEntityHandler that is set as the handler for product variations that returns a ProductVariationHostEntity for its createHostEntity method.

A ProductHostEntityHandler that is set as the handler for products that returns a ProductHostContextEntity for its createHostContextEntity method.

ProductVariationHostEntity class extending HostEntity that expects to wrap a ProductVariation and returns a ProductHostContextEntity in it's getContext() method. i.e. you get the product as the context for any of the variations as hosts.

ProductHostContextEntity class extending HostContextEntity that expects to wrap a Product and returns instances of ProductVariationHostEntity in it's getHosts() method. i.e. you can get the variations as the hosts from the product as context

Remaining tasks

tbd

User interface changes

None

API changes

Some, but BC under the 1:1 interface:class rule as anyone implementing the interface should be extending the provided default class as if it were a base class.

Data model changes

None

✨ Feature request
Status

Active

Version

3.1

Component

Registration Core

Created by

πŸ‡¬πŸ‡§United Kingdom jonathanshaw Stroud, UK

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @jonathanshaw
  • πŸ‡ΊπŸ‡ΈUnited States john.oltman

    Thanks for this excellent post @jonathanshaw. Abstracting the host entity further could also help with a number of other feature requests besides the "change host entity" request:

    * https://www.drupal.org/project/registration/issues/2587903 ✨ Option to make a registration selection Active
    * https://www.drupal.org/project/registration/issues/2634340 ✨ Support multiple capacities by type Active
    * https://www.drupal.org/project/commerce_registration/issues/3415425 πŸ’¬ Multi-Level Pricing? Active

    In all three of those requests, there is a need to have the host entity context be different, and at a "grouping" level (i.e. product in a Commerce install), vs. where the registration field is attached, at least for some checks like capacity. You are definitely onto something here. One issue is the context will be totally variable per site - for many, the "event" will be at the variation level and not the product - for others (sounds like your site) the context is at the product level. Certainly in the scenarios in those three feature requests, some host entity checks need to be at the grouping level - maybe all - not sure yet. Going to ponder this further.

  • πŸ‡¬πŸ‡§United Kingdom jonathanshaw Stroud, UK

    My basic thought on the 3 issues you reference is: the challenges we face here are very similar to those commerce faces with products and where they have huge real world experience; leading them to the products, variations, attributes architecture. I'm particularly thinking of the way variations can be auto-generated from combinations of attributes, being the atomic unit to define the customer choice although not always customer-facing.

    Maybe we need the same basic setup:
    - the atomic host variation
    - the grouping that holds a set of atomic hosts
    - a range of services to get availability etc that can be decorated/overridden like commerce's price checker etc services, because we know our simple 2 level architecture won't suit every use case.

  • πŸ‡¬πŸ‡§United Kingdom jonathanshaw Stroud, UK

    I realised there's an important distinction between shopping and registering. A person can buy as many different things as they like, and as many of each thing; but a person can only be in one place at a time. Thus there are hosts a user should not be able to register for if they have already registered for another 'host' within the same 'scope'.

    This suggests we do have a clear need and meaning for a concept of 'scope' that is higher-level than host. Different sites might attach different meanings to the idea of scope just as they do to host, but the one we insist on is that there can't be multiple registrations of the same user within a single scope.

Production build 0.71.5 2024