public function execute(PhutilArgumentParser $args) { $viewer = $this->getViewer(); $argv = $args->getArg('argv'); if (count($argv) !== 2) { throw new PhutilArgumentUsageException(pht('Specify a commit and a revision to attach it to.')); } $commit_name = head($argv); $revision_name = last($argv); $commit = id(new DiffusionCommitQuery())->setViewer($viewer)->withIdentifiers(array($commit_name))->executeOne(); if (!$commit) { throw new PhutilArgumentUsageException(pht('Commit "%s" does not exist.', $commit_name)); } $revision = id(new PhabricatorObjectQuery())->setViewer($viewer)->withNames(array($revision_name))->executeOne(); if (!$revision) { throw new PhutilArgumentUsageException(pht('Revision "%s" does not exist.', $revision_name)); } if (!$revision instanceof DifferentialRevision) { throw new PhutilArgumentUsageException(pht('Object "%s" must be a Differential revision.', $revision_name)); } // Reload the revision to get the active diff. $revision = id(new DifferentialRevisionQuery())->setViewer($viewer)->withIDs(array($revision->getID()))->needActiveDiffs(true)->executeOne(); $differential_phid = id(new PhabricatorDifferentialApplication())->getPHID(); $extraction_engine = id(new DifferentialDiffExtractionEngine())->setViewer($viewer)->setAuthorPHID($differential_phid); $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_CONSOLE, array()); $extraction_engine->updateRevisionWithCommit($revision, $commit, array(), $content_source); echo tsprintf("%s\n", pht('Attached "%s" to "%s".', $commit->getMonogram(), $revision->getMonogram())); }
public function processRequest() { $request = $this->getRequest(); if (!$request->isFormPost()) { return new Aphront400Response(); } $revision_id = $request->getInt('revision_id'); $revision = id(new DifferentialRevision())->load($revision_id); if (!$revision) { return new Aphront400Response(); } $comment = $request->getStr('comment'); $action = $request->getStr('action'); $reviewers = $request->getArr('reviewers'); $ccs = $request->getArr('ccs'); $editor = new DifferentialCommentEditor($revision, $request->getUser()->getPHID(), $action); $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_WEB, array('ip' => $request->getRemoteAddr())); $editor->setMessage($comment)->setContentSource($content_source)->setAttachInlineComments(true)->setAddCC($action != DifferentialAction::ACTION_RESIGN)->setAddedReviewers($reviewers)->setAddedCCs($ccs)->save(); // TODO: Diff change detection? $draft = id(new PhabricatorDraft())->loadOneWhere('authorPHID = %s AND draftKey = %s', $request->getUser()->getPHID(), 'differential-comment-' . $revision->getID()); if ($draft) { $draft->delete(); } return id(new AphrontRedirectResponse())->setURI('/D' . $revision->getID()); }
public function generateObject() { $author_phid = $this->loadPhabrictorUserPHID(); $author = id(new PhabricatorUser())->loadOneWhere('phid = %s', $author_phid); $task = ManiphestTask::initializeNewTask($author)->setSubPriority($this->generateTaskSubPriority())->setTitle($this->generateTitle()); $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_UNKNOWN, array()); $template = new ManiphestTransaction(); // Accumulate Transactions $changes = array(); $changes[ManiphestTransaction::TYPE_TITLE] = $this->generateTitle(); $changes[ManiphestTransaction::TYPE_DESCRIPTION] = $this->generateDescription(); $changes[ManiphestTransaction::TYPE_OWNER] = $this->loadOwnerPHID(); $changes[ManiphestTransaction::TYPE_STATUS] = $this->generateTaskStatus(); $changes[ManiphestTransaction::TYPE_PRIORITY] = $this->generateTaskPriority(); $changes[PhabricatorTransactions::TYPE_SUBSCRIBERS] = array('=' => $this->getCCPHIDs()); $transactions = array(); foreach ($changes as $type => $value) { $transaction = clone $template; $transaction->setTransactionType($type); $transaction->setNewValue($value); $transactions[] = $transaction; } $transactions[] = id(new ManiphestTransaction())->setTransactionType(PhabricatorTransactions::TYPE_EDGE)->setMetadataValue('edge:type', PhabricatorProjectObjectHasProjectEdgeType::EDGECONST)->setNewValue(array('=' => array_fuse($this->getProjectPHIDs()))); // Apply Transactions $editor = id(new ManiphestTransactionEditor())->setActor($author)->setContentSource($content_source)->setContinueOnNoEffect(true)->setContinueOnMissingFields(true)->applyTransactions($task, $transactions); return $task; }
protected function processReceivedMail(PhabricatorMetaMTAReceivedMail $mail, PhabricatorUser $sender) { $title = $mail->getSubject(); if (!$title) { $title = pht('Email Paste'); } $file = PhabricatorPasteEditor::initializeFileForPaste($sender, $title, $mail->getCleanTextBody()); $xactions = array(); $xactions[] = id(new PhabricatorPasteTransaction())->setTransactionType(PhabricatorPasteTransaction::TYPE_CONTENT)->setNewValue($file->getPHID()); $xactions[] = id(new PhabricatorPasteTransaction())->setTransactionType(PhabricatorPasteTransaction::TYPE_TITLE)->setNewValue($title); $xactions[] = id(new PhabricatorPasteTransaction())->setTransactionType(PhabricatorPasteTransaction::TYPE_LANGUAGE)->setNewValue(''); // auto-detect $paste = PhabricatorPaste::initializeNewPaste($sender); $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_EMAIL, array('id' => $mail->getID())); $editor = id(new PhabricatorPasteEditor())->setActor($sender)->setContentSource($content_source)->setContinueOnNoEffect(true); $xactions = $editor->applyTransactions($paste, $xactions); $mail->setRelatedPHID($paste->getPHID()); $subject_prefix = PhabricatorEnv::getEnvConfig('metamta.paste.subject-prefix'); $subject = pht('You successfully created a paste.'); $paste_uri = PhabricatorEnv::getProductionURI($paste->getURI()); $body = new PhabricatorMetaMTAMailBody(); $body->addRawSection($subject); $body->addTextSection(pht('PASTE LINK'), $paste_uri); id(new PhabricatorMetaMTAMail())->addTos(array($sender->getPHID()))->setSubject($subject)->setSubjectPrefix($subject_prefix)->setFrom($sender->getPHID())->setRelatedPHID($paste->getPHID())->setBody($body->render())->saveAndSend(); }
protected function parseCommit(PhabricatorRepository $repository, PhabricatorRepositoryCommit $commit) { // Reload the commit to pull commit data and audit requests. $commit = id(new DiffusionCommitQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withIDs(array($commit->getID()))->needCommitData(true)->needAuditRequests(true)->executeOne(); $data = $commit->getCommitData(); if (!$data) { throw new PhabricatorWorkerPermanentFailureException(pht('Unable to load commit data. The data for this task is invalid ' . 'or no longer exists.')); } $commit->attachRepository($repository); $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_DAEMON, array()); $committer_phid = $data->getCommitDetail('committerPHID'); $author_phid = $data->getCommitDetail('authorPHID'); $acting_as_phid = nonempty($committer_phid, $author_phid, id(new PhabricatorDiffusionApplication())->getPHID()); $editor = id(new PhabricatorAuditEditor())->setActor(PhabricatorUser::getOmnipotentUser())->setActingAsPHID($acting_as_phid)->setContinueOnMissingFields(true)->setContinueOnNoEffect(true)->setContentSource($content_source); $xactions = array(); $xactions[] = id(new PhabricatorAuditTransaction())->setTransactionType(PhabricatorAuditTransaction::TYPE_COMMIT)->setDateCreated($commit->getEpoch())->setNewValue(array('description' => $data->getCommitMessage(), 'summary' => $data->getSummary(), 'authorName' => $data->getAuthorName(), 'authorPHID' => $commit->getAuthorPHID(), 'committerName' => $data->getCommitDetail('committer'), 'committerPHID' => $data->getCommitDetail('committerPHID'))); $reverts_refs = id(new DifferentialCustomFieldRevertsParser())->parseCorpus($data->getCommitMessage()); $reverts = array_mergev(ipull($reverts_refs, 'monograms')); if ($reverts) { $reverted_commits = id(new DiffusionCommitQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withRepository($repository)->withIdentifiers($reverts)->execute(); $reverted_commit_phids = mpull($reverted_commits, 'getPHID', 'getPHID'); // NOTE: Skip any write attempts if a user cleverly implies a commit // reverts itself. unset($reverted_commit_phids[$commit->getPHID()]); $reverts_edge = DiffusionCommitRevertsCommitEdgeType::EDGECONST; $xactions[] = id(new PhabricatorAuditTransaction())->setTransactionType(PhabricatorTransactions::TYPE_EDGE)->setMetadataValue('edge:type', $reverts_edge)->setNewValue(array('+' => array_fuse($reverted_commit_phids))); } try { $raw_patch = $this->loadRawPatchText($repository, $commit); } catch (Exception $ex) { $raw_patch = pht('Unable to generate patch: %s', $ex->getMessage()); } $editor->setRawPatch($raw_patch); return $editor->applyTransactions($commit, $xactions); }
protected function execute(ConduitAPIRequest $request) { $diff = id(new DifferentialDiff())->load($request->getValue('diffid')); if (!$diff) { throw new ConduitException('ERR_BAD_DIFF'); } $revision = id(new DifferentialRevision())->load($request->getValue('id')); if (!$revision) { throw new ConduitException('ERR_BAD_REVISION'); } if ($request->getUser()->getPHID() !== $revision->getAuthorPHID()) { throw new ConduitException('ERR_WRONG_USER'); } if ($revision->getStatus() == ArcanistDifferentialRevisionStatus::CLOSED) { throw new ConduitException('ERR_CLOSED'); } $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_CONDUIT, array()); $editor = new DifferentialRevisionEditor($revision, $revision->getAuthorPHID()); $editor->setContentSource($content_source); $fields = $request->getValue('fields'); $editor->copyFieldsFromConduit($fields); $editor->addDiff($diff, $request->getValue('message')); $editor->save(); return array('revisionid' => $revision->getID(), 'uri' => PhabricatorEnv::getURI('/D' . $revision->getID())); }
protected function receiveEmail(PhabricatorMetaMTAReceivedMail $mail) { $actor = $this->getActor(); $document = $this->getMailReceiver(); $body_data = $mail->parseBody(); $body = $body_data['body']; $body = $this->enhanceBodyWithAttachments($body, $mail->getAttachments()); $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_EMAIL, array('id' => $mail->getID())); $xactions = array(); $command = $body_data['command']; switch ($command) { case 'unsubscribe': $xaction = id(new LegalpadTransaction())->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS)->setNewValue(array('-' => array($actor->getPHID()))); $xactions[] = $xaction; break; } $xactions[] = id(new LegalpadTransaction())->setTransactionType(PhabricatorTransactions::TYPE_COMMENT)->attachComment(id(new LegalpadTransactionComment())->setDocumentID($document->getID())->setLineNumber(0)->setLineLength(0)->setContent($body)); $editor = id(new LegalpadDocumentEditor())->setActor($actor)->setContentSource($content_source)->setContinueOnNoEffect(true)->setIsPreview(false); try { $xactions = $editor->applyTransactions($document, $xactions); } catch (PhabricatorApplicationTransactionNoEffectException $ex) { // just do nothing, though unclear why you're sending a blank email return true; } $head_xaction = head($xactions); return $head_xaction->getID(); }
public function processRequest() { $request = $this->getRequest(); $viewer = $request->getUser(); if (!$request->isFormPost()) { return new Aphront400Response(); } $question_id = $request->getInt('question_id'); $question = id(new PonderQuestionQuery())->setViewer($viewer)->withIDs(array($question_id))->needAnswers(true)->executeOne(); if (!$question) { return new Aphront404Response(); } $answer = $request->getStr('answer'); if (!strlen(trim($answer))) { $dialog = id(new AphrontDialogView())->setUser($viewer)->setTitle(pht('Empty Answer'))->appendChild(phutil_tag('p', array(), pht('Your answer must not be empty.')))->addCancelButton('/Q' . $question_id); return id(new AphrontDialogResponse())->setDialog($dialog); } $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_WEB, array('ip' => $request->getRemoteAddr())); $res = id(new PonderAnswer())->setAuthorPHID($viewer->getPHID())->setQuestionID($question->getID())->setContent($answer)->setVoteCount(0)->setContentSource($content_source); $xactions = array(); $xactions[] = id(new PonderQuestionTransaction())->setTransactionType(PonderQuestionTransaction::TYPE_ANSWERS)->setNewValue(array('+' => array(array('answer' => $res)))); $editor = id(new PonderQuestionEditor())->setActor($viewer)->setContentSourceFromRequest($request); $editor->applyTransactions($question, $xactions); return id(new AphrontRedirectResponse())->setURI(id(new PhutilURI('/Q' . $question->getID()))); }
protected function receiveEmail(PhabricatorMetaMTAReceivedMail $mail) { $conpherence = $this->getMailReceiver(); $user = $this->getActor(); if (!$conpherence->getPHID()) { $conpherence->attachParticipants(array())->attachFilePHIDs(array()); } else { $edge_type = PhabricatorObjectHasFileEdgeType::EDGECONST; $file_phids = PhabricatorEdgeQuery::loadDestinationPHIDs($conpherence->getPHID(), $edge_type); $conpherence->attachFilePHIDs($file_phids); $participants = id(new ConpherenceParticipant())->loadAllWhere('conpherencePHID = %s', $conpherence->getPHID()); $participants = mpull($participants, null, 'getParticipantPHID'); $conpherence->attachParticipants($participants); } $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_EMAIL, array('id' => $mail->getID())); $editor = id(new ConpherenceEditor())->setActor($user)->setContentSource($content_source)->setParentMessageID($mail->getMessageID()); $body = $mail->getCleanTextBody(); $body = $this->enhanceBodyWithAttachments($body, $mail->getAttachments()); $xactions = array(); if ($this->getMailAddedParticipantPHIDs()) { $xactions[] = id(new ConpherenceTransaction())->setTransactionType(ConpherenceTransaction::TYPE_PARTICIPANTS)->setNewValue(array('+' => $this->getMailAddedParticipantPHIDs())); } $xactions = array_merge($xactions, $editor->generateTransactionsFromText($user, $conpherence, $body)); $editor->applyTransactions($conpherence, $xactions); return $conpherence; }
public function processRequest() { $request = $this->getRequest(); if (!$request->isFormPost()) { return new Aphront400Response(); } $user = $request->getUser(); $question_id = $request->getInt('question_id'); $question = PonderQuestionQuery::loadSingle($user, $question_id); if (!$question) { return new Aphront404Response(); } $answer = $request->getStr('answer'); // Only want answers with some non whitespace content if (!strlen(trim($answer))) { $dialog = new AphrontDialogView(); $dialog->setUser($request->getUser()); $dialog->setTitle('Empty answer'); $dialog->appendChild('<p>Your answer must not be empty.</p>'); $dialog->addCancelButton('/Q' . $question_id); return id(new AphrontDialogResponse())->setDialog($dialog); } $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_WEB, array('ip' => $request->getRemoteAddr())); $res = new PonderAnswer(); $res->setContent($answer)->setAuthorPHID($user->getPHID())->setVoteCount(0)->setQuestionID($question_id)->setContentSource($content_source); id(new PonderAnswerEditor())->setUser($user)->setQuestion($question)->setAnswer($res)->saveAnswer(); return id(new AphrontRedirectResponse())->setURI(id(new PhutilURI('/Q' . $question->getID()))); }
/** * Build and configure an Editor to publish these transactions. */ private function buildEditor(PhabricatorApplicationTransactionInterface $object) { $data = $this->getTaskData(); $daemon_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_DAEMON, array()); $viewer = PhabricatorUser::getOmnipotentUser(); $editor = $object->getApplicationTransactionEditor()->setActor($viewer)->setContentSource($daemon_source)->setActingAsPHID(idx($data, 'actorPHID'))->loadWorkerState(idx($data, 'state', array())); return $editor; }
private function newEditor(PhabricatorMetaMTAReceivedMail $mail) { $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_EMAIL, array('id' => $mail->getID())); $editor = $this->getMailReceiver()->getApplicationTransactionEditor()->setActor($this->getActor())->setContentSource($content_source)->setContinueOnMissingFields(true)->setParentMessageID($mail->getMessageID())->setExcludeMailRecipientPHIDs($this->getExcludeMailRecipientPHIDs()); if ($this->getApplicationEmail()) { $editor->setApplicationEmail($this->getApplicationEmail()); } return $editor; }
protected function execute(ConduitAPIRequest $request) { $action = $request->getValue('action'); $new_commit_id = $request->getValue('commitIdentifier'); $releeph_request = id(new ReleephRequest())->loadOneWhere('phid = %s', $request->getValue('requestPHID')); $xactions = array(); $xactions[] = id(new ReleephRequestTransaction())->setTransactionType(ReleephRequestTransaction::TYPE_COMMIT)->setMetadataValue('action', $action)->setNewValue($new_commit_id); $editor = id(new ReleephRequestTransactionalEditor())->setActor($request->getUser())->setContinueOnNoEffect(true)->setContentSource(PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_CONDUIT, array())); $editor->applyTransactions($releeph_request, $xactions); }
protected function receiveEmail(PhabricatorMetaMTAReceivedMail $mail) { $commit = $this->getMailReceiver(); $actor = $this->getActor(); $message = $mail->getCleanTextBody(); $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_EMAIL, array('id' => $mail->getID())); // TODO: Support !raise, !accept, etc. $xactions = array(); $xactions[] = id(new PhabricatorAuditTransaction())->setTransactionType(PhabricatorTransactions::TYPE_COMMENT)->attachComment(id(new PhabricatorAuditTransactionComment())->setCommitPHID($commit->getPHID())->setContent($message)); $editor = id(new PhabricatorAuditEditor())->setActor($actor)->setContentSource($content_source)->setExcludeMailRecipientPHIDs($this->getExcludeMailRecipientPHIDs())->setContinueOnMissingFields(true)->applyTransactions($commit, $xactions); }
protected function doWork() { $subscription = $this->loadSubscription(); $range = $this->getBillingPeriodRange($subscription); list($last_epoch, $next_epoch) = $range; $should_invoice = $subscription->shouldInvoiceForBillingPeriod($last_epoch, $next_epoch); if (!$should_invoice) { return; } $currency = $subscription->getCostForBillingPeriodAsCurrency($last_epoch, $next_epoch); if (!$currency->isPositive()) { return; } $account = $subscription->getAccount(); $merchant = $subscription->getMerchant(); $viewer = PhabricatorUser::getOmnipotentUser(); $product = id(new PhortuneProductQuery())->setViewer($viewer)->withClassAndRef('PhortuneSubscriptionProduct', $subscription->getPHID())->executeOne(); $cart_implementation = id(new PhortuneSubscriptionCart())->setSubscription($subscription); // TODO: This isn't really ideal. It would be better to use an application // actor than the original author of the subscription. In particular, if // someone initiates a subscription, adds some other account managers, and // later leaves the company, they'll continue "acting" here indefinitely. // However, for now, some of the stuff later in the pipeline requires a // valid actor with a real PHID. The subscription should eventually be // able to create these invoices "as" the application it is acting on // behalf of. $actor = id(new PhabricatorPeopleQuery())->setViewer($viewer)->withPHIDs(array($subscription->getAuthorPHID()))->executeOne(); if (!$actor) { throw new Exception(pht('Failed to load actor to bill subscription!')); } $cart = $account->newCart($actor, $cart_implementation, $merchant); $purchase = $cart->newPurchase($actor, $product); $purchase->setBasePriceAsCurrency($currency)->setMetadataValue('subscriptionPHID', $subscription->getPHID())->setMetadataValue('epoch.start', $last_epoch)->setMetadataValue('epoch.end', $next_epoch)->save(); $cart->setSubscriptionPHID($subscription->getPHID())->setIsInvoice(1)->save(); $cart->activateCart(); try { $issues = $this->chargeSubscription($actor, $subscription, $cart); } catch (Exception $ex) { $issues = array(pht('There was a technical error while trying to automatically bill ' . 'this subscription: %s', $ex)); } if (!$issues) { // We're all done; charging the cart sends a billing email as a side // effect. return; } // We're shoving this through the CartEditor because it has all the logic // for sending mail about carts. This doesn't really affect the state of // the cart, but reduces the amount of code duplication. $xactions = array(); $xactions[] = id(new PhortuneCartTransaction())->setTransactionType(PhortuneCartTransaction::TYPE_INVOICED)->setNewValue(true); $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_PHORTUNE, array()); $acting_phid = id(new PhabricatorPhortuneApplication())->getPHID(); $editor = id(new PhortuneCartEditor())->setActor($viewer)->setActingAsPHID($acting_phid)->setContentSource($content_source)->setContinueOnMissingFields(true)->setInvoiceIssues($issues)->applyTransactions($cart, $xactions); }
protected function receiveEmail(PhabricatorMetaMTAReceivedMail $mail) { $rq = $this->getMailReceiver(); $user = $this->getActor(); $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_EMAIL, array('id' => $mail->getID())); $editor = id(new ReleephRequestTransactionalEditor())->setActor($user)->setContentSource($content_source)->setParentMessageID($mail->getMessageID()); $body = $mail->getCleanTextBody(); $xactions = array(); $xactions[] = id(new ReleephRequestTransaction())->setTransactionType(PhabricatorTransactions::TYPE_COMMENT)->attachComment($body); $editor->applyTransactions($rq, $xactions); return $rq; }
protected function execute(ConduitAPIRequest $request) { $revision = id(new DifferentialRevision())->load($request->getValue('revision_id')); if (!$revision) { throw new ConduitException('ERR_BAD_REVISION'); } $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_CONDUIT, array()); $editor = new DifferentialCommentEditor($revision, $request->getUser()->getPHID(), DifferentialAction::ACTION_COMMENT); $editor->setContentSource($content_source); $editor->setMessage($request->getValue('message')); $editor->save(); return array('revisionid' => $revision->getID(), 'uri' => PhabricatorEnv::getURI('/D' . $revision->getID())); }
protected function execute(ConduitAPIRequest $request) { $viewer = $request->getUser(); $id = $request->getValue('revisionID'); $revision = id(new DifferentialRevisionQuery())->withIDs(array($id))->setViewer($viewer)->needReviewerStatus(true)->executeOne(); if (!$revision) { throw new ConduitException('ERR_NOT_FOUND'); } $xactions = array(); $xactions[] = id(new DifferentialTransaction())->setTransactionType(DifferentialTransaction::TYPE_ACTION)->setNewValue(DifferentialAction::ACTION_CLOSE); $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_CONDUIT, array()); $editor = id(new DifferentialTransactionEditor())->setActor($viewer)->setContentSourceFromConduitRequest($request)->setContinueOnMissingFields(true)->setContinueOnNoEffect(true); $editor->applyTransactions($revision, $xactions); return; }
public function generate() { $author = $this->loadPhabrictorUser(); $revision = DifferentialRevision::initializeNewRevision($author); $revision->attachReviewerStatus(array()); $revision->attachActiveDiff(null); // This could be a bit richer and more formal than it is. $revision->setTitle($this->generateTitle()); $revision->setSummary($this->generateDescription()); $revision->setTestPlan($this->generateDescription()); $diff = $this->generateDiff($author); $xactions = array(); $xactions[] = id(new DifferentialTransaction())->setTransactionType(DifferentialTransaction::TYPE_UPDATE)->setNewValue($diff->getPHID()); $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_LIPSUM, array()); id(new DifferentialTransactionEditor())->setActor($author)->setContentSource($content_source)->applyTransactions($revision, $xactions); return $revision; }
protected function execute(ConduitAPIRequest $request) { $task = new ManiphestTask(); $task->setPriority(ManiphestTaskPriority::PRIORITY_TRIAGE); $task->setAuthorPHID($request->getUser()->getPHID()); $task->setTitle((string) $request->getValue('title')); $task->setDescription((string) $request->getValue('description')); $changes = array(); $changes[ManiphestTransactionType::TYPE_STATUS] = ManiphestTaskStatus::STATUS_OPEN; $priority = $request->getValue('priority'); if ($priority !== null) { $changes[ManiphestTransactionType::TYPE_PRIORITY] = $priority; } $owner_phid = $request->getValue('ownerPHID'); if ($owner_phid !== null) { $changes[ManiphestTransactionType::TYPE_OWNER] = $owner_phid; } $ccs = $request->getValue('ccPHIDs'); if ($ccs !== null) { $changes[ManiphestTransactionType::TYPE_CCS] = $ccs; } $project_phids = $request->getValue('projectPHIDs'); if ($project_phids !== null) { $changes[ManiphestTransactionType::TYPE_PROJECTS] = $project_phids; } $file_phids = $request->getValue('filePHIDs'); if ($file_phids !== null) { $file_map = array_fill_keys($file_phids, true); $changes[ManiphestTransactionType::TYPE_ATTACH] = array(PhabricatorPHIDConstants::PHID_TYPE_FILE => $file_map); } $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_CONDUIT, array()); $template = new ManiphestTransaction(); $template->setContentSource($content_source); $template->setAuthorPHID($request->getUser()->getPHID()); $transactions = array(); foreach ($changes as $type => $value) { $transaction = clone $template; $transaction->setTransactionType($type); $transaction->setNewValue($value); $transactions[] = $transaction; } $editor = new ManiphestTransactionEditor(); $editor->applyTransactions($task, $transactions); return $this->buildTaskInfoDictionary($task); }
public function processRequest() { $request = $this->getRequest(); if (!$request->isFormPost()) { return new Aphront400Response(); } $revision_id = $request->getInt('revision_id'); $revision = id(new DifferentialRevision())->load($revision_id); if (!$revision) { return new Aphront400Response(); } $comment = $request->getStr('comment'); $action = $request->getStr('action'); $reviewers = $request->getArr('reviewers'); $ccs = $request->getArr('ccs'); $editor = new DifferentialCommentEditor($revision, $request->getUser()->getPHID(), $action); $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_WEB, array('ip' => $request->getRemoteAddr())); try { $editor->setMessage($comment)->setContentSource($content_source)->setAttachInlineComments(true)->setAddedReviewers($reviewers)->setAddedCCs($ccs)->save(); } catch (DifferentialActionHasNoEffectException $no_effect) { $has_inlines = id(new DifferentialInlineComment())->loadAllWhere('authorPHID = %s AND revisionID = %d AND commentID IS NULL', $request->getUser()->getPHID(), $revision->getID()); $dialog = new AphrontDialogView(); $dialog->setUser($request->getUser()); $dialog->addCancelButton('/D' . $revision_id); $dialog->addHiddenInput('revision_id', $revision_id); $dialog->addHiddenInput('action', 'none'); $dialog->addHiddenInput('reviewers', $reviewers); $dialog->addHiddenInput('ccs', $ccs); $dialog->addHiddenInput('comment', $comment); $dialog->setTitle('Action Has No Effect'); $dialog->appendChild('<p>' . phutil_escape_html($no_effect->getMessage()) . '</p>'); if (strlen($comment) || $has_inlines) { $dialog->addSubmitButton('Post as Comment'); $dialog->appendChild('<br />'); $dialog->appendChild('<p>Do you want to post your feedback anyway, as a normal ' . 'comment?</p>'); } return id(new AphrontDialogResponse())->setDialog($dialog); } // TODO: Diff change detection? $draft = id(new PhabricatorDraft())->loadOneWhere('authorPHID = %s AND draftKey = %s', $request->getUser()->getPHID(), 'differential-comment-' . $revision->getID()); if ($draft) { $draft->delete(); } return id(new AphrontRedirectResponse())->setURI('/D' . $revision->getID()); }
public function generate() { $author_phid = $this->loadPhabrictorUserPHID(); $author = id(new PhabricatorUser())->loadOneWhere('phid = %s', $author_phid); $mock = PholioMock::initializeNewMock($author); $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_UNKNOWN, array()); $template = id(new PholioTransaction())->setContentSource($content_source); // Accumulate Transactions $changes = array(); $changes[PholioTransaction::TYPE_NAME] = $this->generateTitle(); $changes[PholioTransaction::TYPE_DESCRIPTION] = $this->generateDescription(); $changes[PhabricatorTransactions::TYPE_VIEW_POLICY] = PhabricatorPolicies::POLICY_PUBLIC; $changes[PhabricatorTransactions::TYPE_SUBSCRIBERS] = array('=' => $this->getCCPHIDs()); // Get Files and make Images $file_phids = $this->generateImages(); $files = id(new PhabricatorFileQuery())->setViewer($author)->withPHIDs($file_phids)->execute(); $mock->setCoverPHID(head($files)->getPHID()); $sequence = 0; $images = array(); foreach ($files as $file) { $image = new PholioImage(); $image->setFilePHID($file->getPHID()); $image->setSequence($sequence++); $image->attachMock($mock); $images[] = $image; } // Apply Transactions $transactions = array(); foreach ($changes as $type => $value) { $transaction = clone $template; $transaction->setTransactionType($type); $transaction->setNewValue($value); $transactions[] = $transaction; } $mock->openTransaction(); $editor = id(new PholioMockEditor())->setContentSource($content_source)->setContinueOnNoEffect(true)->setActor($author)->applyTransactions($mock, $transactions); foreach ($images as $image) { $image->setMockID($mock->getID()); $image->save(); } $mock->saveTransaction(); return $mock->save(); }
public function processRequest() { $request = $this->getRequest(); if (!$request->isFormPost()) { return new Aphront400Response(); } $user = $request->getUser(); $question_id = $request->getInt('question_id'); $question = PonderQuestionQuery::loadSingle($user, $question_id); if (!$question) { return new Aphront404Response(); } $answer = $request->getStr('answer'); $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_WEB, array('ip' => $request->getRemoteAddr())); $res = new PonderAnswer(); $res->setContent($answer)->setAuthorPHID($user->getPHID())->setVoteCount(0)->setQuestionID($question_id)->setContentSource($content_source); id(new PonderAnswerEditor())->setQuestion($question)->setAnswer($res)->saveAnswer(); PhabricatorSearchPonderIndexer::indexQuestion($question); return id(new AphrontRedirectResponse())->setURI(id(new PhutilURI('/Q' . $question->getID()))->setFragment('A' . $res->getID())); }
private function handlePost() { $request = $this->getRequest(); $user = $request->getUser(); $errors = array(); $title = $request->getStr('title'); $content = $request->getStr('content'); // form validation if (phutil_utf8_strlen($title) < 1 || phutil_utf8_strlen($title) > 255) { $errors[] = "Please enter a title (1-255 characters)"; } if ($errors) { return $this->showForm($errors, $title, $content); } // no validation errors -> save it $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_WEB, array('ip' => $request->getRemoteAddr())); $question = id(new PonderQuestion())->setTitle($title)->setContent($content)->setAuthorPHID($user->getPHID())->setContentSource($content_source)->setVoteCount(0)->setAnswerCount(0)->setHeat(0.0)->save(); PhabricatorSearchPonderIndexer::indexQuestion($question); return id(new AphrontRedirectResponse())->setURI('/Q' . $question->getID()); }
public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); $question = id(new PonderQuestion())->setAuthorPHID($user->getPHID())->setVoteCount(0)->setAnswerCount(0)->setHeat(0.0); $errors = array(); $e_title = true; if ($request->isFormPost()) { $question->setTitle($request->getStr('title')); $question->setContent($request->getStr('content')); $len = phutil_utf8_strlen($question->getTitle()); if ($len < 1) { $errors[] = pht('Title must not be empty.'); $e_title = pht('Required'); } else { if ($len > 255) { $errors[] = pht('Title is too long.'); $e_title = pht('Too Long'); } } if (!$errors) { $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_WEB, array('ip' => $request->getRemoteAddr())); $question->setContentSource($content_source); id(new PonderQuestionEditor())->setQuestion($question)->setUser($user)->save(); return id(new AphrontRedirectResponse())->setURI('/Q' . $question->getID()); } } $error_view = null; if ($errors) { $error_view = id(new AphrontErrorView())->setTitle('Form Errors')->setErrors($errors); } $header = id(new PhabricatorHeaderView())->setHeader(pht('Ask Question')); $form = id(new AphrontFormView())->setUser($user)->setFlexible(true)->appendChild(id(new AphrontFormTextControl())->setLabel(pht('Question'))->setName('title')->setValue($question->getTitle())->setError($e_title))->appendChild(id(new PhabricatorRemarkupControl())->setName('content')->setID('content')->setValue($question->getContent())->setLabel(pht('Description')))->appendChild(id(new AphrontFormSubmitControl())->setValue('Ask Away!')); $preview = '<div class="aphront-panel-flush">' . '<div id="question-preview">' . '<span class="aphront-panel-preview-loading-text">' . pht('Loading question preview...') . '</span>' . '</div>' . '</div>'; Javelin::initBehavior('ponder-feedback-preview', array('uri' => '/ponder/question/preview/', 'content' => 'content', 'preview' => 'question-preview', 'question_id' => null)); $nav = $this->buildSideNavView($question); $nav->selectFilter($question->getID() ? null : 'question/ask'); $nav->appendChild(array($header, $error_view, $form, $preview)); return $this->buildApplicationPage($nav, array('device' => true, 'title' => 'Ask a Question')); }
protected function execute(ConduitAPIRequest $request) { $action = $request->getValue('action'); $ok = $request->getValue('ok'); $dry_run = $request->getValue('dryRun'); $details = $request->getValue('details', array()); switch ($request->getValue('action')) { case 'pick': $pick_status = $ok ? ReleephRequest::PICK_OK : ReleephRequest::PICK_FAILED; break; case 'revert': $pick_status = $ok ? ReleephRequest::REVERT_OK : ReleephRequest::REVERT_FAILED; break; default: throw new Exception(pht('Unknown action %s!', $action)); } $releeph_request = id(new ReleephRequest())->loadOneWhere('phid = %s', $request->getValue('requestPHID')); $editor = id(new ReleephRequestTransactionalEditor())->setActor($request->getUser())->setContinueOnNoEffect(true)->setContentSource(PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_CONDUIT, array())); $xactions = array(); $xactions[] = id(new ReleephRequestTransaction())->setTransactionType(ReleephRequestTransaction::TYPE_PICK_STATUS)->setMetadataValue('dryRun', $dry_run)->setMetadataValue('details', $details)->setNewValue($pick_status); $editor->applyTransactions($releeph_request, $xactions); }
public final function applyTransactions(PhabricatorLiskDAO $object, array $xactions) { $this->object = $object; $this->xactions = $xactions; $this->isNewObject = $object->getPHID() === null; $this->validateEditParameters($object, $xactions); $actor = $this->requireActor(); // NOTE: Some transaction expansion requires that the edited object be // attached. foreach ($xactions as $xaction) { $xaction->attachObject($object); $xaction->attachViewer($actor); } $xactions = $this->expandTransactions($object, $xactions); $xactions = $this->expandSupportTransactions($object, $xactions); $xactions = $this->combineTransactions($xactions); foreach ($xactions as $xaction) { $xaction = $this->populateTransaction($object, $xaction); } $is_preview = $this->getIsPreview(); $read_locking = false; $transaction_open = false; if (!$is_preview) { $errors = array(); $type_map = mgroup($xactions, 'getTransactionType'); foreach ($this->getTransactionTypes() as $type) { $type_xactions = idx($type_map, $type, array()); $errors[] = $this->validateTransaction($object, $type, $type_xactions); } $errors = array_mergev($errors); $continue_on_missing = $this->getContinueOnMissingFields(); foreach ($errors as $key => $error) { if ($continue_on_missing && $error->getIsMissingFieldError()) { unset($errors[$key]); } } if ($errors) { throw new PhabricatorApplicationTransactionValidationException($errors); } $file_phids = $this->extractFilePHIDs($object, $xactions); if ($object->getID()) { foreach ($xactions as $xaction) { // If any of the transactions require a read lock, hold one and // reload the object. We need to do this fairly early so that the // call to `adjustTransactionValues()` (which populates old values) // is based on the synchronized state of the object, which may differ // from the state when it was originally loaded. if ($this->shouldReadLock($object, $xaction)) { $object->openTransaction(); $object->beginReadLocking(); $transaction_open = true; $read_locking = true; $object->reload(); break; } } } if ($this->shouldApplyInitialEffects($object, $xactions)) { if (!$transaction_open) { $object->openTransaction(); $transaction_open = true; } } } if ($this->shouldApplyInitialEffects($object, $xactions)) { $this->applyInitialEffects($object, $xactions); } foreach ($xactions as $xaction) { $this->adjustTransactionValues($object, $xaction); } $xactions = $this->filterTransactions($object, $xactions); if (!$xactions) { if ($read_locking) { $object->endReadLocking(); $read_locking = false; } if ($transaction_open) { $object->killTransaction(); $transaction_open = false; } return array(); } // Now that we've merged, filtered, and combined transactions, check for // required capabilities. foreach ($xactions as $xaction) { $this->requireCapabilities($object, $xaction); } $xactions = $this->sortTransactions($xactions); if ($is_preview) { $this->loadHandles($xactions); return $xactions; } $comment_editor = id(new PhabricatorApplicationTransactionCommentEditor())->setActor($actor)->setActingAsPHID($this->getActingAsPHID())->setContentSource($this->getContentSource()); if (!$transaction_open) { $object->openTransaction(); } foreach ($xactions as $xaction) { $this->applyInternalEffects($object, $xaction); } $object->save(); foreach ($xactions as $xaction) { $xaction->setObjectPHID($object->getPHID()); if ($xaction->getComment()) { $xaction->setPHID($xaction->generatePHID()); $comment_editor->applyEdit($xaction, $xaction->getComment()); } else { $xaction->save(); } } if ($file_phids) { $this->attachFiles($object, $file_phids); } foreach ($xactions as $xaction) { $this->applyExternalEffects($object, $xaction); } $xactions = $this->applyFinalEffects($object, $xactions); if ($read_locking) { $object->endReadLocking(); $read_locking = false; } $object->saveTransaction(); // Now that we've completely applied the core transaction set, try to apply // Herald rules. Herald rules are allowed to either take direct actions on // the database (like writing flags), or take indirect actions (like saving // some targets for CC when we generate mail a little later), or return // transactions which we'll apply normally using another Editor. // First, check if *this* is a sub-editor which is itself applying Herald // rules: if it is, stop working and return so we don't descend into // madness. // Otherwise, we're not a Herald editor, so process Herald rules (possibly // using a Herald editor to apply resulting transactions) and then send out // mail, notifications, and feed updates about everything. if ($this->getIsHeraldEditor()) { // We are the Herald editor, so stop work here and return the updated // transactions. return $xactions; } else { if ($this->shouldApplyHeraldRules($object, $xactions)) { // We are not the Herald editor, so try to apply Herald rules. $herald_xactions = $this->applyHeraldRules($object, $xactions); if ($herald_xactions) { $xscript_id = $this->getHeraldTranscript()->getID(); foreach ($herald_xactions as $herald_xaction) { $herald_xaction->setMetadataValue('herald:transcriptID', $xscript_id); } // NOTE: We're acting as the omnipotent user because rules deal with // their own policy issues. We use a synthetic author PHID (the // Herald application) as the author of record, so that transactions // will render in a reasonable way ("Herald assigned this task ..."). $herald_actor = PhabricatorUser::getOmnipotentUser(); $herald_phid = id(new PhabricatorHeraldApplication())->getPHID(); // TODO: It would be nice to give transactions a more specific source // which points at the rule which generated them. You can figure this // out from transcripts, but it would be cleaner if you didn't have to. $herald_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_HERALD, array()); $herald_editor = newv(get_class($this), array())->setContinueOnNoEffect(true)->setContinueOnMissingFields(true)->setParentMessageID($this->getParentMessageID())->setIsHeraldEditor(true)->setActor($herald_actor)->setActingAsPHID($herald_phid)->setContentSource($herald_source); $herald_xactions = $herald_editor->applyTransactions($object, $herald_xactions); // Merge the new transactions into the transaction list: we want to // send email and publish feed stories about them, too. $xactions = array_merge($xactions, $herald_xactions); } } } // Before sending mail or publishing feed stories, reload the object // subscribers to pick up changes caused by Herald (or by other side effects // in various transaction phases). $this->loadSubscribers($object); $this->loadHandles($xactions); $mail = null; if (!$this->getDisableEmail()) { if ($this->shouldSendMail($object, $xactions)) { $mail = $this->sendMail($object, $xactions); } } if ($this->supportsSearch()) { id(new PhabricatorSearchIndexer())->queueDocumentForIndexing($object->getPHID()); } if ($this->shouldPublishFeedStory($object, $xactions)) { $mailed = array(); if ($mail) { $mailed = $mail->buildRecipientList(); } $this->publishFeedStory($object, $xactions, $mailed); } $this->didApplyTransactions($xactions); if ($object instanceof PhabricatorCustomFieldInterface) { // Maybe this makes more sense to move into the search index itself? For // now I'm putting it here since I think we might end up with things that // need it to be up to date once the next page loads, but if we don't go // there we we could move it into search once search moves to the daemons. // It now happens in the search indexer as well, but the search indexer is // always daemonized, so the logic above still potentially holds. We could // possibly get rid of this. The major motivation for putting it in the // indexer was to enable reindexing to work. $fields = PhabricatorCustomField::getObjectFields($object, PhabricatorCustomField::ROLE_APPLICATIONSEARCH); $fields->readFieldsFromStorage($object); $fields->rebuildIndexes($object); } return $xactions; }
public function didParseCommit(PhabricatorRepository $repo, PhabricatorRepositoryCommit $commit, PhabricatorRepositoryCommitData $data) { // NOTE: This is currently dead code. See T2222. $releeph_requests = $this->loadReleephRequests(); if (!$releeph_requests) { return; } $releeph_branch = head($releeph_requests)->getBranch(); if (!$this->isCommitOnBranch($repo, $commit, $releeph_branch)) { return; } foreach ($releeph_requests as $releeph_request) { if ($this->releephAction === self::ACTION_PICKS) { $action = 'pick'; } else { $action = 'revert'; } $actor_phid = coalesce($data->getCommitDetail('committerPHID'), $data->getCommitDetail('authorPHID')); $actor = id(new PhabricatorUser())->loadOneWhere('phid = %s', $actor_phid); $xactions = array(); $xactions[] = id(new ReleephRequestTransaction())->setTransactionType(ReleephRequestTransaction::TYPE_DISCOVERY)->setMetadataValue('action', $action)->setMetadataValue('authorPHID', $data->getCommitDetail('authorPHID'))->setMetadataValue('committerPHID', $data->getCommitDetail('committerPHID'))->setNewValue($commit->getPHID()); $editor = id(new ReleephRequestTransactionalEditor())->setActor($actor)->setContinueOnNoEffect(true)->setContentSource(PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_UNKNOWN, array())); $editor->applyTransactions($releeph_request, $xactions); } }
public function getTransactionCommentForSave() { $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_LEGACY, array()); $this->proxy->setViewPolicy('public')->setEditPolicy($this->getAuthorPHID())->setContentSource($content_source)->setCommentVersion(1); return $this->proxy; }
<?php $conn_w = id(new DifferentialRevision())->establishConnection('w'); $rows = new LiskRawMigrationIterator($conn_w, 'differential_comment'); $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_LEGACY, array())->serialize(); echo pht('Migrating Differential comment text to modern storage...') . "\n"; foreach ($rows as $row) { $id = $row['id']; echo pht('Migrating Differential comment %d...', $id) . "\n"; if (!strlen($row['content'])) { echo pht('Comment has no text, continuing.') . "\n"; continue; } $revision = id(new DifferentialRevision())->load($row['revisionID']); if (!$revision) { echo pht('Comment has no valid revision, continuing.') . "\n"; continue; } $revision_phid = $revision->getPHID(); $dst_table = 'differential_inline_comment'; $xaction_phid = PhabricatorPHID::generateNewPHID(PhabricatorApplicationTransactionTransactionPHIDType::TYPECONST, DifferentialRevisionPHIDType::TYPECONST); $comment_phid = PhabricatorPHID::generateNewPHID(PhabricatorPHIDConstants::PHID_TYPE_XCMT, DifferentialRevisionPHIDType::TYPECONST); queryfx($conn_w, 'INSERT IGNORE INTO %T (phid, transactionPHID, authorPHID, viewPolicy, editPolicy, commentVersion, content, contentSource, isDeleted, dateCreated, dateModified, revisionPHID, changesetID, legacyCommentID) VALUES (%s, %s, %s, %s, %s, %d, %s, %s, %d, %d, %d, %s, %nd, %d)', 'differential_transaction_comment', $comment_phid, $xaction_phid, $row['authorPHID'], 'public', $row['authorPHID'], 1, $row['content'], $content_source, 0, $row['dateCreated'], $row['dateModified'], $revision_phid, null, $row['id']);