protected function applyFinalEffects(PhabricatorLiskDAO $object, array $xactions) { // Load auditors explicitly; we may not have them if the caller was a // generic piece of infrastructure. $commit = id(new DiffusionCommitQuery())->setViewer($this->requireActor())->withIDs(array($object->getID()))->needAuditRequests(true)->executeOne(); if (!$commit) { throw new Exception(pht('Failed to load commit during transaction finalization!')); } $object->attachAudits($commit->getAudits()); $status_concerned = PhabricatorAuditStatusConstants::CONCERNED; $status_closed = PhabricatorAuditStatusConstants::CLOSED; $status_resigned = PhabricatorAuditStatusConstants::RESIGNED; $status_accepted = PhabricatorAuditStatusConstants::ACCEPTED; $status_concerned = PhabricatorAuditStatusConstants::CONCERNED; $actor_phid = $this->getActingAsPHID(); $actor_is_author = $object->getAuthorPHID() && $actor_phid == $object->getAuthorPHID(); foreach ($xactions as $xaction) { switch ($xaction->getTransactionType()) { case PhabricatorAuditActionConstants::ACTION: $new = $xaction->getNewValue(); switch ($new) { case PhabricatorAuditActionConstants::CLOSE: // "Close" means wipe out all the concerns. $requests = $object->getAudits(); foreach ($requests as $request) { if ($request->getAuditStatus() == $status_concerned) { $request->setAuditStatus($status_closed)->save(); } } break; case PhabricatorAuditActionConstants::RESIGN: $requests = $object->getAudits(); $requests = mpull($requests, null, 'getAuditorPHID'); $actor_request = idx($requests, $actor_phid); // If the actor doesn't currently have a relationship to the // commit, add one explicitly. For example, this allows members // of a project to resign from a commit and have it drop out of // their queue. if (!$actor_request) { $actor_request = id(new PhabricatorRepositoryAuditRequest())->setCommitPHID($object->getPHID())->setAuditorPHID($actor_phid); $requests[] = $actor_request; $object->attachAudits($requests); } $actor_request->setAuditStatus($status_resigned)->save(); break; case PhabricatorAuditActionConstants::ACCEPT: case PhabricatorAuditActionConstants::CONCERN: if ($new == PhabricatorAuditActionConstants::ACCEPT) { $new_status = $status_accepted; } else { $new_status = $status_concerned; } $requests = $object->getAudits(); $requests = mpull($requests, null, 'getAuditorPHID'); // Figure out which requests the actor has authority over: these // are user requests where they are the auditor, and packages // and projects they are a member of. if ($actor_is_author) { // When modifying your own commits, you act only on behalf of // yourself, not your packages/projects -- the idea being that // you can't accept your own commits. $authority_phids = array($actor_phid); } else { $authority_phids = PhabricatorAuditCommentEditor::loadAuditPHIDsForUser($this->requireActor()); } $authority = array_select_keys($requests, $authority_phids); if (!$authority) { // If the actor has no authority over any existing requests, // create a new request for them. $actor_request = id(new PhabricatorRepositoryAuditRequest())->setCommitPHID($object->getPHID())->setAuditorPHID($actor_phid)->setAuditStatus($new_status)->save(); $requests[$actor_phid] = $actor_request; $object->attachAudits($requests); } else { // Otherwise, update the audit status of the existing requests. foreach ($authority as $request) { $request->setAuditStatus($new_status)->save(); } } break; } break; } } $requests = $object->getAudits(); $object->updateAuditStatus($requests); $object->save(); return $xactions; }
protected function applyFinalEffects(PhabricatorLiskDAO $object, array $xactions) { if ($this->isContribution()) { $object->setVersions($object->getVersions() + 1); $body = $object->getDocumentBody(); $body->setVersion($object->getVersions()); $body->setDocumentPHID($object->getPHID()); $body->save(); $object->setDocumentBodyPHID($body->getPHID()); $actor = $this->getActor(); $type = PhabricatorContributedToObjectEdgeType::EDGECONST; id(new PhabricatorEdgeEditor())->addEdge($actor->getPHID(), $type, $object->getPHID())->save(); $type = PhabricatorObjectHasContributorEdgeType::EDGECONST; $contributors = PhabricatorEdgeQuery::loadDestinationPHIDs($object->getPHID(), $type); $object->setRecentContributorPHIDs(array_slice($contributors, 0, 3)); $object->setContributorCount(count($contributors)); $object->save(); } return $xactions; }
protected function applyInitialEffects(PhabricatorLiskDAO $object, array $xactions) { $object->save(); foreach ($xactions as $xaction) { switch ($xaction->getTransactionType()) { case ConpherenceTransaction::TYPE_PARTICIPANTS: // Since this is a new ConpherenceThread, we have to create the // participation data asap to pass policy checks. For existing // ConpherenceThreads, the existing participation is correct // at this stage. Note that later in applyCustomExternalTransaction // this participation data will be updated, particularly the // behindTransactionPHID which is just a generated dummy for now. $participants = array(); $phids = $this->getPHIDTransactionNewValue($xaction, array()); foreach ($phids as $phid) { if ($phid == $this->getActor()->getPHID()) { $status = ConpherenceParticipationStatus::UP_TO_DATE; $message_count = 1; } else { $status = ConpherenceParticipationStatus::BEHIND; $message_count = 0; } $participants[$phid] = id(new ConpherenceParticipant())->setConpherencePHID($object->getPHID())->setParticipantPHID($phid)->setParticipationStatus($status)->setDateTouched(time())->setBehindTransactionPHID($xaction->generatePHID())->setSeenMessageCount($message_count)->save(); $object->attachParticipants($participants); $object->setRecentParticipantPHIDs(array_keys($participants)); } break; } } }
protected function didApplyHeraldRules(PhabricatorLiskDAO $object, HeraldAdapter $adapter, HeraldTranscript $transcript) { // TODO: Convert these to transactions. The way Maniphest deals with these // transactions is currently unconventional and messy. $save_again = false; $cc_phids = $adapter->getCcPHIDs(); if ($cc_phids) { $existing_cc = $object->getCCPHIDs(); $new_cc = array_unique(array_merge($cc_phids, $existing_cc)); $object->setCCPHIDs($new_cc); $object->save(); } $this->heraldEmailPHIDs = $adapter->getEmailPHIDs(); $xactions = array(); $assign_phid = $adapter->getAssignPHID(); if ($assign_phid) { $xactions[] = id(new ManiphestTransaction())->setTransactionType(ManiphestTransaction::TYPE_OWNER)->setNewValue($assign_phid); } $project_phids = $adapter->getProjectPHIDs(); if ($project_phids) { $project_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST; $xactions[] = id(new ManiphestTransaction())->setTransactionType(PhabricatorTransactions::TYPE_EDGE)->setMetadataValue('edge:type', $project_type)->setNewValue(array('+' => array_fuse($project_phids))); } return $xactions; }
protected function applyFinalEffects(PhabricatorLiskDAO $object, array $xactions) { // If the repository does not have a local path yet, assign it one based // on its ID. We can't do this earlier because we won't have an ID yet. $local_path = $object->getDetail('local-path'); if (!strlen($local_path)) { $local_key = 'repository.default-local-path'; $local_root = PhabricatorEnv::getEnvConfig($local_key); $local_root = rtrim($local_root, '/'); $id = $object->getID(); $local_path = "{$local_root}/{$id}/"; $object->setDetail('local-path', $local_path); $object->save(); } return $xactions; }
protected function applyInitialEffects(PhabricatorLiskDAO $object, array $xactions) { $object->save(); }
protected function applyFinalEffects(PhabricatorLiskDAO $object, array $xactions) { $save_content = false; foreach ($xactions as $xaction) { switch ($xaction->getTransactionType()) { case PhrictionTransaction::TYPE_TITLE: case PhrictionTransaction::TYPE_CONTENT: case PhrictionTransaction::TYPE_DELETE: case PhrictionTransaction::TYPE_MOVE_AWAY: case PhrictionTransaction::TYPE_MOVE_TO: $save_content = true; break; default: break; } } if ($save_content) { $content = $this->getNewContent(); $content->setDocumentID($object->getID()); $content->save(); $object->setContentID($content->getID()); $object->save(); $object->attachContent($content); } if ($this->getIsNewObject() && !$this->getSkipAncestorCheck()) { // Stub out empty parent documents if they don't exist $ancestral_slugs = PhabricatorSlug::getAncestry($object->getSlug()); if ($ancestral_slugs) { $ancestors = id(new PhrictionDocumentQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withSlugs($ancestral_slugs)->needContent(true)->execute(); $ancestors = mpull($ancestors, null, 'getSlug'); $stub_type = PhrictionChangeType::CHANGE_STUB; foreach ($ancestral_slugs as $slug) { $ancestor_doc = idx($ancestors, $slug); // We check for change type to prevent near-infinite recursion if (!$ancestor_doc && $content->getChangeType() != $stub_type) { $ancestor_doc = PhrictionDocument::initializeNewDocument($this->getActor(), $slug); $stub_xactions = array(); $stub_xactions[] = id(new PhrictionTransaction())->setTransactionType(PhrictionTransaction::TYPE_TITLE)->setNewValue(PhabricatorSlug::getDefaultTitle($slug))->setMetadataValue('stub:create:phid', $object->getPHID()); $stub_xactions[] = id(new PhrictionTransaction())->setTransactionType(PhrictionTransaction::TYPE_CONTENT)->setNewValue('')->setMetadataValue('stub:create:phid', $object->getPHID()); $stub_xactions[] = id(new PhrictionTransaction())->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)->setNewValue($object->getViewPolicy()); $stub_xactions[] = id(new PhrictionTransaction())->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY)->setNewValue($object->getEditPolicy()); $sub_editor = id(new PhrictionTransactionEditor())->setActor($this->getActor())->setContentSource($this->getContentSource())->setContinueOnNoEffect($this->getContinueOnNoEffect())->setSkipAncestorCheck(true)->setDescription(pht('Empty Parent Document'))->applyTransactions($ancestor_doc, $stub_xactions); } } } } if ($this->moveAwayDocument !== null) { $move_away_xactions = array(); $move_away_xactions[] = id(new PhrictionTransaction())->setTransactionType(PhrictionTransaction::TYPE_MOVE_AWAY)->setNewValue($object); $sub_editor = id(new PhrictionTransactionEditor())->setActor($this->getActor())->setContentSource($this->getContentSource())->setContinueOnNoEffect($this->getContinueOnNoEffect())->setDescription($this->getDescription())->applyTransactions($this->moveAwayDocument, $move_away_xactions); } // Compute the content diff URI for the publishing phase. foreach ($xactions as $xaction) { switch ($xaction->getTransactionType()) { case PhrictionTransaction::TYPE_CONTENT: $uri = id(new PhutilURI('/phriction/diff/' . $object->getID() . '/'))->alter('l', $this->getOldContent()->getVersion())->alter('r', $this->getNewContent()->getVersion()); $this->contentDiffURI = (string) $uri; break 2; default: break; } } return $xactions; }
protected function applyFinalEffects(PhabricatorLiskDAO $object, array $xactions) { // If the repository does not have a local path yet, assign it one based // on its ID. We can't do this earlier because we won't have an ID yet. $local_path = $object->getLocalPath(); if (!strlen($local_path)) { $local_key = 'repository.default-local-path'; $local_root = PhabricatorEnv::getEnvConfig($local_key); $local_root = rtrim($local_root, '/'); $id = $object->getID(); $local_path = "{$local_root}/{$id}/"; $object->setLocalPath($local_path); $object->save(); } if ($this->getIsNewObject()) { // The default state of repositories is to be hosted, if they are // enabled without configuring any "Observe" URIs. $object->setHosted(true); $object->save(); // Create this repository's builtin URIs. $builtin_uris = $object->newBuiltinURIs(); foreach ($builtin_uris as $uri) { $uri->save(); } id(new DiffusionRepositoryClusterEngine())->setViewer($this->getActor())->setRepository($object)->synchronizeWorkingCopyAfterCreation(); } return $xactions; }