protected function buildAbstractDocumentByPHID($phid) { $commit = $this->loadDocumentByPHID($phid); $commit_data = id(new PhabricatorRepositoryCommitData())->loadOneWhere('commitID = %d', $commit->getID()); $date_created = $commit->getEpoch(); $commit_message = $commit_data->getCommitMessage(); $author_phid = $commit_data->getCommitDetail('authorPHID'); $repository = id(new PhabricatorRepositoryQuery())->setViewer($this->getViewer())->withIDs(array($commit->getRepositoryID()))->executeOne(); if (!$repository) { throw new Exception('No such repository!'); } $title = 'r' . $repository->getCallsign() . $commit->getCommitIdentifier() . ' ' . $commit_data->getSummary(); $doc = new PhabricatorSearchAbstractDocument(); $doc->setPHID($commit->getPHID()); $doc->setDocumentType(PhabricatorRepositoryCommitPHIDType::TYPECONST); $doc->setDocumentCreated($date_created); $doc->setDocumentModified($date_created); $doc->setDocumentTitle($title); $doc->addField(PhabricatorSearchField::FIELD_BODY, $commit_message); if ($author_phid) { $doc->addRelationship(PhabricatorSearchRelationship::RELATIONSHIP_AUTHOR, $author_phid, PhabricatorPeopleUserPHIDType::TYPECONST, $date_created); } $project_phids = PhabricatorEdgeQuery::loadDestinationPHIDs($commit->getPHID(), PhabricatorEdgeConfig::TYPE_COMMIT_HAS_PROJECT); if ($project_phids) { foreach ($project_phids as $project_phid) { $doc->addRelationship(PhabricatorSearchRelationship::RELATIONSHIP_PROJECT, $project_phid, PhabricatorProjectProjectPHIDType::TYPECONST, $date_created); } } $doc->addRelationship(PhabricatorSearchRelationship::RELATIONSHIP_REPOSITORY, $repository->getPHID(), PhabricatorRepositoryRepositoryPHIDType::TYPECONST, $date_created); $this->indexTransactions($doc, new PhabricatorAuditTransactionQuery(), array($commit->getPHID())); return $doc; }
private function handleHovercardEvent($event) { $viewer = $event->getUser(); $hovercard = $event->getValue('hovercard'); $object_handle = $event->getValue('handle'); $commit = $event->getValue('object'); if (!$commit instanceof PhabricatorRepositoryCommit) { return; } $commit_data = $commit->loadCommitData(); $revision = PhabricatorEdgeQuery::loadDestinationPHIDs($commit->getPHID(), PhabricatorEdgeConfig::TYPE_COMMIT_HAS_DREV); $revision = reset($revision); $author = $commit->getAuthorPHID(); $phids = array_filter(array($revision, $author)); $handles = id(new PhabricatorHandleQuery())->setViewer($viewer)->withPHIDs($phids)->execute(); if ($author) { $author = $handles[$author]->renderLink(); } else { $author = phutil_tag('em', array(), $commit_data->getAuthorName()); } $hovercard->setTitle($object_handle->getName()); $hovercard->setDetail($commit->getSummary()); $hovercard->addField(pht('Author'), $author); $hovercard->addField(pht('Date'), phabricator_date($commit->getEpoch(), $viewer)); if ($commit->getAuditStatus() != PhabricatorAuditCommitStatusConstants::NONE) { $hovercard->addField(pht('Audit Status'), PhabricatorAuditCommitStatusConstants::getStatusName($commit->getAuditStatus())); } if ($revision) { $rev_handle = $handles[$revision]; $hovercard->addField(pht('Revision'), $rev_handle->renderLink()); } $event->setValue('hovercard', $hovercard); }
private function performMerge(ManiphestTask $task, PhabricatorObjectHandle $handle, array $phids) { $user = $this->getRequest()->getUser(); $response = id(new AphrontReloadResponse())->setURI($handle->getURI()); $phids = array_fill_keys($phids, true); unset($phids[$task->getPHID()]); // Prevent merging a task into itself. if (!$phids) { return $response; } $targets = id(new ManiphestTaskQuery())->setViewer($user)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->withPHIDs(array_keys($phids))->needSubscriberPHIDs(true)->needProjectPHIDs(true)->execute(); if (empty($targets)) { return $response; } $editor = id(new ManiphestTransactionEditor())->setActor($user)->setContentSourceFromRequest($this->getRequest())->setContinueOnNoEffect(true)->setContinueOnMissingFields(true); $cc_vector = array(); // since we loaded this via a generic object query, go ahead and get the // attach the subscriber and project phids now $task->attachSubscriberPHIDs(PhabricatorSubscribersQuery::loadSubscribersForPHID($task->getPHID())); $task->attachProjectPHIDs(PhabricatorEdgeQuery::loadDestinationPHIDs($task->getPHID(), PhabricatorProjectObjectHasProjectEdgeType::EDGECONST)); $cc_vector[] = $task->getSubscriberPHIDs(); foreach ($targets as $target) { $cc_vector[] = $target->getSubscriberPHIDs(); $cc_vector[] = array($target->getAuthorPHID(), $target->getOwnerPHID()); $merged_into_txn = id(new ManiphestTransaction())->setTransactionType(ManiphestTransaction::TYPE_MERGED_INTO)->setNewValue($task->getPHID()); $editor->applyTransactions($target, array($merged_into_txn)); } $all_ccs = array_mergev($cc_vector); $all_ccs = array_filter($all_ccs); $all_ccs = array_unique($all_ccs); $add_ccs = id(new ManiphestTransaction())->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS)->setNewValue(array('=' => $all_ccs)); $merged_from_txn = id(new ManiphestTransaction())->setTransactionType(ManiphestTransaction::TYPE_MERGED_FROM)->setNewValue(mpull($targets, 'getPHID')); $editor->applyTransactions($task, array($add_ccs, $merged_from_txn)); return $response; }
protected function processDiffusionRequest(AphrontRequest $request) { $user = $request->getUser(); $drequest = $this->getDiffusionRequest(); $callsign = $drequest->getRepository()->getCallsign(); $repository = $drequest->getRepository(); $commit = $drequest->loadCommit(); $data = $commit->loadCommitData(); $page_title = pht('Edit Diffusion Commit'); if (!$commit) { return new Aphront404Response(); } $commit_phid = $commit->getPHID(); $edge_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST; $current_proj_phids = PhabricatorEdgeQuery::loadDestinationPHIDs($commit_phid, $edge_type); if ($request->isFormPost()) { $xactions = array(); $proj_phids = $request->getArr('projects'); $xactions[] = id(new PhabricatorAuditTransaction())->setTransactionType(PhabricatorTransactions::TYPE_EDGE)->setMetadataValue('edge:type', $edge_type)->setNewValue(array('=' => array_fuse($proj_phids))); $editor = id(new PhabricatorAuditEditor())->setActor($user)->setContinueOnNoEffect(true)->setContentSourceFromRequest($request); $xactions = $editor->applyTransactions($commit, $xactions); return id(new AphrontRedirectResponse())->setURI('/r' . $callsign . $commit->getCommitIdentifier()); } $tokenizer_id = celerity_generate_unique_node_id(); $form = id(new AphrontFormView())->setUser($user)->setAction($request->getRequestURI()->getPath())->appendControl(id(new AphrontFormTokenizerControl())->setLabel(pht('Projects'))->setName('projects')->setValue($current_proj_phids)->setID($tokenizer_id)->setCaption(javelin_tag('a', array('href' => '/project/create/', 'mustcapture' => true, 'sigil' => 'project-create'), pht('Create New Project')))->setDatasource(new PhabricatorProjectDatasource())); $reason = $data->getCommitDetail('autocloseReason', false); $reason = PhabricatorRepository::BECAUSE_AUTOCLOSE_FORCED; if ($reason !== false) { switch ($reason) { case PhabricatorRepository::BECAUSE_REPOSITORY_IMPORTING: $desc = pht('No, Repository Importing'); break; case PhabricatorRepository::BECAUSE_AUTOCLOSE_DISABLED: $desc = pht('No, Autoclose Disabled'); break; case PhabricatorRepository::BECAUSE_NOT_ON_AUTOCLOSE_BRANCH: $desc = pht('No, Not On Autoclose Branch'); break; case PhabricatorRepository::BECAUSE_AUTOCLOSE_FORCED: $desc = pht('Yes, Forced Via bin/repository CLI Tool.'); break; case null: $desc = pht('Yes'); break; default: $desc = pht('Unknown'); break; } $doc_href = PhabricatorEnv::getDoclink('Diffusion User Guide: Autoclose'); $doc_link = phutil_tag('a', array('href' => $doc_href, 'target' => '_blank'), pht('Learn More')); $form->appendChild(id(new AphrontFormMarkupControl())->setLabel(pht('Autoclose?'))->setValue(array($desc, " ยท ", $doc_link))); } Javelin::initBehavior('project-create', array('tokenizerID' => $tokenizer_id)); $submit = id(new AphrontFormSubmitControl())->setValue(pht('Save'))->addCancelButton('/r' . $callsign . $commit->getCommitIdentifier()); $form->appendChild($submit); $crumbs = $this->buildCrumbs(array('commit' => true)); $crumbs->addTextCrumb(pht('Edit')); $form_box = id(new PHUIObjectBoxView())->setHeaderText($page_title)->setForm($form); return $this->buildApplicationPage(array($crumbs, $form_box), array('title' => $page_title)); }
protected function readValueFromRevision(DifferentialRevision $revision) { if (!$revision->getPHID()) { return array(); } return PhabricatorEdgeQuery::loadDestinationPHIDs($revision->getPHID(), DifferentialRevisionHasTaskEdgeType::EDGECONST); }
public static function loadForRevision($revision) { $app_legalpad = 'PhabricatorLegalpadApplication'; if (!PhabricatorApplication::isClassInstalled($app_legalpad)) { return array(); } if (!$revision->getPHID()) { return array(); } $phids = PhabricatorEdgeQuery::loadDestinationPHIDs($revision->getPHID(), LegalpadObjectNeedsSignatureEdgeType::EDGECONST); if ($phids) { // NOTE: We're bypassing permissions to pull these. We have to expose // some information about signature status in order to implement this // field meaningfully (otherwise, we could not tell reviewers that they // can't accept the revision yet), but that's OK because the only way to // require signatures is with a "Global" Herald rule, which requires a // high level of access. $signatures = id(new LegalpadDocumentSignatureQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withDocumentPHIDs($phids)->withSignerPHIDs(array($revision->getAuthorPHID()))->execute(); $signatures = mpull($signatures, null, 'getDocumentPHID'); $phids = array_fuse($phids); foreach ($phids as $phid) { $phids[$phid] = isset($signatures[$phid]); } } return $phids; }
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(); $user = $request->getUser(); if ($this->id) { $question = id(new PonderQuestionQuery())->setViewer($user)->withIDs(array($this->id))->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne(); if (!$question) { return new Aphront404Response(); } $v_projects = PhabricatorEdgeQuery::loadDestinationPHIDs($question->getPHID(), PhabricatorProjectObjectHasProjectEdgeType::EDGECONST); $v_projects = array_reverse($v_projects); } else { $question = id(new PonderQuestion())->setStatus(PonderQuestionStatus::STATUS_OPEN)->setAuthorPHID($user->getPHID())->setVoteCount(0)->setAnswerCount(0)->setHeat(0.0); $v_projects = array(); } $v_title = $question->getTitle(); $v_content = $question->getContent(); $errors = array(); $e_title = true; if ($request->isFormPost()) { $v_title = $request->getStr('title'); $v_content = $request->getStr('content'); $v_projects = $request->getArr('projects'); $len = phutil_utf8_strlen($v_title); 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) { $template = id(new PonderQuestionTransaction()); $xactions = array(); $xactions[] = id(clone $template)->setTransactionType(PonderQuestionTransaction::TYPE_TITLE)->setNewValue($v_title); $xactions[] = id(clone $template)->setTransactionType(PonderQuestionTransaction::TYPE_CONTENT)->setNewValue($v_content); $proj_edge_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST; $xactions[] = id(new PonderQuestionTransaction())->setTransactionType(PhabricatorTransactions::TYPE_EDGE)->setMetadataValue('edge:type', $proj_edge_type)->setNewValue(array('=' => array_fuse($v_projects))); $editor = id(new PonderQuestionEditor())->setActor($user)->setContentSourceFromRequest($request)->setContinueOnNoEffect(true); $editor->applyTransactions($question, $xactions); return id(new AphrontRedirectResponse())->setURI('/Q' . $question->getID()); } } $form = id(new AphrontFormView())->setUser($user)->appendChild(id(new AphrontFormTextControl())->setLabel(pht('Question'))->setName('title')->setValue($v_title)->setError($e_title))->appendChild(id(new PhabricatorRemarkupControl())->setUser($user)->setName('content')->setID('content')->setValue($v_content)->setLabel(pht('Description'))->setUser($user)); $form->appendControl(id(new AphrontFormTokenizerControl())->setLabel(pht('Projects'))->setName('projects')->setValue($v_projects)->setDatasource(new PhabricatorProjectDatasource())); $form->appendChild(id(new AphrontFormSubmitControl())->addCancelButton($this->getApplicationURI())->setValue(pht('Ask Away!'))); $preview = id(new PHUIRemarkupPreviewPanel())->setHeader(pht('Question Preview'))->setControlID('content')->setPreviewURI($this->getApplicationURI('preview/')); $form_box = id(new PHUIObjectBoxView())->setHeaderText(pht('Ask New Question'))->setFormErrors($errors)->setForm($form); $crumbs = $this->buildApplicationCrumbs(); $id = $question->getID(); if ($id) { $crumbs->addTextCrumb("Q{$id}", "/Q{$id}"); $crumbs->addTextCrumb(pht('Edit')); } else { $crumbs->addTextCrumb(pht('Ask Question')); } return $this->buildApplicationPage(array($crumbs, $form_box, $preview), array('title' => pht('Ask New Question'))); }
public function save() { if (!$this->object) { throw new PhutilInvalidStateException('setObject'); } $actor = $this->requireActor(); $src = $this->object->getPHID(); if ($this->implicitSubscribePHIDs) { $unsub = PhabricatorEdgeQuery::loadDestinationPHIDs($src, PhabricatorObjectHasUnsubscriberEdgeType::EDGECONST); $unsub = array_fill_keys($unsub, true); $this->implicitSubscribePHIDs = array_diff_key($this->implicitSubscribePHIDs, $unsub); } $add = $this->implicitSubscribePHIDs + $this->explicitSubscribePHIDs; $del = $this->unsubscribePHIDs; // If a PHID is marked for both subscription and unsubscription, treat // unsubscription as the stronger action. $add = array_diff_key($add, $del); if ($add || $del) { $u_type = PhabricatorObjectHasUnsubscriberEdgeType::EDGECONST; $s_type = PhabricatorObjectHasSubscriberEdgeType::EDGECONST; $editor = new PhabricatorEdgeEditor(); foreach ($add as $phid => $ignored) { $editor->removeEdge($src, $u_type, $phid); $editor->addEdge($src, $s_type, $phid); } foreach ($del as $phid => $ignored) { $editor->removeEdge($src, $s_type, $phid); $editor->addEdge($src, $u_type, $phid); } $editor->save(); } }
public function save() { if (!$this->object) { throw new Exception('Call setObject() before save()!'); } $actor = $this->requireActor(); $src = $this->object->getPHID(); if ($this->implicitSubscribePHIDs) { $unsub = PhabricatorEdgeQuery::loadDestinationPHIDs($src, PhabricatorEdgeConfig::TYPE_OBJECT_HAS_UNSUBSCRIBER); $unsub = array_fill_keys($unsub, true); $this->implicitSubscribePHIDs = array_diff_key($this->implicitSubscribePHIDs, $unsub); } $add = $this->implicitSubscribePHIDs + $this->explicitSubscribePHIDs; $del = $this->unsubscribePHIDs; // If a PHID is marked for both subscription and unsubscription, treat // unsubscription as the stronger action. $add = array_diff_key($add, $del); if ($add || $del) { $u_type = PhabricatorEdgeConfig::TYPE_OBJECT_HAS_UNSUBSCRIBER; $s_type = PhabricatorEdgeConfig::TYPE_OBJECT_HAS_SUBSCRIBER; $editor = new PhabricatorEdgeEditor(); foreach ($add as $phid => $ignored) { $editor->removeEdge($src, $u_type, $phid); $editor->addEdge($src, $s_type, $phid); } foreach ($del as $phid => $ignored) { $editor->removeEdge($src, $s_type, $phid); $editor->addEdge($src, $u_type, $phid); } $editor->save(); } }
public function getHeraldFieldValue($object) { $repository = $this->getAdapter()->loadRepository(); if (!$repository) { return array(); } return PhabricatorEdgeQuery::loadDestinationPHIDs($repository->getPHID(), PhabricatorProjectObjectHasProjectEdgeType::EDGECONST); }
private function getDependentRevisionPHIDs() { $requested_object = $this->getObject()->getRequestedObjectPHID(); if (!$requested_object instanceof DifferentialRevision) { return array(); } $revision = $requested_object; return PhabricatorEdgeQuery::loadDestinationPHIDs($revision->getPHID(), PhabricatorEdgeConfig::TYPE_DREV_DEPENDS_ON_DREV); }
private function getDependentRevisionPHIDs() { $requested_object = $this->getObject()->getRequestedObjectPHID(); if (!$requested_object instanceof DifferentialRevision) { return array(); } $revision = $requested_object; return PhabricatorEdgeQuery::loadDestinationPHIDs($revision->getPHID(), DifferentialRevisionDependsOnRevisionEdgeType::EDGECONST); }
public function handleRequest(AphrontRequest $request) { $response = $this->loadDiffusionContextForEdit(); if ($response) { return $response; } $viewer = $request->getUser(); $drequest = $this->getDiffusionRequest(); $repository = $drequest->getRepository(); $edit_uri = $this->getRepositoryControllerURI($repository, 'edit/'); $v_name = $repository->getName(); $v_desc = $repository->getDetail('description'); $v_slug = $repository->getRepositorySlug(); $v_projects = PhabricatorEdgeQuery::loadDestinationPHIDs($repository->getPHID(), PhabricatorProjectObjectHasProjectEdgeType::EDGECONST); $e_name = true; $e_slug = null; $errors = array(); $validation_exception = null; if ($request->isFormPost()) { $v_name = $request->getStr('name'); $v_desc = $request->getStr('description'); $v_projects = $request->getArr('projectPHIDs'); $v_slug = $request->getStr('slug'); if (!strlen($v_name)) { $e_name = pht('Required'); $errors[] = pht('Repository name is required.'); } else { $e_name = null; } if (!$errors) { $xactions = array(); $template = id(new PhabricatorRepositoryTransaction()); $type_name = PhabricatorRepositoryTransaction::TYPE_NAME; $type_desc = PhabricatorRepositoryTransaction::TYPE_DESCRIPTION; $type_edge = PhabricatorTransactions::TYPE_EDGE; $type_slug = PhabricatorRepositoryTransaction::TYPE_SLUG; $xactions[] = id(clone $template)->setTransactionType($type_name)->setNewValue($v_name); $xactions[] = id(clone $template)->setTransactionType($type_desc)->setNewValue($v_desc); $xactions[] = id(clone $template)->setTransactionType($type_slug)->setNewValue($v_slug); $xactions[] = id(clone $template)->setTransactionType($type_edge)->setMetadataValue('edge:type', PhabricatorProjectObjectHasProjectEdgeType::EDGECONST)->setNewValue(array('=' => array_fuse($v_projects))); $editor = id(new PhabricatorRepositoryEditor())->setContinueOnNoEffect(true)->setContentSourceFromRequest($request)->setActor($viewer); try { $editor->applyTransactions($repository, $xactions); return id(new AphrontRedirectResponse())->setURI($edit_uri); } catch (PhabricatorApplicationTransactionValidationException $ex) { $validation_exception = $ex; $e_slug = $ex->getShortMessage($type_slug); } } } $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('Edit Basics')); $title = pht('Edit %s', $repository->getName()); $form = id(new AphrontFormView())->setUser($viewer)->appendChild(id(new AphrontFormTextControl())->setName('name')->setLabel(pht('Name'))->setValue($v_name)->setError($e_name))->appendChild(id(new AphrontFormTextControl())->setName('slug')->setLabel(pht('Short Name'))->setValue($v_slug)->setError($e_slug))->appendChild(id(new PhabricatorRemarkupControl())->setUser($viewer)->setName('description')->setLabel(pht('Description'))->setValue($v_desc))->appendControl(id(new AphrontFormTokenizerControl())->setDatasource(new PhabricatorProjectDatasource())->setName('projectPHIDs')->setLabel(pht('Projects'))->setValue($v_projects))->appendChild(id(new AphrontFormSubmitControl())->setValue(pht('Save'))->addCancelButton($edit_uri))->appendChild(id(new PHUIFormDividerControl()))->appendRemarkupInstructions($this->getReadmeInstructions()); $object_box = id(new PHUIObjectBoxView())->setHeaderText($title)->setValidationException($validation_exception)->setForm($form)->setFormErrors($errors); return $this->newPage()->setTitle($title)->setCrumbs($crumbs)->appendChild($object_box); }
protected function readValueFromRevision(DifferentialRevision $revision) { if (!$revision->getPHID()) { return array(); } $projects = PhabricatorEdgeQuery::loadDestinationPHIDs($revision->getPHID(), PhabricatorProjectObjectHasProjectEdgeType::EDGECONST); $projects = array_reverse($projects); return $projects; }
private function handlePropertyEvent($event) { $user = $event->getUser(); $object = $event->getValue('object'); if (!$object || !$object->getPHID()) { // No object, or the object has no PHID yet.. return; } if (!$object instanceof PhabricatorProjectInterface) { // This object doesn't have projects. return; } $project_phids = PhabricatorEdgeQuery::loadDestinationPHIDs($object->getPHID(), PhabricatorProjectObjectHasProjectEdgeType::EDGECONST); if ($project_phids) { $project_phids = array_reverse($project_phids); $handles = id(new PhabricatorHandleQuery())->setViewer($user)->withPHIDs($project_phids)->execute(); } else { $handles = array(); } // If this object can appear on boards, build the workboard annotations. // Some day, this might be a generic interface. For now, only tasks can // appear on boards. $can_appear_on_boards = $object instanceof ManiphestTask; $annotations = array(); if ($handles && $can_appear_on_boards) { // TDOO: Generalize this UI and move it out of Maniphest. require_celerity_resource('maniphest-task-summary-css'); $positions_query = id(new PhabricatorProjectColumnPositionQuery())->setViewer($user)->withBoardPHIDs($project_phids)->withObjectPHIDs(array($object->getPHID()))->needColumns(true); // This is important because positions will be created "on demand" // based on the set of columns. If we don't specify it, positions // won't be created. $columns = id(new PhabricatorProjectColumnQuery())->setViewer($user)->withProjectPHIDs($project_phids)->execute(); if ($columns) { $positions_query->withColumns($columns); } $positions = $positions_query->execute(); $positions = mpull($positions, null, 'getBoardPHID'); foreach ($project_phids as $project_phid) { $handle = $handles[$project_phid]; $position = idx($positions, $project_phid); if ($position) { $column = $position->getColumn(); $column_name = pht('(%s)', $column->getDisplayName()); $column_link = phutil_tag('a', array('href' => $handle->getURI() . 'board/', 'class' => 'maniphest-board-link'), $column_name); $annotations[$project_phid] = array(' ', $column_link); } } } if ($handles) { $list = id(new PHUIHandleTagListView())->setHandles($handles)->setAnnotations($annotations); } else { $list = phutil_tag('em', array(), pht('None')); } $view = $event->getValue('view'); $view->addProperty(pht('Projects'), $list); }
protected function indexProjects(PhabricatorSearchAbstractDocument $doc, PhabricatorProjectInterface $object) { $project_phids = PhabricatorEdgeQuery::loadDestinationPHIDs($object->getPHID(), PhabricatorProjectObjectHasProjectEdgeType::EDGECONST); if ($project_phids) { foreach ($project_phids as $project_phid) { $doc->addRelationship(PhabricatorSearchRelationship::RELATIONSHIP_PROJECT, $project_phid, PhabricatorProjectProjectPHIDType::TYPECONST, $doc->getDocumentModified()); // Bogus timestamp. } } }
public function fromPartial($partial_string) { $this->objectPHID = null; // Look for diffs $matches = array(); if (preg_match('/^D([1-9]\\d*)$/', $partial_string, $matches)) { $diff_id = $matches[1]; $diff_rev = id(new DifferentialRevisionQuery())->setViewer($this->getUser())->withIDs(array($diff_id))->needCommitPHIDs(true)->executeOne(); if (!$diff_rev) { throw new ReleephCommitFinderException(pht('%s does not refer to an existing diff.', $partial_string)); } $commit_phids = $diff_rev->getCommitPHIDs(); if (!$commit_phids) { throw new ReleephCommitFinderException(pht('%s has no commits associated with it yet.', $partial_string)); } $this->objectPHID = $diff_rev->getPHID(); $commits = id(new DiffusionCommitQuery())->setViewer($this->getUser())->withPHIDs($commit_phids)->execute(); $commits = msort($commits, 'getEpoch'); return head($commits); } // Look for a raw commit number, or r<callsign><commit-number>. $repository = $this->releephProject->getRepository(); $dr_data = null; $matches = array(); if (preg_match('/^r(?P<callsign>[A-Z]+)(?P<commit>\\w+)$/', $partial_string, $matches)) { $callsign = $matches['callsign']; if ($callsign != $repository->getCallsign()) { throw new ReleephCommitFinderException(pht('%s is in a different repository to this Releeph project (%s).', $partial_string, $repository->getCallsign())); } else { $dr_data = $matches; } } else { $dr_data = array('callsign' => $repository->getCallsign(), 'commit' => $partial_string); } try { $dr_data['user'] = $this->getUser(); $dr = DiffusionRequest::newFromDictionary($dr_data); } catch (Exception $ex) { $message = pht('No commit matches %s: %s', $partial_string, $ex->getMessage()); throw new ReleephCommitFinderException($message); } $phabricator_repository_commit = $dr->loadCommit(); if (!$phabricator_repository_commit) { throw new ReleephCommitFinderException(pht("The commit %s doesn't exist in this repository.", $partial_string)); } // When requesting a single commit, if it has an associated review we // imply the review was requested instead. This is always correct for now // and consistent with the older behavior, although it might not be the // right rule in the future. $phids = PhabricatorEdgeQuery::loadDestinationPHIDs($phabricator_repository_commit->getPHID(), DiffusionCommitHasRevisionEdgeType::EDGECONST); if ($phids) { $this->objectPHID = head($phids); } return $phabricator_repository_commit; }
public function fromPartial($partial_string) { $this->objectPHID = null; // Look for diffs $matches = array(); if (preg_match('/^D([1-9]\\d*)$/', $partial_string, $matches)) { $diff_id = $matches[1]; // TOOD: (T603) This is all slated for annihilation. $diff_rev = id(new DifferentialRevision())->load($diff_id); if (!$diff_rev) { throw new ReleephCommitFinderException("{$partial_string} does not refer to an existing diff."); } $commit_phids = $diff_rev->loadCommitPHIDs(); if (!$commit_phids) { throw new ReleephCommitFinderException("{$partial_string} has no commits associated with it yet."); } $this->objectPHID = $diff_rev->getPHID(); $commits = id(new PhabricatorRepositoryCommit())->loadAllWhere('phid IN (%Ls) ORDER BY epoch ASC', $commit_phids); return head($commits); } // Look for a raw commit number, or r<callsign><commit-number>. $repository = $this->releephProject->getRepository(); $dr_data = null; $matches = array(); if (preg_match('/^r(?P<callsign>[A-Z]+)(?P<commit>\\w+)$/', $partial_string, $matches)) { $callsign = $matches['callsign']; if ($callsign != $repository->getCallsign()) { throw new ReleephCommitFinderException(sprintf('%s is in a different repository to this Releeph project (%s).', $partial_string, $repository->getCallsign())); } else { $dr_data = $matches; } } else { $dr_data = array('callsign' => $repository->getCallsign(), 'commit' => $partial_string); } try { $dr_data['user'] = $this->getUser(); $dr = DiffusionRequest::newFromDictionary($dr_data); } catch (Exception $ex) { $message = "No commit matches {$partial_string}: " . $ex->getMessage(); throw new ReleephCommitFinderException($message); } $phabricator_repository_commit = $dr->loadCommit(); if (!$phabricator_repository_commit) { throw new ReleephCommitFinderException("The commit {$partial_string} doesn't exist in this repository."); } // When requesting a single commit, if it has an associated review we // imply the review was requested instead. This is always correct for now // and consistent with the older behavior, although it might not be the // right rule in the future. $phids = PhabricatorEdgeQuery::loadDestinationPHIDs($phabricator_repository_commit->getPHID(), PhabricatorEdgeConfig::TYPE_COMMIT_HAS_DREV); if ($phids) { $this->objectPHID = head($phids); } return $phabricator_repository_commit; }
public function indexFulltextObject($object, PhabricatorSearchAbstractDocument $document) { $project_phids = PhabricatorEdgeQuery::loadDestinationPHIDs($object->getPHID(), PhabricatorProjectObjectHasProjectEdgeType::EDGECONST); if (!$project_phids) { return; } foreach ($project_phids as $project_phid) { $document->addRelationship(PhabricatorSearchRelationship::RELATIONSHIP_PROJECT, $project_phid, PhabricatorProjectProjectPHIDType::TYPECONST, $document->getDocumentModified()); // Bogus timestamp. } }
/** * Publishes stories into JIRA using the JIRA API. */ protected function publishFeedStory() { $story = $this->getFeedStory(); $viewer = $this->getViewer(); $provider = $this->getProvider(); $object = $this->getStoryObject(); $publisher = $this->getPublisher(); $jira_issue_phids = PhabricatorEdgeQuery::loadDestinationPHIDs($object->getPHID(), PhabricatorJiraIssueHasObjectEdgeType::EDGECONST); if (!$jira_issue_phids) { $this->log("%s\n", pht('Story is about an object with no linked JIRA issues.')); return; } $do_anything = $this->shouldPostComment() || $this->shouldPostLink(); if (!$do_anything) { $this->log("%s\n", pht('JIRA integration is configured not to post anything.')); return; } $xobjs = id(new DoorkeeperExternalObjectQuery())->setViewer($viewer)->withPHIDs($jira_issue_phids)->execute(); if (!$xobjs) { $this->log("%s\n", pht('Story object has no corresponding external JIRA objects.')); return; } $try_users = $this->findUsersToPossess(); if (!$try_users) { $this->log("%s\n", pht('No users to act on linked JIRA objects.')); return; } $xobjs = mgroup($xobjs, 'getApplicationDomain'); foreach ($xobjs as $domain => $xobj_list) { $accounts = id(new PhabricatorExternalAccountQuery())->setViewer($viewer)->withUserPHIDs($try_users)->withAccountTypes(array($provider->getProviderType()))->withAccountDomains(array($domain))->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->execute(); // Reorder accounts in the original order. // TODO: This needs to be adjusted if/when we allow you to link multiple // accounts. $accounts = mpull($accounts, null, 'getUserPHID'); $accounts = array_select_keys($accounts, $try_users); foreach ($xobj_list as $xobj) { foreach ($accounts as $account) { try { $jira_key = $xobj->getObjectID(); if ($this->shouldPostComment()) { $this->postComment($account, $jira_key); } if ($this->shouldPostLink()) { $this->postLink($account, $jira_key); } break; } catch (HTTPFutureResponseStatus $ex) { phlog($ex); $this->log("%s\n", pht('Failed to update object %s using user %s.', $xobj->getObjectID(), $account->getUserPHID())); } } } } }
public function loadBloggerPHIDs() { if (!$this->getPHID()) { return $this; } if ($this->bloggerPHIDs) { return $this; } $this->bloggerPHIDs = PhabricatorEdgeQuery::loadDestinationPHIDs($this->getPHID(), PhabricatorEdgeConfig::TYPE_BLOG_HAS_BLOGGER); return $this; }
public function processRequest() { $user = $this->getRequest()->getUser(); $phid = $user->getPHID(); $blog_phids = PhabricatorEdgeQuery::loadDestinationPHIDs($phid, PhabricatorEdgeConfig::TYPE_BLOGGER_HAS_BLOG); $blogs = id(new PhameBlogQuery())->withPHIDs($blog_phids)->needBloggers(true)->executeWithPager($this->getPager()); $this->setBlogs($blogs); $this->setPageTitle('My Blogs'); $this->setShowSideNav(true); return $this->buildBlogListPageResponse(); }
public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); $handle = id(new PhabricatorHandleQuery())->setViewer($user)->withPHIDs(array($this->phid))->executeOne(); $object_type = $handle->getType(); $attach_type = $this->type; $object = id(new PhabricatorObjectQuery())->setViewer($user)->withPHIDs(array($this->phid))->executeOne(); if (!$object) { return new Aphront404Response(); } $edge_type = null; switch ($this->action) { case self::ACTION_EDGE: case self::ACTION_DEPENDENCIES: case self::ACTION_BLOCKS: case self::ACTION_ATTACH: $edge_type = $this->getEdgeType($object_type, $attach_type); break; } if ($request->isFormPost()) { $phids = explode(';', $request->getStr('phids')); $phids = array_filter($phids); $phids = array_values($phids); if ($edge_type) { if (!$object instanceof PhabricatorApplicationTransactionInterface) { throw new Exception(pht('Expected object ("%s") to implement interface "%s".', get_class($object), 'PhabricatorApplicationTransactionInterface')); } $old_phids = PhabricatorEdgeQuery::loadDestinationPHIDs($this->phid, $edge_type); $add_phids = $phids; $rem_phids = array_diff($old_phids, $add_phids); $txn_editor = $object->getApplicationTransactionEditor()->setActor($user)->setContentSourceFromRequest($request)->setContinueOnMissingFields(true); $txn_template = $object->getApplicationTransactionTemplate()->setTransactionType(PhabricatorTransactions::TYPE_EDGE)->setMetadataValue('edge:type', $edge_type)->setNewValue(array('+' => array_fuse($add_phids), '-' => array_fuse($rem_phids))); $txn_editor->applyTransactions($object->getApplicationTransactionObject(), array($txn_template)); return id(new AphrontReloadResponse())->setURI($handle->getURI()); } else { return $this->performMerge($object, $handle, $phids); } } else { if ($edge_type) { $phids = PhabricatorEdgeQuery::loadDestinationPHIDs($this->phid, $edge_type); } else { // This is a merge. $phids = array(); } } $strings = $this->getStrings(); $handles = $this->loadViewerHandles($phids); $obj_dialog = new PhabricatorObjectSelectorDialog(); $obj_dialog->setUser($user)->setHandles($handles)->setFilters($this->getFilters($strings))->setSelectedFilter($strings['selected'])->setExcluded($this->phid)->setCancelURI($handle->getURI())->setSearchURI('/search/select/' . $attach_type . '/')->setTitle($strings['title'])->setHeader($strings['header'])->setButtonText($strings['button'])->setInstructions($strings['instructions']); $dialog = $obj_dialog->buildDialog(); return id(new AphrontDialogResponse())->setDialog($dialog); }
private function handlePropertyEvent($event) { $user = $event->getUser(); $object = $event->getValue('object'); if (!$object || !$object->getPHID()) { // No object, or the object has no PHID yet.. return; } if (!$object instanceof PhabricatorProjectInterface) { // This object doesn't have projects. return; } $project_phids = PhabricatorEdgeQuery::loadDestinationPHIDs($object->getPHID(), PhabricatorProjectObjectHasProjectEdgeType::EDGECONST); if ($project_phids) { $project_phids = array_reverse($project_phids); $handles = id(new PhabricatorHandleQuery())->setViewer($user)->withPHIDs($project_phids)->execute(); } else { $handles = array(); } // If this object can appear on boards, build the workboard annotations. // Some day, this might be a generic interface. For now, only tasks can // appear on boards. $can_appear_on_boards = $object instanceof ManiphestTask; $annotations = array(); if ($handles && $can_appear_on_boards) { $engine = id(new PhabricatorBoardLayoutEngine())->setViewer($user)->setBoardPHIDs($project_phids)->setObjectPHIDs(array($object->getPHID()))->executeLayout(); // TDOO: Generalize this UI and move it out of Maniphest. require_celerity_resource('maniphest-task-summary-css'); foreach ($project_phids as $project_phid) { $handle = $handles[$project_phid]; $columns = $engine->getObjectColumns($project_phid, $object->getPHID()); $annotation = array(); foreach ($columns as $column) { $project_id = $column->getProject()->getID(); $column_name = pht('(%s)', $column->getDisplayName()); $column_link = phutil_tag('a', array('href' => "/project/board/{$project_id}/", 'class' => 'maniphest-board-link'), $column_name); $annotation[] = $column_link; } if ($annotation) { $annotations[$project_phid] = array(' ', phutil_implode_html(', ', $annotation)); } } } if ($handles) { $list = id(new PHUIHandleTagListView())->setHandles($handles)->setAnnotations($annotations)->setShowHovercards(true); } else { $list = phutil_tag('em', array(), pht('None')); } $view = $event->getValue('view'); $view->addProperty(pht('Projects'), $list); }
public function getHeraldField($field) { switch ($field) { case self::FIELD_TITLE: return $this->getMock()->getName(); case self::FIELD_BODY: return $this->getMock()->getDescription(); case self::FIELD_AUTHOR: return $this->getMock()->getAuthorPHID(); case self::FIELD_PROJECTS: return PhabricatorEdgeQuery::loadDestinationPHIDs($this->getMock()->getPHID(), PhabricatorProjectObjectHasProjectEdgeType::EDGECONST); } return parent::getHeraldField($field); }
public function buildCustomEditFields(PhabricatorEditEngine $engine, PhabricatorApplicationTransactionInterface $object) { $edge_type = PhabricatorTransactions::TYPE_EDGE; $project_edge_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST; $object_phid = $object->getPHID(); if ($object_phid) { $project_phids = PhabricatorEdgeQuery::loadDestinationPHIDs($object_phid, $project_edge_type); $project_phids = array_reverse($project_phids); } else { $project_phids = array(); } $projects_field = id(new PhabricatorProjectsEditField())->setKey('projectPHIDs')->setLabel(pht('Projects'))->setEditTypeKey('projects')->setDescription(pht('Add or remove associated projects.'))->setAliases(array('project', 'projects'))->setIsCopyable(true)->setUseEdgeTransactions(true)->setEdgeTransactionDescriptions(pht('Add projects.'), pht('Remove projects.'), pht('Set associated projects, overwriting current value.'))->setCommentActionLabel(pht('Change Projects'))->setTransactionType($edge_type)->setMetadataValue('edge:type', $project_edge_type)->setValue($project_phids); return array($projects_field); }
public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); $mock = id(new PholioMockQuery())->setViewer($user)->withIDs(array($this->id))->needImages(true)->needInlineComments(true)->executeOne(); if (!$mock) { return new Aphront404Response(); } $xactions = id(new PholioTransactionQuery())->setViewer($user)->withObjectPHIDs(array($mock->getPHID()))->execute(); $phids = PhabricatorEdgeQuery::loadDestinationPHIDs($mock->getPHID(), PhabricatorEdgeConfig::TYPE_MOCK_HAS_TASK); $this->setManiphestTaskPHIDs($phids); $phids[] = $mock->getAuthorPHID(); $this->loadHandles($phids); $engine = id(new PhabricatorMarkupEngine())->setViewer($user); $engine->addObject($mock, PholioMock::MARKUP_FIELD_DESCRIPTION); foreach ($xactions as $xaction) { if ($xaction->getComment()) { $engine->addObject($xaction->getComment(), PhabricatorApplicationTransactionComment::MARKUP_FIELD_COMMENT); } } $engine->process(); $title = $mock->getName(); if ($mock->isClosed()) { $header_icon = 'fa-ban'; $header_name = pht('Closed'); $header_color = 'dark'; } else { $header_icon = 'fa-square-o'; $header_name = pht('Open'); $header_color = 'bluegrey'; } $header = id(new PHUIHeaderView())->setHeader($title)->setUser($user)->setStatus($header_icon, $header_color, $header_name)->setPolicyObject($mock); $actions = $this->buildActionView($mock); $properties = $this->buildPropertyView($mock, $engine, $actions); require_celerity_resource('pholio-css'); require_celerity_resource('pholio-inline-comments-css'); $comment_form_id = celerity_generate_unique_node_id(); $output = id(new PholioMockImagesView())->setRequestURI($request->getRequestURI())->setCommentFormID($comment_form_id)->setUser($user)->setMock($mock)->setImageID($this->imageID); $output = id(new PHUIObjectBoxView())->setHeaderText(pht('Image'))->appendChild($output); $xaction_view = id(new PholioTransactionView())->setUser($this->getRequest()->getUser())->setMock($mock)->setObjectPHID($mock->getPHID())->setTransactions($xactions)->setMarkupEngine($engine); $add_comment = $this->buildAddCommentView($mock, $comment_form_id); $crumbs = $this->buildApplicationCrumbs(); $crumbs->setActionList($actions); $crumbs->addTextCrumb('M' . $mock->getID(), '/M' . $mock->getID()); $object_box = id(new PHUIObjectBoxView())->setHeader($header)->addPropertyList($properties); $thumb_grid = id(new PholioMockThumbGridView())->setUser($user)->setMock($mock); $content = array($crumbs, $object_box, $output, $thumb_grid, $xaction_view, $add_comment); return $this->buildApplicationPage($content, array('title' => 'M' . $mock->getID() . ' ' . $title, 'pageObjects' => array($mock->getPHID()))); }
public function willApplyRules(PhabricatorUser $viewer, array $values, array $objects) { // We want to let the user see the object if they're a subscriber or // a member of any project which is a subscriber. Additionally, because // subscriber state is complex, we need to read hints passed from // the TransactionEditor to predict policy state after transactions apply. $viewer_phid = $viewer->getPHID(); if (!$viewer_phid) { return; } if (empty($this->subscribed[$viewer_phid])) { $this->subscribed[$viewer_phid] = array(); } // Load the project PHIDs the user is a member of. if (!isset($this->sourcePHIDs[$viewer_phid])) { $source_phids = PhabricatorEdgeQuery::loadDestinationPHIDs($viewer_phid, PhabricatorProjectMemberOfProjectEdgeType::EDGECONST); $source_phids[] = $viewer_phid; $this->sourcePHIDs[$viewer_phid] = $source_phids; } // Look for transaction hints. foreach ($objects as $key => $object) { $cache = $this->getTransactionHint($object); if ($cache === null) { // We don't have a hint for this object, so we'll deal with it below. continue; } // We have a hint, so use that as the source of truth. unset($objects[$key]); foreach ($this->sourcePHIDs[$viewer_phid] as $source_phid) { if (isset($cache[$source_phid])) { $this->subscribed[$viewer_phid][$object->getPHID()] = true; break; } } } $phids = mpull($objects, 'getPHID'); if (!$phids) { return; } $edge_query = id(new PhabricatorEdgeQuery())->withSourcePHIDs($this->sourcePHIDs[$viewer_phid])->withEdgeTypes(array(PhabricatorSubscribedToObjectEdgeType::EDGECONST))->withDestinationPHIDs($phids); $edge_query->execute(); $subscribed = $edge_query->getDestinationPHIDs(); if (!$subscribed) { return; } $this->subscribed[$viewer_phid] += array_fill_keys($subscribed, true); }
/** * Attach the revision to the task(s) and the task(s) to the revision. * * @return void */ public function didWriteRevision(DifferentialRevisionEditor $editor) { $revision = $editor->getRevision(); $revision_phid = $revision->getPHID(); $edge_type = PhabricatorEdgeConfig::TYPE_DREV_HAS_RELATED_TASK; $old_phids = PhabricatorEdgeQuery::loadDestinationPHIDs($revision_phid, $edge_type); $add_phids = $this->maniphestTasks; $rem_phids = array_diff($old_phids, $add_phids); $edge_editor = id(new PhabricatorEdgeEditor())->setUser($this->getUser()); foreach ($add_phids as $phid) { $edge_editor->addEdge($revision_phid, $edge_type, $phid); } foreach ($rem_phids as $phid) { $edge_editor->removeEdge($revision_phid, $edge_type, $phid); } $edge_editor->save(); }