[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
1 @title Events User Guide: Installing Event Listeners 2 @group userguide 3 4 Using Phabricator event listeners to customize behavior. 5 6 = Overview = 7 8 Phabricator and Arcanist allow you to install custom runtime event listeners 9 which can react to certain things happening (like a Maniphest Task being edited 10 or a user creating a new Differential Revision) and run custom code to perform 11 logging, synchronize with other systems, or modify workflows. 12 13 These listeners are PHP classes which you install beside Phabricator or 14 Arcanist, and which Phabricator loads at runtime and runs in-process. They 15 require somewhat more effort upfront than simple configuration switches, but are 16 the most direct and powerful way to respond to events. 17 18 = Installing Event Listeners (Phabicator) = 19 20 To install event listeners in Phabricator, follow these steps: 21 22 - Write a listener class which extends @{class@libphutil:PhutilEventListener}. 23 - Add it to a libphutil library, or create a new library (for instructions, 24 see @{article:libphutil Libraries User Guide}. 25 - Configure Phabricator to load the library by adding it to `load-libraries` 26 in the Phabricator config. 27 - Configure Phabricator to install the event listener by adding the class 28 name to `events.listeners` in the Phabricator config. 29 30 You can verify your listener is registered in the "Events" tab of DarkConsole. 31 It should appear at the top under "Registered Event Listeners". You can also 32 see any events the page emitted there. For details on DarkConsole, see 33 @{article:Using DarkConsole}. 34 35 = Installing Event Listeners (Arcanist) = 36 37 To install event listeners in Arcanist, follow these steps: 38 39 - Write a listener class which extends @{class@libphutil:PhutilEventListener}. 40 - Add it to a libphutil library, or create a new library (for instructions, 41 see @{article:libphutil Libraries User Guide}. 42 - Configure Phabricator to load the library by adding it to `load` 43 in the Arcanist config (e.g., `.arcconfig`, or user/global config). 44 - Configure Arcanist to install the event listener by adding the class 45 name to `events.listeners` in the Arcanist config. 46 47 You can verify your listener is registered by running any `arc` command with 48 `--trace`. You should see output indicating your class was registered as an 49 event listener. 50 51 = Example Listener = 52 53 Phabricator includes an example event listener, 54 @{class:PhabricatorExampleEventListener}, which may be useful as a starting 55 point in developing your own listeners. This listener listens for a test 56 event that is emitted by the script `scripts/util/emit_test_event.php`. 57 58 If you run this script normally, it should output something like this: 59 60 $ ./scripts/util/emit_test_event.php 61 Emitting event... 62 Done. 63 64 This is because there are no listeners for the event, so nothing reacts to it 65 when it is emitted. You can add the example listener by either adding it to 66 your `events.listeners` configuration or with the `--listen` command-line flag: 67 68 $ ./scripts/util/emit_test_event.php --listen PhabricatorExampleEventListener 69 Installing 'PhabricatorExampleEventListener'... 70 Emitting event... 71 PhabricatorExampleEventListener got test event at 1341344566 72 Done. 73 74 This time, the listener was installed and had its callback invoked when the 75 test event was emitted. 76 77 = Available Events = 78 79 You can find a list of all Phabricator events in @{class:PhabricatorEventType}. 80 81 == All Events == 82 83 The special constant `PhutilEventType::TYPE_ALL` will let you listen for all 84 events. Normally, you want to listen only to specific events, but if you're 85 writing a generic handler you can listen to all events with this constant 86 rather than by enumerating each event. 87 88 == Arcanist Events == 89 90 Arcanist event constants are listed in @{class@arcanist:ArcanistEventType}. 91 92 All Arcanist events have this data available: 93 94 - `workflow` The active @{class@arcanist:ArcanistWorkflow}. 95 96 == Arcanist: Commit: Will Commit SVN == 97 98 The constant for this event is `ArcanistEventType::TYPE_COMMIT_WILLCOMMITSVN`. 99 100 This event is dispatched before an `svn commit` occurs and allows you to 101 modify the commit message. Data available on this event: 102 103 - `message` The text of the message. 104 105 == Arcanist: Diff: Will Build Message == 106 107 The constant for this event is `ArcanistEventType::TYPE_DIFF_WILLBUILDMESSAGE`. 108 109 This event is dispatched before an editable message is presented to the user, 110 and allows you to, e.g., fill in default values for fields. Data available 111 on this event: 112 113 - `fields` A map of field values to be compiled into a message. 114 115 == Arcanist: Diff: Was Created == 116 117 The constant for this event is `ArcanistEventType::TYPE_DIFF_WASCREATED`. 118 119 This event is dispatched after a diff is created. It is currently only useful 120 for collecting timing information. No data is available on this event. 121 122 == Arcanist: Revision: Will Create Revision == 123 124 The constant for this event is 125 `ArcanistEventType::TYPE_REVISION_WILLCREATEREVISION`. 126 127 This event is dispatched before a revision is created. It allows you to modify 128 fields to, e.g., edit revision titles. Data available on this event: 129 130 - `specification` Parameters that will be used to invoke the 131 `differential.createrevision` Conduit call. 132 133 == Controller: Check Request == 134 135 The constant for this event is 136 `PhabricatorEventType::TYPE_CONTROLLER_CHECKREQUEST`. 137 138 This event is dispatched when controller is about to begin execution. It is 139 meant for checking if the user is allowed to use the application at the moment. 140 It can check if the user has performed too many operations recently, if his IP 141 address is allowed or if the servers are overloaded to process the request. 142 Data available on this event: 143 144 - `request` Object of class @{class:AphrontRequest}. 145 - `controller` Class name of the current controller. 146 147 You can delegate the execution to another controller by modifying `controller`. 148 149 == Maniphest: Will Edit Task == 150 151 The constant for this event is 152 `PhabricatorEventType::TYPE_MANIPHEST_WILLEDITTASK`. 153 154 This event is dispatched before a task is edited, and allows you to respond to 155 or alter the edit. Data available on this event: 156 157 - ##task## The @{class:ManiphestTask} being edited. 158 - ##transactions## The list of edits (objects of class 159 @{class:ManiphestTransaction}) being applied. 160 - ##new## A boolean indicating if this task is being created. 161 - ##mail## If this edit originates from email, the 162 @{class:PhabricatorMetaMTAReceivedMail} object. 163 164 This is similar to the next event (did edit task) but occurs before the edit 165 begins. 166 167 == Maniphest: Did Edit Task == 168 169 The constant for this event is 170 `PhabricatorEventType::TYPE_MANIPHEST_DIDEDITTASK`. 171 172 This event is dispatched after a task is edited, and allows you to react to the 173 edit. Data available on this event: 174 175 - ##task## The @{class:ManiphestTask} that was edited. 176 - ##transactions## The list of edits (objects of class 177 @{class:ManiphestTransaction}) that were applied. 178 - ##new## A boolean indicating if this task was newly created. 179 - ##mail## If this edit originates from email, the 180 @{class:PhabricatorMetaMTAReceivedMail} object. 181 182 This is similar to the previous event (will edit task) but occurs after the 183 edit completes. 184 185 == Differential: Will Mark Generated == 186 187 The constant for this event is 188 `PhabricatorEventType::TYPE_DIFFERENTIAL_WILLMARKGENERATED`. 189 190 This event is dispatched before Differential decides if a file is generated (and 191 doesn't need to be reviewed) or not. Data available on this event: 192 193 - ##corpus## Body of the file. 194 - ##is_generated## Boolean indicating if this file should be treated as 195 generated. 196 197 == Diffusion: Did Discover Commit == 198 199 The constant for this event is 200 `PhabricatorEventType::TYPE_DIFFUSION_DIDDISCOVERCOMMIT`. 201 202 This event is dispatched when the daemons discover a commit for the first time. 203 This event happens very early in the pipeline, and not all commit information 204 will be available yet. Data available on this event: 205 206 - `commit` The @{class:PhabricatorRepositoryCommit} that was discovered. 207 - `repository` The @{class:PhabricatorRepository} the commit was discovered 208 in. 209 210 == Diffusion: Lookup User == 211 212 The constant for this event is 213 `PhabricatorEventType::TYPE_DIFFUSION_LOOKUPUSER`. 214 215 This event is dispatched when the daemons are trying to link a commit to a 216 Phabricator user account. You can listen for it to improve the accuracy of 217 associating users with their commits. 218 219 By default, Phabricator will try to find matches based on usernames, real names, 220 or email addresses, but this can result in incorrect matches (e.g., if you have 221 several employees with the same name) or failures to match (e.g., if someone 222 changed their email address). Listening for this event allows you to intercept 223 the lookup and supplement the results from another datasource. 224 225 Data available on this event: 226 227 - `commit` The @{class:PhabricatorRepositoryCommit} that data is being looked 228 up for. 229 - `query` The author or committer string being looked up. This will usually 230 be something like "Abraham Lincoln <[email protected]>", but 231 comes from the commit metadata so it may not be well-formatted. 232 - `result` The current result from the lookup (Phabricator's best guess at 233 the user PHID of the user named in the "query"). To substitute the result 234 with a different result, replace this with the correct PHID in your event 235 listener. 236 237 Using @{class@libphutil:PhutilEmailAddress} may be helpful in parsing the query. 238 239 == Search: Did Update Index == 240 241 The constant for this event is 242 `PhabricatorEventType::TYPE_SEARCH_DIDUPDATEINDEX`. 243 244 This event is dispatched from the Search application's indexing engine, after 245 it indexes a document. It allows you to publish search-like indexes into other 246 systems. 247 248 Note that this event happens after the update is fully complete: you can not 249 prevent or modify the update. Further, the event may fire significantly later 250 in real time than the update, as indexing may occur in the background. You 251 should use other events if you need guarantees about when the event executes. 252 253 Finally, this event may fire more than once for a single update. For example, 254 if the search indexes are rebuilt, this event will fire on objects which have 255 not actually changed. 256 257 So, good use cases for event listeners are: 258 259 - Updating secondary search indexes. 260 261 Bad use cases are: 262 263 - Editing the object or document. 264 - Anything with side effects, like sending email. 265 266 Data available on this event: 267 268 - `phid` The PHID of the updated object. 269 - `object` The object which was updated (like a @{class:ManiphesTask}). 270 - `document` The @{class:PhabricatorSearchAbstractDocument} which was indexed. 271 This contains an abstract representation of the object, and may be useful 272 in populating secondary indexes because it provides a uniform API. 273 274 == Test: Did Run Test == 275 276 The constant for this event is 277 `PhabricatorEventType::TYPE_TEST_DIDRUNTEST`. 278 279 This is a test event for testing event listeners. See above for details. 280 281 == UI: Did Render Actions == 282 283 The constant for this event is 284 `PhabricatorEventType::TYPE_UI_DIDRENDERACTIONS`. 285 286 This event is dispatched after a @{class:PhabricatorActionListView} is built by 287 the UI. It allows you to add new actions that your application may provide, like 288 "Fax this Object". Data available on this event: 289 290 - `object` The object which actions are being rendered for. 291 - `actions` The current list of available actions. 292 293 NOTE: This event is unstable and subject to change. 294 295 = Debugging Listeners = 296 297 If you're having problems with your listener, try these steps: 298 299 - If you're getting an error about Phabricator being unable to find the 300 listener class, make sure you've added it to a libphutil library and 301 configured Phabricator to load the library with `load-libraries`. 302 - Make sure the listener is registered. It should appear in the "Events" tab 303 of DarkConsole. If it's not there, you may have forgotten to add it to 304 `events.listeners`. 305 - Make sure it calls `listen()` on the right events in its `register()` 306 method. If you don't listen for the events you're interested in, you 307 won't get a callback. 308 - Make sure the events you're listening for are actually happening. If they 309 occur on a normal page they should appear in the "Events" tab of 310 DarkConsole. If they occur on a POST, you could add a `phlog()` 311 to the source code near the event and check your error log to make sure the 312 code ran. 313 - You can check if your callback is getting invoked by adding `phlog()` with 314 a message and checking the error log. 315 - You can try listening to `PhutilEventType::TYPE_ALL` instead of a specific 316 event type to get all events, to narrow down whether problems are caused 317 by the types of events you're listening to. 318 - You can edit the `emit_test_event.php` script to emit other types of 319 events instead, to test that your listener reacts to them properly. You 320 might have to use fake data, but this gives you an easy way to test the 321 at least the basics. 322 - For scripts, you can run under `--trace` to see which events are emitted 323 and how many handlers are listening to each event. 324 325 = Next Steps = 326 327 Continue by: 328 329 - taking a look at @{class:PhabricatorExampleEventListener}; or 330 - building a library with @{article:libphutil Libraries User Guide}.
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Nov 30 09:20:46 2014 | Cross-referenced by PHPXref 0.7.1 |