protected function applyCustomExternalTransaction(PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case AlmanacDeviceTransaction::TYPE_NAME: return; case AlmanacDeviceTransaction::TYPE_INTERFACE: $old = $xaction->getOldValue(); if ($old) { $interface = id(new AlmanacInterfaceQuery())->setViewer($this->requireActor())->withIDs(array($old['id']))->executeOne(); if (!$interface) { throw new Exception(pht('Unable to load interface!')); } } else { $interface = AlmanacInterface::initializeNewInterface()->setDevicePHID($object->getPHID()); } $new = $xaction->getNewValue(); if ($new) { $interface->setNetworkPHID($new['networkPHID'])->setAddress($new['address'])->setPort((int) $new['port']); if (idx($new, 'phid')) { $interface->setPHID($new['phid']); } $interface->save(); } else { $interface->delete(); } return; } return parent::applyCustomExternalTransaction($object, $xaction); }
public function computeRawFactsForObject(PhabricatorLiskDAO $object) { $facts = array(); $phid = $object->getPHID(); $type = phid_get_type($phid); foreach (array('N:*', 'N:' . $type) as $fact_type) { $facts[] = id(new PhabricatorFactRaw())->setFactType($fact_type)->setObjectPHID($phid)->setValueX(1)->setEpoch($object->getDateCreated()); } return $facts; }
protected function applyCustomExternalTransaction(PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case AlmanacServiceTransaction::TYPE_NAME: return; case AlmanacServiceTransaction::TYPE_LOCK: $service = id(new AlmanacServiceQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withPHIDs(array($object->getPHID()))->needBindings(true)->executeOne(); $devices = array(); foreach ($service->getBindings() as $binding) { $device = $binding->getInterface()->getDevice(); $devices[$device->getPHID()] = $device; } foreach ($devices as $device) { $device->rebuildDeviceLocks(); } return; } return parent::applyCustomExternalTransaction($object, $xaction); }
protected function applyCustomExternalTransaction(PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case AlmanacTransaction::TYPE_PROPERTY_UPDATE: $property_key = $xaction->getMetadataValue('almanac.property'); if ($object->hasAlmanacProperty($property_key)) { $property = $object->getAlmanacProperty($property_key); } else { $property = id(new AlmanacProperty())->setObjectPHID($object->getPHID())->setFieldName($property_key); } $property->setFieldValue($xaction->getNewValue())->save(); return; case AlmanacTransaction::TYPE_PROPERTY_REMOVE: $property_key = $xaction->getMetadataValue('almanac.property'); if ($object->hasAlmanacProperty($property_key)) { $property = $object->getAlmanacProperty($property_key); $property->delete(); } return; } return parent::applyCustomExternalTransaction($object, $xaction); }
protected function applyCustomExternalTransaction(PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case PhabricatorRepositoryTransaction::TYPE_AUTOMATION_BLUEPRINTS: DrydockAuthorization::applyAuthorizationChanges($this->getActor(), $object->getPHID(), $xaction->getOldValue(), $xaction->getNewValue()); break; } }
protected function getMailThreadID(PhabricatorLiskDAO $object) { return 'maniphest-task-' . $object->getPHID(); }
protected function buildHeraldAdapter(PhabricatorLiskDAO $object, array $xactions) { $revision = id(new DifferentialRevisionQuery())->setViewer($this->getActor())->withPHIDs(array($object->getPHID()))->needActiveDiffs(true)->needReviewerStatus(true)->executeOne(); if (!$revision) { throw new Exception(pht('Failed to load revision for Herald adapter construction!')); } $adapter = HeraldDifferentialRevisionAdapter::newLegacyAdapter($revision, $revision->getActiveDiff()); $reviewers = $revision->getReviewerStatus(); $reviewer_phids = mpull($reviewers, 'getReviewerPHID'); $adapter->setExplicitReviewers($reviewer_phids); return $adapter; }
protected function getMailThreadID(PhabricatorLiskDAO $object) { // For backward compatibility, use this legacy thread ID. return 'diffusion-audit-' . $object->getPHID(); }
protected function buildMailTemplate(PhabricatorLiskDAO $object) { $phid = $object->getPHID(); $name = $object->getName(); return id(new PhabricatorMetaMTAMail())->setSubject($name)->addHeader('Thread-Topic', $phid); }
protected function buildMailTemplate(PhabricatorLiskDAO $object) { $id = $object->getID(); $phid = $object->getPHID(); $title = $object->getSummaryForDisplay(); return id(new PhabricatorMetaMTAMail())->setSubject("RQ{$id}: {$title}")->addHeader('Thread-Topic', "RQ{$id}: {$phid}"); }
private function addSlug(PhabricatorLiskDAO $object, $name) { $slug = PhabricatorSlug::normalizeProjectSlug($name); $slug_object = id(new PhabricatorProjectSlug())->loadOneWhere('slug = %s', $slug); if ($slug_object) { return; } $new_slug = id(new PhabricatorProjectSlug())->setSlug($slug)->setProjectPHID($object->getPHID())->save(); }
protected function getMailTo(PhabricatorLiskDAO $object) { $phids = array(); // Reload the cart to pull merchant and account information, in case we // just created the object. $cart = id(new PhortuneCartQuery())->setViewer($this->requireActor())->withPHIDs(array($object->getPHID()))->executeOne(); foreach ($cart->getAccount()->getMemberPHIDs() as $account_member) { $phids[] = $account_member; } foreach ($cart->getMerchant()->getMemberPHIDs() as $merchant_member) { $phids[] = $merchant_member; } return $phids; }
protected function applyCustomExternalTransaction(PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case PhabricatorCalendarEventTransaction::TYPE_RECURRING: case PhabricatorCalendarEventTransaction::TYPE_FREQUENCY: case PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE: case PhabricatorCalendarEventTransaction::TYPE_INSTANCE_OF_EVENT: case PhabricatorCalendarEventTransaction::TYPE_SEQUENCE_INDEX: case PhabricatorCalendarEventTransaction::TYPE_NAME: case PhabricatorCalendarEventTransaction::TYPE_START_DATE: case PhabricatorCalendarEventTransaction::TYPE_END_DATE: case PhabricatorCalendarEventTransaction::TYPE_DESCRIPTION: case PhabricatorCalendarEventTransaction::TYPE_CANCEL: case PhabricatorCalendarEventTransaction::TYPE_ALL_DAY: case PhabricatorCalendarEventTransaction::TYPE_ICON: return; case PhabricatorCalendarEventTransaction::TYPE_INVITE: $map = $xaction->getNewValue(); $phids = array_keys($map); $invitees = $object->getInvitees(); $invitees = mpull($invitees, null, 'getInviteePHID'); foreach ($phids as $phid) { $invitee = idx($invitees, $phid); if (!$invitee) { $invitee = id(new PhabricatorCalendarEventInvitee())->setEventPHID($object->getPHID())->setInviteePHID($phid)->setInviterPHID($this->getActingAsPHID()); $invitees[] = $invitee; } $invitee->setStatus($map[$phid])->save(); } $object->attachInvitees($invitees); return; } return parent::applyCustomExternalTransaction($object, $xaction); }
protected function buildMailTemplate(PhabricatorLiskDAO $object) { $id = $object->getID(); $title = $object->getContent()->getTitle(); return id(new PhabricatorMetaMTAMail())->setSubject($title)->addHeader('Thread-Topic', $object->getPHID()); }
protected function didApplyHeraldRules(PhabricatorLiskDAO $object, HeraldAdapter $adapter, HeraldTranscript $transcript) { $xactions = array(); $audit_phids = $adapter->getAuditMap(); foreach ($audit_phids as $phid => $rule_ids) { foreach ($rule_ids as $rule_id) { $this->addAuditReason($phid, pht('%s Triggered Audit', "H{$rule_id}")); } } if ($audit_phids) { $xactions[] = id(new PhabricatorAuditTransaction())->setTransactionType(PhabricatorAuditActionConstants::ADD_AUDITORS)->setNewValue(array_fuse(array_keys($audit_phids)))->setMetadataValue('auditStatus', PhabricatorAuditStatusConstants::AUDIT_REQUIRED)->setMetadataValue('auditReasonMap', $this->auditReasonMap); } HarbormasterBuildable::applyBuildPlans($object->getPHID(), $object->getRepository()->getPHID(), $adapter->getBuildPlans()); $limit = self::MAX_FILES_SHOWN_IN_EMAIL; $files = $adapter->loadAffectedPaths(); sort($files); if (count($files) > $limit) { array_splice($files, $limit); $files[] = pht('(This commit affected more than %d files. Only %d are shown here ' . 'and additional ones are truncated.)', $limit, $limit); } $this->affectedFiles = implode("\n", $files); return $xactions; }
protected function buildMailTemplate(PhabricatorLiskDAO $object) { $id = $object->getID(); $phid = $object->getPHID(); $title = $object->getDocumentBody()->getTitle(); return id(new PhabricatorMetaMTAMail())->setSubject("L{$id}: {$title}")->addHeader('Thread-Topic', "L{$id}: {$phid}"); }
private function buildMoveTransaction(PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { $new = $xaction->getNewValue(); if (!is_array($new)) { $this->validateColumnPHID($new); $new = array($new); } $nearby_phids = array(); foreach ($new as $key => $value) { if (!is_array($value)) { $this->validateColumnPHID($value); $value = array('columnPHID' => $value); } PhutilTypeSpec::checkMap($value, array('columnPHID' => 'string', 'beforePHID' => 'optional string', 'afterPHID' => 'optional string')); $new[$key] = $value; if (!empty($value['beforePHID'])) { $nearby_phids[] = $value['beforePHID']; } if (!empty($value['afterPHID'])) { $nearby_phids[] = $value['afterPHID']; } } if ($nearby_phids) { $nearby_objects = id(new PhabricatorObjectQuery())->setViewer($this->getActor())->withPHIDs($nearby_phids)->execute(); $nearby_objects = mpull($nearby_objects, null, 'getPHID'); } else { $nearby_objects = array(); } $column_phids = ipull($new, 'columnPHID'); if ($column_phids) { $columns = id(new PhabricatorProjectColumnQuery())->setViewer($this->getActor())->withPHIDs($column_phids)->execute(); $columns = mpull($columns, null, 'getPHID'); } else { $columns = array(); } $board_phids = mpull($columns, 'getProjectPHID'); $object_phid = $object->getPHID(); $object_phids = $nearby_phids; // Note that we may not have an object PHID if we're creating a new // object. if ($object_phid) { $object_phids[] = $object_phid; } if ($object_phids) { $layout_engine = id(new PhabricatorBoardLayoutEngine())->setViewer($this->getActor())->setBoardPHIDs($board_phids)->setObjectPHIDs($object_phids)->setFetchAllBoards(true)->executeLayout(); } foreach ($new as $key => $spec) { $column_phid = $spec['columnPHID']; $column = idx($columns, $column_phid); if (!$column) { throw new Exception(pht('Column move transaction specifies column PHID "%s", but there ' . 'is no corresponding column with this PHID.', $column_phid)); } $board_phid = $column->getProjectPHID(); $nearby = array(); if (!empty($spec['beforePHID'])) { $nearby['beforePHID'] = $spec['beforePHID']; } if (!empty($spec['afterPHID'])) { $nearby['afterPHID'] = $spec['afterPHID']; } if (count($nearby) > 1) { throw new Exception(pht('Column move transaction moves object to multiple positions. ' . 'Specify only "beforePHID" or "afterPHID", not both.')); } foreach ($nearby as $where => $nearby_phid) { if (empty($nearby_objects[$nearby_phid])) { throw new Exception(pht('Column move transaction specifies object "%s" as "%s", but ' . 'there is no corresponding object with this PHID.', $object_phid, $where)); } $nearby_columns = $layout_engine->getObjectColumns($board_phid, $nearby_phid); $nearby_columns = mpull($nearby_columns, null, 'getPHID'); if (empty($nearby_columns[$column_phid])) { throw new Exception(pht('Column move transaction specifies object "%s" as "%s" in ' . 'column "%s", but this object is not in that column!', $nearby_phid, $where, $column_phid)); } } if ($object_phid) { $old_columns = $layout_engine->getObjectColumns($board_phid, $object_phid); $old_column_phids = mpull($old_columns, 'getPHID'); } else { $old_column_phids = array(); } $spec += array('boardPHID' => $board_phid, 'fromColumnPHIDs' => $old_column_phids); // Check if the object is already in this column, and isn't being moved. // We can just drop this column change if it has no effect. $from_map = array_fuse($spec['fromColumnPHIDs']); $already_here = isset($from_map[$column_phid]); $is_reordering = (bool) $nearby; if ($already_here && !$is_reordering) { unset($new[$key]); } else { $new[$key] = $spec; } } $new = array_values($new); $xaction->setNewValue($new); $more = array(); // If we're moving the object into a column and it does not already belong // in the column, add the appropriate board. For normal columns, this // is the board PHID. For proxy columns, it is the proxy PHID, unless the // object is already a member of some descendant of the proxy PHID. // The major case where this can happen is moves via the API, but it also // happens when a user drags a task from the "Backlog" to a milestone // column. if ($object_phid) { $current_phids = PhabricatorEdgeQuery::loadDestinationPHIDs($object_phid, PhabricatorProjectObjectHasProjectEdgeType::EDGECONST); $current_phids = array_fuse($current_phids); } else { $current_phids = array(); } $add_boards = array(); foreach ($new as $move) { $column_phid = $move['columnPHID']; $board_phid = $move['boardPHID']; $column = $columns[$column_phid]; $proxy_phid = $column->getProxyPHID(); // If this is a normal column, add the board if the object isn't already // associated. if (!$proxy_phid) { if (!isset($current_phids[$board_phid])) { $add_boards[] = $board_phid; } continue; } // If this is a proxy column but the object is already associated with // the proxy board, we don't need to do anything. if (isset($current_phids[$proxy_phid])) { continue; } // If this a proxy column and the object is already associated with some // descendant of the proxy board, we also don't need to do anything. $descendants = id(new PhabricatorProjectQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withAncestorProjectPHIDs(array($proxy_phid))->execute(); $found_descendant = false; foreach ($descendants as $descendant) { if (isset($current_phids[$descendant->getPHID()])) { $found_descendant = true; break; } } if ($found_descendant) { continue; } // Otherwise, we're moving the object to a proxy column which it is not // a member of yet, so add an association to the column's proxy board. $add_boards[] = $proxy_phid; } if ($add_boards) { $more[] = id(new ManiphestTransaction())->setTransactionType(PhabricatorTransactions::TYPE_EDGE)->setMetadataValue('edge:type', PhabricatorProjectObjectHasProjectEdgeType::EDGECONST)->setIgnoreOnNoEffect(true)->setNewValue(array('+' => array_fuse($add_boards))); } return $more; }
protected function buildHeraldAdapter(PhabricatorLiskDAO $object, array $xactions) { // Herald rules may run on behalf of other users and need to execute // membership checks against ancestors. $project = id(new PhabricatorProjectQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withPHIDs(array($object->getPHID()))->needAncestorMembers(true)->executeOne(); return id(new PhabricatorProjectHeraldAdapter())->setProject($project); }
protected function buildMailTemplate(PhabricatorLiskDAO $object) { $id = $object->getID(); $title = $object->getTitle(); if (!$title) { $title = pht('%s sent you a message.', $this->getActor()->getUserName()); } $phid = $object->getPHID(); return id(new PhabricatorMetaMTAMail())->setSubject("Z{$id}: {$title}")->addHeader('Thread-Topic', "Z{$id}: {$phid}"); }
protected function buildMailTemplate(PhabricatorLiskDAO $object) { $id = $object->getID(); $name = $object->getName(); $phid = $object->getPHID(); $mail = id(new PhabricatorMetaMTAMail())->setSubject(pht('SSH Key %d: %s', $id, $name))->addHeader('Thread-Topic', $phid); // The primary value of this mail is alerting users to account compromises, // so force delivery. In particular, this mail should still be delievered // even if "self mail" is disabled. $mail->setForceDelivery(true); return $mail; }
protected function buildHeraldAdapter(PhabricatorLiskDAO $object, array $xactions) { $unsubscribed_phids = PhabricatorEdgeQuery::loadDestinationPHIDs($object->getPHID(), PhabricatorEdgeConfig::TYPE_OBJECT_HAS_UNSUBSCRIBER); $subscribed_phids = PhabricatorSubscribersQuery::loadSubscribersForPHID($object->getPHID()); $revision = id(new DifferentialRevisionQuery())->setViewer($this->getActor())->withPHIDs(array($object->getPHID()))->needActiveDiffs(true)->needReviewerStatus(true)->executeOne(); if (!$revision) { throw new Exception(pht('Failed to load revision for Herald adapter construction!')); } $adapter = HeraldDifferentialRevisionAdapter::newLegacyAdapter($revision, $revision->getActiveDiff()); $reviewers = $revision->getReviewerStatus(); $reviewer_phids = mpull($reviewers, 'getReviewerPHID'); $adapter->setExplicitCCs($subscribed_phids); $adapter->setExplicitReviewers($reviewer_phids); $adapter->setForbiddenCCs($unsubscribed_phids); $adapter->setIsNewObject($this->getIsNewObject()); return $adapter; }
protected function applyCustomExternalTransaction(PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case PhabricatorRepositoryTransaction::TYPE_CREDENTIAL: // Adjust the object <-> credential edge for this repository. $old_phid = $xaction->getOldValue(); $new_phid = $xaction->getNewValue(); $editor = new PhabricatorEdgeEditor(); $edge_type = PhabricatorEdgeConfig::TYPE_OBJECT_USES_CREDENTIAL; $src_phid = $object->getPHID(); if ($old_phid) { $editor->removeEdge($src_phid, $edge_type, $old_phid); } if ($new_phid) { $editor->addEdge($src_phid, $edge_type, $new_phid); } $editor->save(); break; } }
protected function applyFinalEffects(PhabricatorLiskDAO $object, array $xactions) { $materialize = false; $new_parent = null; foreach ($xactions as $xaction) { switch ($xaction->getTransactionType()) { case PhabricatorTransactions::TYPE_EDGE: switch ($xaction->getMetadataValue('edge:type')) { case PhabricatorProjectProjectHasMemberEdgeType::EDGECONST: $materialize = true; break; } break; case PhabricatorProjectTransaction::TYPE_PARENT: $materialize = true; $new_parent = $object->getParentProject(); break; } } if ($new_parent) { // If we just created the first subproject of this parent, we want to // copy all of the real members to the subproject. if (!$new_parent->getHasSubprojects()) { $member_type = PhabricatorProjectProjectHasMemberEdgeType::EDGECONST; $project_members = PhabricatorEdgeQuery::loadDestinationPHIDs($new_parent->getPHID(), $member_type); if ($project_members) { $editor = id(new PhabricatorEdgeEditor()); foreach ($project_members as $phid) { $editor->addEdge($object->getPHID(), $member_type, $phid); } $editor->save(); } } } if ($this->getIsNewObject()) { $this->setDefaultProfilePicture($object); } // TODO: We should dump an informational transaction onto the parent // project to show that we created the sub-thing. if ($materialize) { id(new PhabricatorProjectsMembershipIndexEngineExtension())->rematerialize($object); } return parent::applyFinalEffects($object, $xactions); }
protected function applyCustomExternalTransaction(PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case PhabricatorRepositoryTransaction::TYPE_CREDENTIAL: // Adjust the object <-> credential edge for this repository. $old_phid = $xaction->getOldValue(); $new_phid = $xaction->getNewValue(); $editor = new PhabricatorEdgeEditor(); $edge_type = PhabricatorObjectUsesCredentialsEdgeType::EDGECONST; $src_phid = $object->getPHID(); if ($old_phid) { $editor->removeEdge($src_phid, $edge_type, $old_phid); } if ($new_phid) { $editor->addEdge($src_phid, $edge_type, $new_phid); } $editor->save(); break; case PhabricatorRepositoryTransaction::TYPE_AUTOMATION_BLUEPRINTS: DrydockAuthorization::applyAuthorizationChanges($this->getActor(), $object->getPHID(), $xaction->getOldValue(), $xaction->getNewValue()); break; } }
protected function getMailTo(PhabricatorLiskDAO $object) { $phids = array(); if ($object->getPHID()) { $phids[] = $object->getPHID(); } $phids[] = $this->getActingAsPHID(); $phids = array_unique($phids); return $phids; }
protected function applyCustomExternalTransaction(PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case PhabricatorMacroTransaction::TYPE_FILE: case PhabricatorMacroTransaction::TYPE_AUDIO: // When changing a macro's image or audio, attach the underlying files // to the macro (and detach the old files). $old = $xaction->getOldValue(); $new = $xaction->getNewValue(); $all = array(); if ($old) { $all[] = $old; } if ($new) { $all[] = $new; } $files = id(new PhabricatorFileQuery())->setViewer($this->requireActor())->withPHIDs($all)->execute(); $files = mpull($files, null, 'getPHID'); $old_file = idx($files, $old); if ($old_file) { $old_file->detachFromObject($object->getPHID()); } $new_file = idx($files, $new); if ($new_file) { $new_file->attachToObject($object->getPHID()); } break; } }
private function applyInverseEdgeTransactions(PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction, $inverse_type) { $old = $xaction->getOldValue(); $new = $xaction->getNewValue(); $add = array_keys(array_diff_key($new, $old)); $rem = array_keys(array_diff_key($old, $new)); $add = array_fuse($add); $rem = array_fuse($rem); $all = $add + $rem; $nodes = id(new PhabricatorObjectQuery())->setViewer($this->requireActor())->withPHIDs($all)->execute(); foreach ($nodes as $node) { if (!$node instanceof PhabricatorApplicationTransactionInterface) { continue; } $editor = $node->getApplicationTransactionEditor(); $template = $node->getApplicationTransactionTemplate(); $target = $node->getApplicationTransactionObject(); if (isset($add[$node->getPHID()])) { $edge_edit_type = '+'; } else { $edge_edit_type = '-'; } $template->setTransactionType($xaction->getTransactionType())->setMetadataValue('edge:type', $inverse_type)->setNewValue(array($edge_edit_type => array($object->getPHID() => $object->getPHID()))); $editor->setContinueOnNoEffect(true)->setContinueOnMissingFields(true)->setParentMessageID($this->getParentMessageID())->setIsInverseEdgeEditor(true)->setActor($this->requireActor())->setActingAsPHID($this->getActingAsPHID())->setContentSource($this->getContentSource()); $editor->applyTransactions($target, array($template)); } }
protected function willPublish(PhabricatorLiskDAO $object, array $xactions) { $member_phids = PhabricatorEdgeQuery::loadDestinationPHIDs($object->getPHID(), PhabricatorProjectProjectHasMemberEdgeType::EDGECONST); $object->attachMemberPHIDs($member_phids); return $object; }