Long ago, I implemented an "event" system in order to provide extensibility for some operations. The system isn't very good, and we've found better solutions to these problems since the original implementation. I would like to reduce the size of this system over time and eventually remove it.
We have gradually reduced the size of the system. Continuing in this direction, we are deprecating the `TYPE_MANIPHEST_WILLEDITTASK` and `TYPE_MANIPHEST_DIDEDITTASK` events today and will remove them in a future version of Phabricator.
If you do not have custom event listeners, you are not affected. This is an advanced feature which very few installs are likely to be affected by.
The event system suffers from a number of irreparable problems that are fundamental to the architecture (for example, poor observability), but the biggest general issue is that modern modular extensions are much more powerful than events. Retaining events leaves us with two separate systems. We'd rather just have one way to do things.
If you currently use these events, you can replace your handlers with one of these approaches:
- For event handlers which modify the task or adjust transactions, a Herald action is probably the best replacement. See below for details.
- For event handlers which publish notifications into remote systems, see discussion in {T5462}.
- We are not aware of any other types of event handlers in the wild. If you have something which isn't covered here, you may need to fork. You can likely call your code from `ManiphestTransactionEditor`, either via `applyInitialEffects()` or `applyFinalEffects()`.
---
Writing a Herald Action
==================
In some cases, writing a Herald action is the best replacement for event behavior. In the simplest case, you'll write an action which has an effect like "Run MyCompany Special Rules", then write a Herald rule like this:
> When:
> [ Always ]
> Take these actions:
> [ Run MyCompany Special Rules ]
This will cause your action to always run. Your action can execute complex logic internally and decide whether or not to actually do anything, so this general case is broadly equivalent to the old event handler behavior.
Depending on what your handler does, it may also make sense to create actions which work more like real actions and move some of the logic into Herald itself. This may be a little more powerful and more flexible.
Herald actions fire in a phase between the WILLEDIT and DIDEDIT events: the primary transactions have already applied, but no notifications have been published about them yet. You can apply additional transactions which will be turned into part of the same transaction group for the purposes of mail, feed, etc.
Here's an example of how to write such an action (which just counts the number of transactions which applied):
{P1896}
To put it into effect, write a rule like this:
{F1004166}
Here's an example of it in action:
{F1004168}
Like other Herald actions, it will appear in the transcript:
{F1004172}
Broadly, all of the upstream Herald actions are also implemented like this, so you can look at other `HeraldAction` subclasses to figure out how to do things they do.