Path: blob/master/src/applications/metamta/query/PhabricatorMetaMTAMemberQuery.php
12256 views
<?php12/**3* Expands aggregate mail recipients into their component mailables. For4* example, a project currently expands into all of its members.5*/6final class PhabricatorMetaMTAMemberQuery extends PhabricatorQuery {78private $phids = array();9private $viewer;1011public function setViewer(PhabricatorUser $viewer) {12$this->viewer = $viewer;13return $this;14}1516public function getViewer() {17return $this->viewer;18}1920public function withPHIDs(array $phids) {21$this->phids = $phids;22return $this;23}2425public function execute() {26$viewer = $this->getViewer();2728$phids = array_fuse($this->phids);29$actors = array();30$type_map = array();31foreach ($phids as $phid) {32$type_map[phid_get_type($phid)][] = $phid;33}3435// TODO: Generalize this somewhere else.363738// If we have packages, break them down into their constituent user and39// project owners first. Then we'll resolve those and build the packages40// back up from the pieces.41$package_type = PhabricatorOwnersPackagePHIDType::TYPECONST;42$package_phids = idx($type_map, $package_type, array());43unset($type_map[$package_type]);4445$package_map = array();46if ($package_phids) {47$packages = id(new PhabricatorOwnersPackageQuery())48->setViewer($viewer)49->withPHIDs($package_phids)50->execute();5152foreach ($packages as $package) {53$package_owners = array();54foreach ($package->getOwners() as $owner) {55$owner_phid = $owner->getUserPHID();56$owner_type = phid_get_type($owner_phid);57$type_map[$owner_type][] = $owner_phid;58$package_owners[] = $owner_phid;59}60$package_map[$package->getPHID()] = $package_owners;61}6263// See T13648. We may have packages that no longer exist or can't be64// loaded (for example, because they have been destroyed). Give them65// empty entries in the map so we return a mapping for all input PHIDs.6667foreach ($package_phids as $package_phid) {68if (!isset($package_map[$package_phid])) {69$package_map[$package_phid] = array();70}71}72}7374$results = array();75foreach ($type_map as $type => $phids) {76switch ($type) {77case PhabricatorProjectProjectPHIDType::TYPECONST:78// NOTE: We're loading the projects here in order to respect policies.7980$projects = id(new PhabricatorProjectQuery())81->setViewer($viewer)82->withPHIDs($phids)83->needMembers(true)84->needWatchers(true)85->execute();8687$edge_type = PhabricatorProjectSilencedEdgeType::EDGECONST;8889$edge_query = id(new PhabricatorEdgeQuery())90->withSourcePHIDs($phids)91->withEdgeTypes(92array(93$edge_type,94));9596$edge_query->execute();9798$projects = mpull($projects, null, 'getPHID');99foreach ($phids as $phid) {100$project = idx($projects, $phid);101102if (!$project) {103$results[$phid] = array();104continue;105}106107// Recipients are members who haven't silenced the project, plus108// watchers.109110$members = $project->getMemberPHIDs();111$members = array_fuse($members);112113$watchers = $project->getWatcherPHIDs();114$watchers = array_fuse($watchers);115116$silenced = $edge_query->getDestinationPHIDs(117array($phid),118array($edge_type));119$silenced = array_fuse($silenced);120121$result_map = array_diff_key($members, $silenced);122$result_map = $result_map + $watchers;123124$results[$phid] = array_values($result_map);125}126break;127default:128// For other types, just map the PHID to itself without modification.129// This allows callers to do less work.130foreach ($phids as $phid) {131$results[$phid] = array($phid);132}133break;134}135}136137// For any packages, stitch them back together from the resolved users138// and projects.139if ($package_map) {140foreach ($package_map as $package_phid => $owner_phids) {141$resolved = array();142foreach ($owner_phids as $owner_phid) {143$resolved_phids = idx($results, $owner_phid, array());144foreach ($resolved_phids as $resolved_phid) {145$resolved[] = $resolved_phid;146}147}148$results[$package_phid] = $resolved;149}150}151152return $results;153}154155156/**157* Execute the query, merging results into a single list of unique member158* PHIDs.159*/160public function executeExpansion() {161return array_unique(array_mergev($this->execute()));162}163164}165166167