Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/metamta/query/PhabricatorMetaMTAMemberQuery.php
12256 views
1
<?php
2
3
/**
4
* Expands aggregate mail recipients into their component mailables. For
5
* example, a project currently expands into all of its members.
6
*/
7
final class PhabricatorMetaMTAMemberQuery extends PhabricatorQuery {
8
9
private $phids = array();
10
private $viewer;
11
12
public function setViewer(PhabricatorUser $viewer) {
13
$this->viewer = $viewer;
14
return $this;
15
}
16
17
public function getViewer() {
18
return $this->viewer;
19
}
20
21
public function withPHIDs(array $phids) {
22
$this->phids = $phids;
23
return $this;
24
}
25
26
public function execute() {
27
$viewer = $this->getViewer();
28
29
$phids = array_fuse($this->phids);
30
$actors = array();
31
$type_map = array();
32
foreach ($phids as $phid) {
33
$type_map[phid_get_type($phid)][] = $phid;
34
}
35
36
// TODO: Generalize this somewhere else.
37
38
39
// If we have packages, break them down into their constituent user and
40
// project owners first. Then we'll resolve those and build the packages
41
// back up from the pieces.
42
$package_type = PhabricatorOwnersPackagePHIDType::TYPECONST;
43
$package_phids = idx($type_map, $package_type, array());
44
unset($type_map[$package_type]);
45
46
$package_map = array();
47
if ($package_phids) {
48
$packages = id(new PhabricatorOwnersPackageQuery())
49
->setViewer($viewer)
50
->withPHIDs($package_phids)
51
->execute();
52
53
foreach ($packages as $package) {
54
$package_owners = array();
55
foreach ($package->getOwners() as $owner) {
56
$owner_phid = $owner->getUserPHID();
57
$owner_type = phid_get_type($owner_phid);
58
$type_map[$owner_type][] = $owner_phid;
59
$package_owners[] = $owner_phid;
60
}
61
$package_map[$package->getPHID()] = $package_owners;
62
}
63
64
// See T13648. We may have packages that no longer exist or can't be
65
// loaded (for example, because they have been destroyed). Give them
66
// empty entries in the map so we return a mapping for all input PHIDs.
67
68
foreach ($package_phids as $package_phid) {
69
if (!isset($package_map[$package_phid])) {
70
$package_map[$package_phid] = array();
71
}
72
}
73
}
74
75
$results = array();
76
foreach ($type_map as $type => $phids) {
77
switch ($type) {
78
case PhabricatorProjectProjectPHIDType::TYPECONST:
79
// NOTE: We're loading the projects here in order to respect policies.
80
81
$projects = id(new PhabricatorProjectQuery())
82
->setViewer($viewer)
83
->withPHIDs($phids)
84
->needMembers(true)
85
->needWatchers(true)
86
->execute();
87
88
$edge_type = PhabricatorProjectSilencedEdgeType::EDGECONST;
89
90
$edge_query = id(new PhabricatorEdgeQuery())
91
->withSourcePHIDs($phids)
92
->withEdgeTypes(
93
array(
94
$edge_type,
95
));
96
97
$edge_query->execute();
98
99
$projects = mpull($projects, null, 'getPHID');
100
foreach ($phids as $phid) {
101
$project = idx($projects, $phid);
102
103
if (!$project) {
104
$results[$phid] = array();
105
continue;
106
}
107
108
// Recipients are members who haven't silenced the project, plus
109
// watchers.
110
111
$members = $project->getMemberPHIDs();
112
$members = array_fuse($members);
113
114
$watchers = $project->getWatcherPHIDs();
115
$watchers = array_fuse($watchers);
116
117
$silenced = $edge_query->getDestinationPHIDs(
118
array($phid),
119
array($edge_type));
120
$silenced = array_fuse($silenced);
121
122
$result_map = array_diff_key($members, $silenced);
123
$result_map = $result_map + $watchers;
124
125
$results[$phid] = array_values($result_map);
126
}
127
break;
128
default:
129
// For other types, just map the PHID to itself without modification.
130
// This allows callers to do less work.
131
foreach ($phids as $phid) {
132
$results[$phid] = array($phid);
133
}
134
break;
135
}
136
}
137
138
// For any packages, stitch them back together from the resolved users
139
// and projects.
140
if ($package_map) {
141
foreach ($package_map as $package_phid => $owner_phids) {
142
$resolved = array();
143
foreach ($owner_phids as $owner_phid) {
144
$resolved_phids = idx($results, $owner_phid, array());
145
foreach ($resolved_phids as $resolved_phid) {
146
$resolved[] = $resolved_phid;
147
}
148
}
149
$results[$package_phid] = $resolved;
150
}
151
}
152
153
return $results;
154
}
155
156
157
/**
158
* Execute the query, merging results into a single list of unique member
159
* PHIDs.
160
*/
161
public function executeExpansion() {
162
return array_unique(array_mergev($this->execute()));
163
}
164
165
}
166
167