infinum / eightshift-libs

Library that is meant to be used inside Eightshift Boilerplate and Eightshift Boilerplate Plugin libs via composer in order to be able to easily set up a modern development process.
https://eightshift.com
MIT License
62 stars 11 forks source link

Better CLI loading for ServiceInterface implementations #438

Closed mbmjertan closed 5 days ago

mbmjertan commented 1 month ago

Description

Currently, if you want to load a ServiceInterface-implementing class in the WP-CLI context, such as a class inheriting from AbstractPostType or AbstractTaxonomy, you're out of luck. And you really should load those in the CLI context.

Only classes implementing ServiceCliInterface are loaded in the CLI context, and they're aren't loaded in the web context. Only classes implementing ServiceInterface are loaded in the web context, and you've guessed it.

This could be worked around by just making no such distinction, but that lowers developer flexibility and makes you unable not to load e.g. CLI commands in the web context.

Instead of such compromises, this PR proposes an alternative way to indicate a ServiceInterface should be loaded in CLI contexts using a class attribute, a cool new PHP 8 feature, alongside our good and trusted friend ReflectionClass. We have been using this without any performance penalty on the web and nothing noticeable in WP-CLI for months now.

If this PR is merged, you'll be able to ensure a service class gets loaded in the WP-CLI context like so:

<?php
namespace EightshiftProject\Services;

#[ShouldLoadInCliContext]
class SomeServiceClass implements ServiceInterface 
{
  // ...
}

Additionally, if your class is a child of any class annotated with the ShouldLoadInCliContext attribute, it will be loaded, so you can annotate AbstractTaxonomy with the ~mark of the devil~ attribute or do things like these:

<?php
namespace EightshiftProject\Things;

#[ShouldLoadInCliContext]
abstract AbstractSomethingService implements ServiceInterface
{
  // ...
}
<?php
namespace EighshiftProject\Things;

class SomethingService extends AbstractSomethingService {
  // ...
}

I believe this is a valuable backend addition to eightshift-libs and it has helped us to entirely eliminate issues with loading post types, taxonomies and other shared service interfaces in our projects. I am open to any and all comments.

If this gets merged, please also mark AbstractPostType and AbstractTaxonomy with the attribute.