Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/repository/parser/PhabricatorRepositoryCommitMessageDetailParser.php b/src/applications/repository/parser/PhabricatorRepositoryCommitMessageDetailParser.php
index 444efc55f8..34d4b230d8 100644
--- a/src/applications/repository/parser/PhabricatorRepositoryCommitMessageDetailParser.php
+++ b/src/applications/repository/parser/PhabricatorRepositoryCommitMessageDetailParser.php
@@ -1,113 +1,117 @@
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
abstract class PhabricatorRepositoryCommitMessageDetailParser {
private $commit;
private $commitData;
final public function __construct(
PhabricatorRepositoryCommit $commit,
PhabricatorRepositoryCommitData $data) {
$this->commit = $commit;
$this->commitData = $data;
}
final public function getCommit() {
return $this->commit;
}
final public function getCommitData() {
return $this->commitData;
}
/**
* Try to link a commit name to a Phabricator account. Basically we throw it
* at the wall and see if something sticks.
*/
public function resolveUserPHID($user_name) {
if (!strlen($user_name)) {
return null;
}
$phid = $this->findUserByUserName($user_name);
if ($phid) {
return $phid;
}
$phid = $this->findUserByEmailAddress($user_name);
if ($phid) {
return $phid;
}
$phid = $this->findUserByRealName($user_name);
if ($phid) {
return $phid;
}
// No hits yet, try to parse it as an email address.
$email = new PhutilEmailAddress($user_name);
$phid = $this->findUserByEmailAddress($email->getAddress());
if ($phid) {
return $phid;
}
$display_name = $email->getDisplayName();
if ($display_name) {
+ $phid = $this->findUserByUserName($display_name);
+ if ($phid) {
+ return $phid;
+ }
$phid = $this->findUserByRealName($display_name);
if ($phid) {
return $phid;
}
}
return null;
}
abstract public function parseCommitDetails();
private function findUserByUserName($user_name) {
$by_username = id(new PhabricatorUser())->loadOneWhere(
'userName = %s',
$user_name);
if ($by_username) {
return $by_username->getPHID();
}
return null;
}
private function findUserByRealName($real_name) {
// Note, real names are not guaranteed unique, which is why we do it this
// way.
$by_realname = id(new PhabricatorUser())->loadOneWhere(
'realName = %s LIMIT 1',
$real_name);
if ($by_realname) {
return $by_realname->getPHID();
}
return null;
}
private function findUserByEmailAddress($email_address) {
$by_email = PhabricatorUser::loadOneWithEmailAddress($email_address);
if ($by_email) {
return $by_email->getPHID();
}
return null;
}
}
diff --git a/src/applications/repository/worker/commitmessageparser/PhabricatorRepositoryCommitMessageParserWorker.php b/src/applications/repository/worker/commitmessageparser/PhabricatorRepositoryCommitMessageParserWorker.php
index 770330ec66..da89a7a698 100644
--- a/src/applications/repository/worker/commitmessageparser/PhabricatorRepositoryCommitMessageParserWorker.php
+++ b/src/applications/repository/worker/commitmessageparser/PhabricatorRepositoryCommitMessageParserWorker.php
@@ -1,351 +1,385 @@
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
abstract class PhabricatorRepositoryCommitMessageParserWorker
extends PhabricatorRepositoryCommitParserWorker {
abstract protected function getCommitHashes(
PhabricatorRepository $repository,
PhabricatorRepositoryCommit $commit);
final protected function updateCommitData($author, $message,
$committer = null) {
$commit = $this->commit;
$data = id(new PhabricatorRepositoryCommitData())->loadOneWhere(
'commitID = %d',
$commit->getID());
if (!$data) {
$data = new PhabricatorRepositoryCommitData();
}
$data->setCommitID($commit->getID());
$data->setAuthorName($author);
$data->setCommitMessage($message);
if ($committer) {
$data->setCommitDetail('committer', $committer);
}
$repository = $this->repository;
$detail_parser = $repository->getDetail(
'detail-parser',
'PhabricatorRepositoryDefaultCommitMessageDetailParser');
if ($detail_parser) {
$parser_obj = newv($detail_parser, array($commit, $data));
$parser_obj->parseCommitDetails();
}
- $author_phid = $data->getCommitDetail('authorPHID');
- if ($author_phid) {
+ $author_phid = $this->lookupUser(
+ $commit,
+ $data->getAuthorName(),
+ $data->getCommitDetail('authorPHID'));
+ $data->setCommitDetail('authorPHID', $author_phid);
+
+ $committer_phid = $this->lookupUser(
+ $commit,
+ $data->getCommitDetail('committer'),
+ $data->getCommitDetail('committerPHID'));
+ $data->setCommitDetail('committerPHID', $committer_phid);
+
+ if ($author_phid != $commit->getAuthorPHID()) {
$commit->setAuthorPHID($author_phid);
$commit->save();
}
$conn_w = id(new DifferentialRevision())->establishConnection('w');
// NOTE: The `differential_commit` table has a unique ID on `commitPHID`,
// preventing more than one revision from being associated with a commit.
// Generally this is good and desirable, but with the advent of hash
// tracking we may end up in a situation where we match several different
// revisions. We just kind of ignore this and pick one, we might want to
// revisit this and do something differently. (If we match several revisions
// someone probably did something very silly, though.)
$revision_id = $data->getCommitDetail('differential.revisionID');
if (!$revision_id) {
$hashes = $this->getCommitHashes(
$this->repository,
$this->commit);
if ($hashes) {
$query = new DifferentialRevisionQuery();
$query->withCommitHashes($hashes);
$revisions = $query->execute();
if (!empty($revisions)) {
$revision = $this->identifyBestRevision($revisions);
$revision_id = $revision->getID();
}
}
}
if ($revision_id) {
$revision = id(new DifferentialRevision())->load($revision_id);
if ($revision) {
queryfx(
$conn_w,
'INSERT IGNORE INTO %T (revisionID, commitPHID) VALUES (%d, %s)',
DifferentialRevision::TABLE_COMMIT,
$revision->getID(),
$commit->getPHID());
$commit_is_new = $conn_w->getAffectedRows();
$committer_phid = $data->getCommitDetail('committerPHID');
if ($committer_phid) {
$handle = PhabricatorObjectHandleData::loadOneHandle($committer_phid);
$committer_name = '@'.$handle->getName();
} else {
$committer_name = $data->getCommitDetail('committer');
}
$author_phid = $data->getCommitDetail('authorPHID');
if ($author_phid) {
$handle = PhabricatorObjectHandleData::loadOneHandle($author_phid);
$author_name = '@'.$handle->getName();
} else {
$author_name = $data->getAuthorName();
}
$commit_name = $repository->formatCommitName(
$commit->getCommitIdentifier());
$info = array();
$info[] = "authored by {$author_name}";
if ($committer_name && ($committer_name != $author_name)) {
$info[] = "committed by {$committer_name}";
}
$info = implode(', ', $info);
$message = "Closed by commit {$commit_name} ({$info}).";
$actor_phid = nonempty(
$committer_phid,
$author_phid,
$revision->getAuthorPHID());
$status_closed = ArcanistDifferentialRevisionStatus::CLOSED;
$should_close = $commit_is_new &&
($revision->getStatus() != $status_closed) &&
$repository->shouldAutocloseCommit($commit, $data);
if ($should_close) {
$diff = $this->attachToRevision($revision, $actor_phid);
$revision->setDateCommitted($commit->getEpoch());
$editor = new DifferentialCommentEditor(
$revision,
$actor_phid,
DifferentialAction::ACTION_CLOSE);
$editor->setIsDaemonWorkflow(true);
$vs_diff = $this->loadChangedByCommit($diff);
if ($vs_diff) {
$data->setCommitDetail('vsDiff', $vs_diff->getID());
$changed_by_commit = PhabricatorEnv::getProductionURI(
'/D'.$revision->getID().
'?vs='.$vs_diff->getID().
'&id='.$diff->getID().
'#differential-review-toc');
$editor->setChangedByCommit($changed_by_commit);
}
$editor->setMessage($message)->save();
}
}
}
$data->save();
}
private function attachToRevision(
DifferentialRevision $revision,
$actor_phid) {
$drequest = DiffusionRequest::newFromDictionary(array(
'repository' => $this->repository,
'commit' => $this->commit->getCommitIdentifier(),
));
$raw_diff = DiffusionRawDiffQuery::newFromDiffusionRequest($drequest)
->loadRawDiff();
$changes = id(new ArcanistDiffParser())->parseDiff($raw_diff);
$diff = DifferentialDiff::newFromRawChanges($changes)
->setRevisionID($revision->getID())
->setAuthorPHID($actor_phid)
->setCreationMethod('commit')
->setSourceControlSystem($this->repository->getVersionControlSystem())
->setLintStatus(DifferentialLintStatus::LINT_SKIP)
->setUnitStatus(DifferentialUnitStatus::UNIT_SKIP)
->setDateCreated($this->commit->getEpoch())
->setDescription(
'Commit r'.
$this->repository->getCallsign().
$this->commit->getCommitIdentifier());
// TODO: This is not correct in SVN where one repository can have multiple
// Arcanist projects.
$arcanist_project = id(new PhabricatorRepositoryArcanistProject())
->loadOneWhere('repositoryID = %d LIMIT 1', $this->repository->getID());
if ($arcanist_project) {
$diff->setArcanistProjectPHID($arcanist_project->getPHID());
}
$parents = DiffusionCommitParentsQuery::newFromDiffusionRequest($drequest)
->loadParents();
if ($parents) {
$diff->setSourceControlBaseRevision(head_key($parents));
}
// TODO: Attach binary files.
return $diff->save();
}
private function loadChangedByCommit(DifferentialDiff $diff) {
$repository = $this->repository;
$vs_changesets = array();
$vs_diff = id(new DifferentialDiff())->loadOneWhere(
'revisionID = %d AND creationMethod != %s ORDER BY id DESC LIMIT 1',
$diff->getRevisionID(),
'commit');
foreach ($vs_diff->loadChangesets() as $changeset) {
$path = $changeset->getAbsoluteRepositoryPath($repository, $vs_diff);
$path = ltrim($path, '/');
$vs_changesets[$path] = $changeset;
}
$changesets = array();
foreach ($diff->getChangesets() as $changeset) {
$path = $changeset->getAbsoluteRepositoryPath($repository, $diff);
$path = ltrim($path, '/');
$changesets[$path] = $changeset;
}
if (array_fill_keys(array_keys($changesets), true) !=
array_fill_keys(array_keys($vs_changesets), true)) {
return $vs_diff;
}
$hunks = id(new DifferentialHunk())->loadAllWhere(
'changesetID IN (%Ld)',
mpull($vs_changesets, 'getID'));
$hunks = mgroup($hunks, 'getChangesetID');
foreach ($vs_changesets as $changeset) {
$changeset->attachHunks(idx($hunks, $changeset->getID(), array()));
}
$file_phids = array();
foreach ($vs_changesets as $changeset) {
$metadata = $changeset->getMetadata();
$file_phid = idx($metadata, 'new:binary-phid');
if ($file_phid) {
$file_phids[$file_phid] = $file_phid;
}
}
$files = array();
if ($file_phids) {
$files = id(new PhabricatorFile())->loadAllWhere(
'phid IN (%Ls)',
$file_phids);
$files = mpull($files, null, 'getPHID');
}
foreach ($changesets as $path => $changeset) {
$vs_changeset = $vs_changesets[$path];
$file_phid = idx($vs_changeset->getMetadata(), 'new:binary-phid');
if ($file_phid) {
if (!isset($files[$file_phid])) {
return $vs_diff;
}
$drequest = DiffusionRequest::newFromDictionary(array(
'repository' => $this->repository,
'commit' => $this->commit->getCommitIdentifier(),
'path' => $path,
));
$corpus = DiffusionFileContentQuery::newFromDiffusionRequest($drequest)
->loadFileContent()
->getCorpus();
if ($files[$file_phid]->loadFileData() != $corpus) {
return $vs_diff;
}
} else if ($changeset->makeChangesWithContext() !=
$vs_changeset->makeChangesWithContext()) {
return $vs_diff;
}
}
return null;
}
/**
* When querying for revisions by hash, more than one revision may be found.
* This function identifies the "best" revision from such a set. Typically,
* there is only one revision found. Otherwise, we try to pick an accepted
* revision first, followed by an open revision, and otherwise we go with a
* closed or abandoned revision as a last resort.
*/
private function identifyBestRevision(array $revisions) {
assert_instances_of($revisions, 'DifferentialRevision');
// get the simplest, common case out of the way
if (count($revisions) == 1) {
return reset($revisions);
}
$first_choice = array();
$second_choice = array();
$third_choice = array();
foreach ($revisions as $revision) {
switch ($revision->getStatus()) {
// "Accepted" revisions -- ostensibly what we're looking for!
case ArcanistDifferentialRevisionStatus::ACCEPTED:
$first_choice[] = $revision;
break;
// "Open" revisions
case ArcanistDifferentialRevisionStatus::NEEDS_REVIEW:
case ArcanistDifferentialRevisionStatus::NEEDS_REVISION:
$second_choice[] = $revision;
break;
// default is a wtf? here
default:
case ArcanistDifferentialRevisionStatus::ABANDONED:
case ArcanistDifferentialRevisionStatus::CLOSED:
$third_choice[] = $revision;
break;
}
}
// go down the ladder like a bro at last call
if (!empty($first_choice)) {
return $this->identifyMostRecentRevision($first_choice);
}
if (!empty($second_choice)) {
return $this->identifyMostRecentRevision($second_choice);
}
if (!empty($third_choice)) {
return $this->identifyMostRecentRevision($third_choice);
}
}
/**
* Given a set of revisions, returns the revision with the latest
* updated time. This is ostensibly the most recent revision.
*/
private function identifyMostRecentRevision(array $revisions) {
assert_instances_of($revisions, 'DifferentialRevision');
$revisions = msort($revisions, 'getDateModified');
return end($revisions);
}
+
+ /**
+ * Emit an event so installs can do custom lookup of commit authors who may
+ * not be naturally resolvable.
+ */
+ private function lookupUser(
+ PhabricatorRepositoryCommit $commit,
+ $query,
+ $guess) {
+
+ $type = PhabricatorEventType::TYPE_DIFFUSION_LOOKUPUSER;
+ $data = array(
+ 'commit' => $commit,
+ 'query' => $query,
+ 'result' => $guess,
+ );
+
+ $event = new PhabricatorEvent($type, $data);
+ PhutilEventEngine::dispatchEvent($event);
+
+ return $event->getValue('result');
+ }
+
}
diff --git a/src/docs/userguide/events.diviner b/src/docs/userguide/events.diviner
index 3ca182fe96..2dfe023dac 100644
--- a/src/docs/userguide/events.diviner
+++ b/src/docs/userguide/events.diviner
@@ -1,217 +1,246 @@
@title Events User Guide: Installing Event Listeners
@group userguide
Using Phabricator event listeners to customize behavior.
= Overview =
Phabricator allows you to install custom runtime event listeners which can react
to certain things happening (like a Maniphest Task being edited) and run custom
code to perform logging, synchronize with other systems, or modify workflows.
These listeners are PHP classes which you install beside Phabricator, and which
Phabricator loads at runtime and runs in-process. They are the most direct and
powerful way to respond to events.
= Installing Event Listeners =
To install event listeners, follow these steps:
- Write a listener class which extends @{class:PhutilEventListener}.
- Add it to a libphutil library, or create a new library (for instructions,
see @{article:libphutil Libraries User Guide}.
- Configure Phabricator to load the library by adding it to `load-libraries`
in the Phabricator config.
- Configure Phabricator to install the event listener by adding the class
name to `events.listeners` in the Phabricator config.
You can verify your listener is registered in the "Events" tab of DarkConsole.
It should appear at the top under "Registered Event Listeners". You can also
see any events the page emitted there. For details on DarkConsole, see
@{article:Using DarkConsole}.
= Example Listener =
Phabricator includes an example event listener,
@{class:PhabricatorExampleEventListener}, which may be useful as a starting
point in developing your own listeners. This listener listens for a test
event that is emitted by the script `scripts/util/emit_test_event.php`.
If you run this script normally, it should output something like this:
$ ./scripts/util/emit_test_event.php
Emitting event...
Done.
This is because there are no listeners for the event, so nothing reacts to it
when it is emitted. You can add the example listener by either adding it to
your `events.listeners` configuration or with the `--listen` command-line flag:
$ ./scripts/util/emit_test_event.php --listen PhabricatorExampleEventListener
Installing 'PhabricatorExampleEventListener'...
Emitting event...
PhabricatorExampleEventListener got test event at 1341344566
Done.
This time, the listener was installed and had its callback invoked when the
test event was emitted.
= Available Events =
You can find a list of all Phabricator events in @{class:PhabricatorEventType}.
== All Events ==
The special constant `PhutilEventType::TYPE_ALL` will let you listen for all
events. Normally, you want to listen only to specific events, but if you're
writing a generic handler you can listen to all events with this constant
rather than by enumerating each event.
== Maniphest: Will Edit Task ==
The constant for this event is
`PhabricatorEventType::TYPE_MANIPHEST_WILLEDITTASK`.
This event is dispatched before a task is edited, and allows you to respond to
or alter the edit. Data available on this event:
- ##task## The @{class:ManiphestTask} being edited.
- ##transactions## The list of edits (objects of class
@{class:ManiphestTransaction}) being applied.
- ##new## A boolean indicating if this task is being created.
- ##mail## If this edit originates from email, the
@{class:PhabricatorMetaMTAReceivedMail} object.
This is similar to the next event (did edit task) but occurs before the edit
begins.
== Maniphest: Did Edit Task ==
The constant for this event is
`PhabricatorEventType::TYPE_MANIPHEST_DIDEDITTASK`.
This event is dispatched after a task is edited, and allows you to react to the
edit. Data available on this event:
- ##task## The @{class:ManiphestTask} that was edited.
- ##transactions## The list of edits (objects of class
@{class:ManiphestTransaction}) that were applied.
- ##new## A boolean indicating if this task was newly created.
- ##mail## If this edit originates from email, the
@{class:PhabricatorMetaMTAReceivedMail} object.
This is similar to the previous event (will edit task) but occurs after the
edit completes.
== Differential: Will Send Mail ==
The constant for this event is
`PhabricatorEventType::TYPE_DIFFERENTIAL_WILLSENDMAIL`
This event is dispatched before Differential sends an email, and allows you to
edit the message that will be sent. Data available on this event:
- ##mail## The @{class:PhabricatorMetaMTAMail} being edited.
== Differential: Will Mark Generated ==
The constant for this event is
`PhabricatorEventType::TYPE_DIFFERENTIAL_WILLMARKGENERATED`.
This event is dispatched before Differential decides if a file is generated (and
doesn't need to be reviewed) or not. Data available on this event:
- ##corpus## Body of the file.
- ##is_generated## Boolean indicating if this file should be treated as
generated.
== Diffusion: Did Discover Commit ==
The constant for this event is
`PhabricatorEventType::TYPE_DIFFUSION_DIDDISCOVERCOMMIT`.
This event is dispatched when the daemons discover a commit for the first time.
This event happens very early in the pipeline, and not all commit information
will be available yet. Data available on this event:
- `commit` The @{class:PhabricatorRepositoryCommit} that was discovered.
- `repository` The @{class:PhabricatorRepository} the commit was discovered
in.
+== Diffusion: Lookup User ==
+
+The constant for this event is
+`PhabricatorEventType::TYPE_DIFFUSION_LOOKUPUSER`.
+
+This event is dispatched when the daemons are trying to link a commit to a
+Phabricator user account. You can listen for it to improve the accuracy of
+associating users with their commits.
+
+By default, Phabricator will try to find matches based on usernames, real names,
+or email addresses, but this can result in incorrect matches (e.g., if you have
+several employees with the same name) or failures to match (e.g., if someone
+changed their email address). Listening for this event allows you to intercept
+the lookup and supplement the results from another datasource.
+
+Data available on this event:
+
+ - `commit` The @{class:PhabricatorRepositoryCommit} that data is being looked
+ up for.
+ - `query` The author or committer string being looked up. This will usually
+ be something like "Abraham Lincoln <alincoln@logcabin.example.com>", but
+ comes from the commit metadata so it may not be well-formatted.
+ - `result` The current result from the lookup (Phabricator's best guess at
+ the user PHID of the user named in the "query"). To substitute the result
+ with a different result, replace this with the correct PHID in your event
+ listener.
+
+Using @{class:PhutilEmailAddress} may be helpful in parsing the query.
+
== Edge: Will Edit Edges ==
NOTE: Edge events are low-level events deep in the core. It is more difficult to
correct implement listeners for these events than for higher-level events.
The constant for this event is
`PhabricatorEventType::TYPE_EDGE_WILLEDITEDGES`.
This event is dispatched before @{class:PhabricatorEdgeEditor} makes an edge
edit.
- `id` An identifier for this edit operation.
- `add` A list of dictionaries, each representing a new edge.
- `rem` A list of dictionaries, each representing a removed edge.
This is similar to the next event (did edit edges) but occurs before the
edit begins.
== Edge: Did Edit Edges ==
The constant for this event is
`PhabricatorEventType::TYPE_EDGE_DIDEDITEDGES`.
This event is dispatched after @{class:PhabricatorEdgeEditor} makes an edge
edit, but before it commits the transactions. Data available on this event:
- `id` An identifier for this edit operation. This is the same ID as
the one included in the corresponding "will edit edges" event.
- `add` A list of dictionaries, each representing a new edge.
- `rem` A list of dictionaries, each representing a removed edge.
This is similar to the previous event (will edit edges) but occurs after the
edit completes.
== Test: Did Run Test ==
The constant for this event is
`PhabricatorEventType::TYPE_TEST_DIDRUNTEST`.
This is a test event for testing event listeners. See above for details.
= Debugging Listeners =
If you're having problems with your listener, try these steps:
- If you're getting an error about Phabricator being unable to find the
listener class, make sure you've added it to a libphutil library and
configured Phabricator to load the library with `load-libraries`.
- Make sure the listener is registered. It should appear in the "Events" tab
of DarkConsole. If it's not there, you may have forgotten to add it to
`events.listeners`.
- Make sure it calls `listen()` on the right events in its `register()`
method. If you don't listen for the events you're interested in, you
won't get a callback.
- Make sure the events you're listening for are actually happening. If they
occur on a normal page they should appear in the "Events" tab of
DarkConsole. If they occur on a POST, you could add a `phlog()`
to the source code near the event and check your error log to make sure the
code ran.
- You can check if your callback is getting invoked by adding `phlog()` with
a message and checking the error log.
- You can try listening to `PhutilEventType::TYPE_ALL` instead of a specific
event type to get all events, to narrow down whether problems are caused
by the types of events you're listening to.
- You can edit the `emit_test_event.php` script to emit other types of
events instead, to test that your listener reacts to them properly. You
might have to use fake data, but this gives you an easy way to test the
at least the basics.
- For scripts, you can run under `--trace` to see which events are emitted
and how many handlers are listening to each event.
= Next Steps =
Continue by:
- taking a look at @{class:PhabricatorExampleEventListener}; or
- building a library with @{article:libphutil Libraries User Guide}.
\ No newline at end of file
diff --git a/src/infrastructure/events/constant/PhabricatorEventType.php b/src/infrastructure/events/constant/PhabricatorEventType.php
index 0aa5132f26..8eeb1b7f76 100644
--- a/src/infrastructure/events/constant/PhabricatorEventType.php
+++ b/src/infrastructure/events/constant/PhabricatorEventType.php
@@ -1,40 +1,41 @@
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* For detailed explanations of these events, see
* @{article:Events User Guide: Installing Event Listeners}.
*
* @group events
*/
final class PhabricatorEventType extends PhutilEventType {
const TYPE_MANIPHEST_WILLEDITTASK = 'maniphest.willEditTask';
const TYPE_MANIPHEST_DIDEDITTASK = 'maniphest.didEditTask';
const TYPE_DIFFERENTIAL_WILLSENDMAIL = 'differential.willSendMail';
const TYPE_DIFFERENTIAL_WILLMARKGENERATED = 'differential.willMarkGenerated';
const TYPE_DIFFUSION_DIDDISCOVERCOMMIT = 'diffusion.didDiscoverCommit';
+ const TYPE_DIFFUSION_LOOKUPUSER = 'diffusion.lookupUser';
const TYPE_EDGE_WILLEDITEDGES = 'edge.willEditEdges';
const TYPE_EDGE_DIDEDITEDGES = 'edge.didEditEdges';
const TYPE_TEST_DIDRUNTEST = 'test.didRunTest';
}

File Metadata

Mime Type
text/x-diff
Expires
Sat, Nov 15, 5:29 PM (13 h, 26 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
338257
Default Alt Text
(28 KB)

Event Timeline