Path: blob/master/src/applications/diffusion/xaction/DiffusionCommitAuditorsTransaction.php
12241 views
<?php12final class DiffusionCommitAuditorsTransaction3extends DiffusionCommitTransactionType {45const TRANSACTIONTYPE = 'diffusion.commit.auditors';67public function generateOldValue($object) {8$auditors = $object->getAudits();9return mpull($auditors, 'getAuditStatus', 'getAuditorPHID');10}1112public function generateNewValue($object, $value) {13$actor = $this->getActor();1415$auditors = $this->generateOldValue($object);16$old_auditors = $auditors;1718$request_status = PhabricatorAuditRequestStatus::AUDIT_REQUESTED;1920$rem = idx($value, '-', array());21foreach ($rem as $phid) {22unset($auditors[$phid]);23}2425$add = idx($value, '+', array());26$add_map = array();27foreach ($add as $phid) {28$add_map[$phid] = $request_status;29}3031$set = idx($value, '=', null);32if ($set !== null) {33foreach ($set as $phid) {34$add_map[$phid] = $request_status;35}3637$auditors = array();38}3940foreach ($add_map as $phid => $new_status) {41$old_status = idx($old_auditors, $phid);4243if ($old_status) {44$auditors[$phid] = $old_status;45continue;46}4748$auditors[$phid] = $new_status;49}5051return $auditors;52}5354public function getTransactionHasEffect($object, $old, $new) {55ksort($old);56ksort($new);57return ($old !== $new);58}5960public function mergeTransactions(61$object,62PhabricatorApplicationTransaction $u,63PhabricatorApplicationTransaction $v) {6465$u_new = $u->getNewValue();66$v_new = $v->getNewValue();6768$result = $v_new;69foreach (array('-', '+') as $key) {70$u_value = idx($u_new, $key, array());71$v_value = idx($v_new, $key, array());7273$merged = $u_value + $v_value;7475if ($merged) {76$result[$key] = $merged;77}78}7980$u->setNewValue($result);8182return $u;83}8485public function applyExternalEffects($object, $value) {86$src_phid = $object->getPHID();8788$old = $this->generateOldValue($object);89$new = $value;9091$auditors = $object->getAudits();92$auditors = mpull($auditors, null, 'getAuditorPHID');9394$rem = array_diff_key($old, $new);95foreach ($rem as $phid => $status) {96$auditor = idx($auditors, $phid);97if ($auditor) {98$auditor->delete();99}100}101102$this->updateAudits($object, $new);103}104105public function getTitle() {106$old = $this->getOldValue();107$new = $this->getNewValue();108109$rem = array_diff_key($old, $new);110$add = array_diff_key($new, $old);111$rem_phids = array_keys($rem);112$add_phids = array_keys($add);113$total_count = count($rem) + count($add);114115if ($rem && $add) {116return pht(117'%s edited %s auditor(s), removed %s: %s; added %s: %s.',118$this->renderAuthor(),119new PhutilNumber($total_count),120phutil_count($rem_phids),121$this->renderHandleList($rem_phids),122phutil_count($add_phids),123$this->renderHandleList($add_phids));124} else if ($add) {125return pht(126'%s added %s auditor(s): %s.',127$this->renderAuthor(),128phutil_count($add_phids),129$this->renderHandleList($add_phids));130} else {131return pht(132'%s removed %s auditor(s): %s.',133$this->renderAuthor(),134phutil_count($rem_phids),135$this->renderHandleList($rem_phids));136}137}138139public function getTitleForFeed() {140$old = $this->getOldValue();141$new = $this->getNewValue();142143$rem = array_diff_key($old, $new);144$add = array_diff_key($new, $old);145$rem_phids = array_keys($rem);146$add_phids = array_keys($add);147$total_count = count($rem) + count($add);148149if ($rem && $add) {150return pht(151'%s edited %s auditor(s) for %s, removed %s: %s; added %s: %s.',152$this->renderAuthor(),153new PhutilNumber($total_count),154$this->renderObject(),155phutil_count($rem_phids),156$this->renderHandleList($rem_phids),157phutil_count($add_phids),158$this->renderHandleList($add_phids));159} else if ($add) {160return pht(161'%s added %s auditor(s) for %s: %s.',162$this->renderAuthor(),163phutil_count($add_phids),164$this->renderObject(),165$this->renderHandleList($add_phids));166} else {167return pht(168'%s removed %s auditor(s) for %s: %s.',169$this->renderAuthor(),170phutil_count($rem_phids),171$this->renderObject(),172$this->renderHandleList($rem_phids));173}174}175176public function validateTransactions($object, array $xactions) {177$actor = $this->getActor();178$errors = array();179180if (!$xactions) {181return $errors;182}183184$author_phid = $object->getEffectiveAuthorPHID();185$can_author_close_key = 'audit.can-author-close-audit';186$can_author_close = PhabricatorEnv::getEnvConfig($can_author_close_key);187188$old = $this->generateOldValue($object);189foreach ($xactions as $xaction) {190$new = $this->generateNewValue($object, $xaction->getNewValue());191192$add = array_diff_key($new, $old);193if (!$add) {194continue;195}196197$objects = id(new PhabricatorObjectQuery())198->setViewer($actor)199->withPHIDs(array_keys($add))200->execute();201$objects = mpull($objects, null, 'getPHID');202203foreach ($add as $phid => $status) {204if (!isset($objects[$phid])) {205$errors[] = $this->newInvalidError(206pht(207'Auditor "%s" is not a valid object.',208$phid),209$xaction);210continue;211}212213switch (phid_get_type($phid)) {214case PhabricatorPeopleUserPHIDType::TYPECONST:215case PhabricatorOwnersPackagePHIDType::TYPECONST:216case PhabricatorProjectProjectPHIDType::TYPECONST:217break;218default:219$errors[] = $this->newInvalidError(220pht(221'Auditor "%s" must be a user, a package, or a project.',222$phid),223$xaction);224continue 2;225}226227$is_self = ($phid === $author_phid);228if ($is_self && !$can_author_close) {229$errors[] = $this->newInvalidError(230pht('The author of a commit can not be an auditor.'),231$xaction);232continue;233}234}235}236237return $errors;238}239240}241242243