API for "configurable behavior objects".

Required for
- Entity display plugin (an alternative to entity view modes),
- List format,
- Cfr block,
and possibly more in the future.

See https://www.youtube.com/watch?time_continue=1&v=AejsIbZO2MI

The API currently only exists for Drupal 7, but is arguably more powerful and flexible than the Drupal 8 plugin API.

Every PHP interface is implicitly a plugin type.
Some plugin types have integration in other Drupal subsystems, e.g. in Views.
Some plugin types act as configuration options for other plugins.

For every plugin type you get a drilldown configuration form.
The configuration can then be turned into a behavior object.

The goal is to make Drupal a lot more modular than it is now. Complex custom logic can now be easily implemented in independent components, reusable on the same or even on different Drupal websites.

A lot of plugin types and plugin implementations can be found in renderkit. You should look there for some inspiration.

A good start is to use this in combination with entdisp and/or listformat, which make some of the renderkit plugins available in views and other places in Drupal.

This module package contains multiple modules. (*)
Usually you will enable cfrplugin and the others as a dependency of other modules.
It is highly recommended to also enable cfrplugindiscovery, which is also part of this module suite. Without this, most of the plugins from renderkit will not be available.
Note: A module named "cfr" does not exist!

(*) The modules are packed together because they benefit from a shared version history. Cross-module refactoring becomes easier this way. If you disagree with this, open an issue.


Try entdisp_example for a demo!

How plugins work

In cfrplugin, every interface is automatically a plugin type.

A plugin of that type is an id and label associated with one of the following
- a class that implements the plugin type's interface
- a static method that returns an object implementing the type's interface.
- a class that implements Drupal\cfrapi\Configurator\ConfiguratorInterface, with a ->confGetValue() method that returns an instance of the plugin type's interface.
- a static method that returns such a configurator object. Typically the class that holds this static method should implement the plugin type's interface, so that cfrplugindiscovery can determine the plugin type.

Plugins are registered by implementing hook_cfrplugin_info(), and returning a nested associative array of plugin definitions keyed by the plugin type (interface name) and the plugin id.

It is recommended to organize your classes with PSR-4, annotate the plugins (class or static method) with @CfrPlugin(..) in the doc comment, and then call return cfrplugindiscovery()->moduleFileScanPsr4(__FILE__); from within hook_cfrplugin_info().

More about this in the README.md file.

Development status: Alpha, possibly soon stable

The module / API was in a "preview" state for a long while, because of expected API changes.

Most or all of these changes are done now. So you can start using the module!

There are likely no more API breaks - but no promise. Simply avoid updating this module on your live site. If you do update the module, look at the release notes and check if everything still works.

Alternative module name: "CBO"?

In hindsight, a more melodic and catchy module name would be "cbo" for "Configurable behavior objects" or "Configuration-born behavior objects". Technically, a configurator can give you any "configuration-born runtime value", but most of the time this value is a "behavior object".

Unfortunately, I do not think the disruption of a rename would be worthwhile. Maybe this

Drupal 8 ?

Work on a D8 version will start when I have some feedback from users.

One challenge will be the integration with the D8 service container. Annotated service dependencies could be the way to do this.

Move to github / Composer / Packagist?

Possibly, I want a major part of this API to move to github and packagist, and be independent of Drupal. The only Drupal-y part is the form handling, which needs to be different for e.g. the Symfony form API.

I do have some ideas for this, but first I want to see some feedback from this Drupal 7 module.

Project Information