Add support for generating setters & multiple types of getters

Created on 22 August 2022, about 2 years ago
Updated 19 March 2024, 6 months ago

Problem/Motivation

It would be useful to be able to generate more types of methods (getters/setters/adders/removers) and have multiple possible generators per type. For example, for entity reference fields we could have getters returning the full entities and getters returning the ids.

Proposed resolution

Make EntityBundleClassMethodGenerators more abstract:

  • Rename EntityBundleClassMethodGeneratorInterface::buildGetter to EntityBundleClassMethodGeneratorInterface::buildMethod
  • Remove EntityBundleClassMethodGeneratorInterface::buildSetter (was never used anyway)
  • Add Getter suffix to existing method generators (e.g. EmailGetter instead of Email)
  • Add EntityBundleClassMethodGeneratorInterface::applies(FieldDefinitionInterface $field) to determine whether a certain generator can be used for a certain field
  • Stop using the id annotation property to match with field types, add a field_type property instead and give every method generator a unique ID
  • Add a type property to determine what kind of method will be generated (getter/setter/adder/remover)
  • Update the entity:bundle-class-generate command. Add an extra argument or option to determine what method types need to be generated. In case multiple generators exist for a certain field/method type combination, ask which one should be used.

Nice to have

(can be turned into follow up issues if this one becomes too big)

  • Add setter/adder/remover generators for all field types with existing getter generators
  • Add an admin form through which methods can be generated
  • Add settings through which default generators can be set for field type/method type combinations

Remaining tasks

Implement it!

User interface changes

A new administration form.

API changes

Changes to Drupal\entity_bundle_scaffold\EntityBundleClassMethodGeneratorInterface and Drupal\entity_bundle_scaffold\Annotation\EntityBundleClassMethodGenerator. These will probably require a new major version.

Data model changes

None.

Feature request
Status

Active

Version

3.0

Component

Code

Created by

🇧🇪Belgium dieterholvoet Brussels

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

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • 🇧🇪Belgium beerendlauwers

    is there a branch open for this? I'd like to customize and add to the method generators and this seems like a good fit.

    For determining whether a certain generator can be used for a certain field: we can take the logic from WidgetPluginManager that checks if it's in the 'field_types' array and also provides a static isApplicable method for making a decision on the field definition.

    I don't think it's handy to have it be a non-static method, because that would mean you would have to instantiate each plugin to check if it applies or not.

  • 🇧🇪Belgium dieterholvoet Brussels

    No, there isn't an open branch yet. Your approach sounds good!

  • 🇧🇪Belgium beerendlauwers

    What do you think of this initial annotation setup?

    namespace Drupal\entity_bundle_scaffold\Plugin\EntityBundleClassMethodGenerator;
    
    /**
     * A getter method generator for float fields.
     *
     * @EntityBundleClassMethodGenerator(
     *   id = "float_getter",
     *   method_prefix = "get",
     *   field_types = {
     *     "float": { "provider": "core" },
     *     "decimal": { "provider": "core" },
     *     "computed_decimal": { "provider": "computed_field" },
     *     "computed_float": { "provider": "computed_field" },
     *   }
     * )
     */
    class FloatGetter extends BaseScalarType {
    
      /**
       * {@inheritdoc}
       */
      public static function getType(): string {
        return 'float';
      }
    
    }
    

    This would add a get(fieldLabel) method to each applicable field type.

    A collection of thoughts as I was perusing the code:

    We could also pull out the method prefix from the annotation and have it be determined in a static parent method, e.g. FieldGetter.php. That might be cleaner, but would make one-off custom methods a bit more cumbersome because you would first have to define a parent class for your one-off method generator.

    We'll have to make some minor changes to EntityBundleClassGenerator::buildFieldGetterName (and rename it) to use that prefix.

    There might be some other things we might want to put into the plugin annotation / parent class logic, e.g. the method visibility and "generators.bundle_class.field_getter_name_source".

    The "generators.bundle_class.fields_to_ignore" setting might have to be a matrix of fields and applicable generators (think of the role / permission checkboxes matrix). This matrix might also solve https://www.drupal.org/project/entity_bundle_scaffold/issues/3402376 Make automatic bundle class/getter method generation configurable Active .

  • Assigned to beerendlauwers
  • 🇧🇪Belgium dieterholvoet Brussels

    Why not keep the field_types array simpler, like this:

    field_types = {
      "string_long",
      "email"
    }
    

    That's also how it's done for formatters and widgets.

    We could do applies or isApplicable, both are used in core.

    Another thing to add to the annotation: a type property to determine what kind of method will be generated (getter/setter/adder/remover). I mentioned this before in the proposed resolution in the issue description, feel free to keep that updated with any proposed changes.

  • 🇧🇪Belgium beerendlauwers

    I made the field_types array that way to support the different providers. Otherwise, you would still have a lot of code duplication for the same field. I mean, we could silently ignore any field types that do not exist, then you wouldn't need the provider keys anymore. Did you use these provider keys for anything else?

    Another thing to add to the annotation: a type property to determine what kind of method will be generated (getter/setter/adder/remover).

    I was wondering about that, what purpose does that have? For code generation, it doesn't really matter. It would be useful for categorization, so you could group the generators on an overview form or the like. What's your vision on it?

  • 🇧🇪Belgium dieterholvoet Brussels

    I made the field_types array that way to support the different providers.

    Right, I get it. Good call!

    I was wondering about that, what purpose does that have?

    If people want to generate certain kinds of methods on demand. Or if we want to offer the option to not automatically getters, setters and adders. Those might not all be necessary.

    I don't really have the capacity to work on this myself right now, but feel free to implement something and I'll review!

Production build 0.71.5 2024