(dev/core#873) civi.api.prepare - Allow dynamic wrappers #14047
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Overview
Allow extensions to dynamically wrap an API. There are some existing mechanisms which sort-of allow wrapping, but this enables additional use-cases. It is primarily expected to be used with a business-y APIs (like
Mailing.submit
) rather than CRUD-y APIs (likeMailing.get
), but the technique can be used on any API call.Before
There are a few techniques for wrapping or overriding an API, but none is suitable to my current use-case. Limitations:
hook_civicrm_apiWrappers
- This allows registering things before and after the API call, but it does not allow changing the underlying API call.civi.api.{authorize,prepare,respond}
events - Same as above. These are a bit more nuanced/fine-grained, but still does not allow changingcivi.api.resolve
event withAdhocProvider
- This allows you to swap an API completely, but it doesn't allow you to delegate back to the original API call (if you've got nothing to add).After
One may subscribe to
civi.api.prepare
and then call thewrapApi()
helper:Key characteristics:
$continue
).$continue
.$continue
once... or twice... or thrice... or not at all.The style here is more event-oriented, but you can see the same concept in OOP systems, such as PHP's function-override notation. This would be analogous: