public function execute(PhutilArgumentParser $args) { $console = PhutilConsole::getConsole(); $ids = $args->getArg('id'); if (!$ids) { throw new PhutilArgumentUsageException(pht("Use the '%s' flag to specify one or more SMS messages to show.", '--id')); } $messages = id(new PhabricatorSMS())->loadAllWhere('id IN (%Ld)', $ids); if ($ids) { $ids = array_fuse($ids); $missing = array_diff_key($ids, $messages); if ($missing) { throw new PhutilArgumentUsageException(pht('Some specified SMS messages do not exist: %s', implode(', ', array_keys($missing)))); } } $last_key = last_key($messages); foreach ($messages as $message_key => $message) { $info = array(); $info[] = pht('PROPERTIES'); $info[] = pht('ID: %d', $message->getID()); $info[] = pht('Status: %s', $message->getSendStatus()); $info[] = pht('To: %s', $message->getToNumber()); $info[] = pht('From: %s', $message->getFromNumber()); $info[] = null; $info[] = pht('BODY'); $info[] = $message->getBody(); $info[] = null; $console->writeOut('%s', implode("\n", $info)); if ($message_key != $last_key) { $console->writeOut("\n%s\n\n", str_repeat('-', 80)); } } }
protected function getUsersFromRequest(AphrontRequest $request, $key, array $allow_types = array()) { $list = $this->getListFromRequest($request, $key); $phids = array(); $names = array(); $allow_types = array_fuse($allow_types); $user_type = PhabricatorPeopleUserPHIDType::TYPECONST; foreach ($list as $item) { $type = phid_get_type($item); if ($type == $user_type) { $phids[] = $item; } else { if (isset($allow_types[$type])) { $phids[] = $item; } else { if (PhabricatorTypeaheadDatasource::isFunctionToken($item)) { // If this is a function, pass it through unchanged; we'll evaluate // it later. $phids[] = $item; } else { $names[] = $item; } } } } if ($names) { $users = id(new PhabricatorPeopleQuery())->setViewer($this->getViewer())->withUsernames($names)->execute(); foreach ($users as $user) { $phids[] = $user->getPHID(); } $phids = array_unique($phids); } return $phids; }
public function getValueForTransaction() { $new = parent::getValueForTransaction(); if (!$this->getUseEdgeTransactions()) { return $new; } $old = $this->getInitialValue(); if ($old === null) { return array('=' => array_fuse($new)); } // If we're building an edge transaction and the request has data about the // original value the user saw when they loaded the form, interpret the // edit as a mixture of "+" and "-" operations instead of a single "=" // operation. This limits our exposure to race conditions by making most // concurrent edits merge correctly. $add = array_diff($new, $old); $rem = array_diff($old, $new); $value = array(); if ($add) { $value['+'] = array_fuse($add); } if ($rem) { $value['-'] = array_fuse($rem); } return $value; }
public function handleRequest(AphrontRequest $request) { $viewer = $request->getViewer(); $book_name = $request->getURIData('book'); $book = id(new DivinerBookQuery())->setViewer($viewer)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->needProjectPHIDs(true)->withNames(array($book_name))->executeOne(); if (!$book) { return new Aphront404Response(); } $view_uri = '/book/' . $book->getName() . '/'; if ($request->isFormPost()) { $v_projects = $request->getArr('projectPHIDs'); $v_view = $request->getStr('viewPolicy'); $v_edit = $request->getStr('editPolicy'); $xactions = array(); $xactions[] = id(new DivinerLiveBookTransaction())->setTransactionType(PhabricatorTransactions::TYPE_EDGE)->setMetadataValue('edge:type', PhabricatorProjectObjectHasProjectEdgeType::EDGECONST)->setNewValue(array('=' => array_fuse($v_projects))); $xactions[] = id(new DivinerLiveBookTransaction())->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)->setNewValue($v_view); $xactions[] = id(new DivinerLiveBookTransaction())->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY)->setNewValue($v_edit); id(new DivinerLiveBookEditor())->setContinueOnNoEffect(true)->setContentSourceFromRequest($request)->setActor($viewer)->applyTransactions($book, $xactions); return id(new AphrontRedirectResponse())->setURI($view_uri); } $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('Edit Basics')); $title = pht('Edit %s', $book->getTitle()); $policies = id(new PhabricatorPolicyQuery())->setViewer($viewer)->setObject($book)->execute(); $view_capability = PhabricatorPolicyCapability::CAN_VIEW; $edit_capability = PhabricatorPolicyCapability::CAN_EDIT; $form = id(new AphrontFormView())->setUser($viewer)->appendControl(id(new AphrontFormTokenizerControl())->setDatasource(new PhabricatorProjectDatasource())->setName('projectPHIDs')->setLabel(pht('Projects'))->setValue($book->getProjectPHIDs()))->appendControl(id(new AphrontFormTokenizerControl())->setDatasource(new DiffusionRepositoryDatasource())->setName('repositoryPHIDs')->setLabel(pht('Repository'))->setDisableBehavior(true)->setLimit(1)->setValue($book->getRepositoryPHID() ? array($book->getRepositoryPHID()) : null))->appendChild(id(new AphrontFormPolicyControl())->setName('viewPolicy')->setPolicyObject($book)->setCapability($view_capability)->setPolicies($policies)->setCaption($book->describeAutomaticCapability($view_capability)))->appendChild(id(new AphrontFormPolicyControl())->setName('editPolicy')->setPolicyObject($book)->setCapability($edit_capability)->setPolicies($policies)->setCaption($book->describeAutomaticCapability($edit_capability)))->appendChild(id(new AphrontFormSubmitControl())->setValue(pht('Save'))->addCancelButton($view_uri)); $object_box = id(new PHUIObjectBoxView())->setHeaderText($title)->setForm($form); $timeline = $this->buildTransactionTimeline($book, new DivinerLiveBookTransactionQuery()); $timeline->setShouldTerminate(true); return $this->buildApplicationPage(array($crumbs, $object_box, $timeline), array('title' => $title)); }
protected function getGitResult(ConduitAPIRequest $request) { $drequest = $this->getDiffusionRequest(); $repository = $drequest->getRepository(); $commit = $drequest->getSymbolicCommit(); $commit_filter = null; if ($commit) { $commit_filter = $this->loadTagNamesForCommit($commit); } $name_filter = $request->getValue('names', null); $all_tags = $this->loadGitTagList(); $all_tags = mpull($all_tags, null, 'getName'); if ($name_filter !== null) { $all_tags = array_intersect_key($all_tags, array_fuse($name_filter)); } if ($commit_filter !== null) { $all_tags = array_intersect_key($all_tags, $commit_filter); } $tags = array_values($all_tags); $offset = $request->getValue('offset'); $limit = $request->getValue('limit'); if ($offset) { $tags = array_slice($tags, $offset); } if ($limit) { $tags = array_slice($tags, 0, $limit); } if ($request->getValue('needMessages')) { $this->loadMessagesForTags($all_tags); } return mpull($tags, 'toDictionary'); }
public function buildNav() { $user = $this->getRequest()->getUser(); $nav = new AphrontSideNavFilterView(); $nav->setBaseURI(new PhutilURI('/')); $applications = id(new PhabricatorApplicationQuery())->setViewer($user)->withInstalled(true)->withUnlisted(false)->withLaunchable(true)->execute(); $pinned = $user->loadPreferences()->getPinnedApplications($applications, $user); // Force "Applications" to appear at the bottom. $meta_app = 'PhabricatorApplicationsApplication'; $pinned = array_fuse($pinned); unset($pinned[$meta_app]); $pinned[$meta_app] = $meta_app; $applications[$meta_app] = PhabricatorApplication::getByClass($meta_app); $tiles = array(); $home_app = new PhabricatorHomeApplication(); $tiles[] = id(new PhabricatorApplicationLaunchView())->setApplication($home_app)->setApplicationStatus($home_app->loadStatus($user))->addClass('phabricator-application-launch-phone-only')->setUser($user); foreach ($pinned as $pinned_application) { if (empty($applications[$pinned_application])) { continue; } $application = $applications[$pinned_application]; $tile = id(new PhabricatorApplicationLaunchView())->setApplication($application)->setApplicationStatus($application->loadStatus($user))->setUser($user); $tiles[] = $tile; } $nav->addCustomBlock(phutil_tag('div', array('class' => 'application-tile-group'), $tiles)); $nav->addFilter('', pht('Customize Applications...'), '/settings/panel/home/'); $nav->addClass('phabricator-side-menu-home'); $nav->selectFilter(null); return $nav; }
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 getValueForTransaction() { $new = parent::getValueForTransaction(); $edge_types = array(PhabricatorTransactions::TYPE_EDGE => true, PhabricatorTransactions::TYPE_SUBSCRIBERS => true); if (isset($edge_types[$this->getTransactionType()])) { if ($this->originalValue !== null) { // If we're building an edge transaction and the request has data // about the original value the user saw when they loaded the form, // interpret the edit as a mixture of "+" and "-" operations instead // of a single "=" operation. This limits our exposure to race // conditions by making most concurrent edits merge correctly. $new = parent::getValueForTransaction(); $old = $this->originalValue; $add = array_diff($new, $old); $rem = array_diff($old, $new); $value = array(); if ($add) { $value['+'] = array_fuse($add); } if ($rem) { $value['-'] = array_fuse($rem); } return $value; } else { if (!is_array($new)) { throw new Exception(print_r($new, true)); } return array('=' => array_fuse($new)); } } return $new; }
public static function loadAffiliatedUserPHIDs(array $package_ids) { if (!$package_ids) { return array(); } $owners = id(new PhabricatorOwnersOwner())->loadAllWhere('packageID IN (%Ls)', $package_ids); $type_user = PhabricatorPeopleUserPHIDType::TYPECONST; $type_project = PhabricatorProjectProjectPHIDType::TYPECONST; $user_phids = array(); $project_phids = array(); foreach ($owners as $owner) { $owner_phid = $owner->getUserPHID(); switch (phid_get_type($owner_phid)) { case PhabricatorPeopleUserPHIDType::TYPECONST: $user_phids[] = $owner_phid; break; case PhabricatorProjectProjectPHIDType::TYPECONST: $project_phids[] = $owner_phid; break; } } if ($project_phids) { $projects = id(new PhabricatorProjectQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withPHIDs($project_phids)->needMembers(true)->execute(); foreach ($projects as $project) { foreach ($project->getMemberPHIDs() as $member_phid) { $user_phids[] = $member_phid; } } } $user_phids = array_fuse($user_phids); return array_values($user_phids); }
protected function applyAuditors(array $phids, HeraldRule $rule) { $adapter = $this->getAdapter(); $object = $adapter->getObject(); $auditors = $object->getAudits(); $current = array(); foreach ($auditors as $auditor) { if ($auditor->isInteresting()) { $current[] = $auditor->getAuditorPHID(); } } $allowed_types = array(PhabricatorPeopleUserPHIDType::TYPECONST, PhabricatorProjectProjectPHIDType::TYPECONST, PhabricatorOwnersPackagePHIDType::TYPECONST); $targets = $this->loadStandardTargets($phids, $allowed_types, $current); if (!$targets) { return; } $phids = array_fuse(array_keys($targets)); // TODO: Convert this to be translatable, structured data eventually. $reason_map = array(); foreach ($phids as $phid) { $reason_map[$phid][] = pht('%s Triggered Audit', $rule->getMonogram()); } $xaction = $adapter->newTransaction()->setTransactionType(PhabricatorAuditActionConstants::ADD_AUDITORS)->setNewValue($phids)->setMetadataValue('auditStatus', PhabricatorAuditStatusConstants::AUDIT_REQUIRED)->setMetadataValue('auditReasonMap', $reason_map); $adapter->queueTransaction($xaction); $this->logEffect(self::DO_ADD_AUDITORS, $phids); }
public function processRequest(AphrontRequest $request) { $user = $request->getUser(); $username = $user->getUsername(); $pref_time = PhabricatorUserPreferences::PREFERENCE_TIME_FORMAT; $pref_date = PhabricatorUserPreferences::PREFERENCE_DATE_FORMAT; $pref_week_start = PhabricatorUserPreferences::PREFERENCE_WEEK_START_DAY; $preferences = $user->loadPreferences(); $errors = array(); if ($request->isFormPost()) { $new_timezone = $request->getStr('timezone'); if (in_array($new_timezone, DateTimeZone::listIdentifiers(), true)) { $user->setTimezoneIdentifier($new_timezone); } else { $errors[] = pht('The selected timezone is not a valid timezone.'); } $preferences->setPreference($pref_time, $request->getStr($pref_time))->setPreference($pref_date, $request->getStr($pref_date))->setPreference($pref_week_start, $request->getStr($pref_week_start)); if (!$errors) { $preferences->save(); $user->save(); return id(new AphrontRedirectResponse())->setURI($this->getPanelURI('?saved=true')); } } $timezone_ids = DateTimeZone::listIdentifiers(); $timezone_id_map = array_fuse($timezone_ids); $form = new AphrontFormView(); $form->setUser($user)->appendChild(id(new AphrontFormSelectControl())->setLabel(pht('Timezone'))->setName('timezone')->setOptions($timezone_id_map)->setValue($user->getTimezoneIdentifier()))->appendChild(id(new AphrontFormSelectControl())->setLabel(pht('Time-of-Day Format'))->setName($pref_time)->setOptions(array('g:i A' => pht('12-hour (2:34 PM)'), 'H:i' => pht('24-hour (14:34)')))->setCaption(pht('Format used when rendering a time of day.'))->setValue($preferences->getPreference($pref_time)))->appendChild(id(new AphrontFormSelectControl())->setLabel(pht('Date Format'))->setName($pref_date)->setOptions(array('Y-m-d' => pht('ISO 8601 (2000-02-28)'), 'n/j/Y' => pht('US (2/28/2000)'), 'd-m-Y' => pht('European (28-02-2000)')))->setCaption(pht('Format used when rendering a date.'))->setValue($preferences->getPreference($pref_date)))->appendChild(id(new AphrontFormSelectControl())->setLabel(pht('Week Starts On'))->setOptions($this->getWeekDays())->setName($pref_week_start)->setCaption(pht('Calendar weeks will start with this day.'))->setValue($preferences->getPreference($pref_week_start, 0)))->appendChild(id(new AphrontFormSubmitControl())->setValue(pht('Save Account Settings'))); $form_box = id(new PHUIObjectBoxView())->setHeaderText(pht('Date and Time Settings'))->setFormSaved($request->getStr('saved'))->setFormErrors($errors)->setForm($form); return array($form_box); }
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); }
public function buildSearchForm(AphrontFormView $form, PhabricatorSavedQuery $saved) { $options = array(); $author_value = null; $owner_value = null; $subscribers_value = null; $project_value = null; $author_phids = $saved->getParameter('authorPHIDs', array()); $owner_phids = $saved->getParameter('ownerPHIDs', array()); $subscriber_phids = $saved->getParameter('subscriberPHIDs', array()); $project_phids = $saved->getParameter('projectPHIDs', array()); $all_phids = array_merge($author_phids, $owner_phids, $subscriber_phids, $project_phids); $all_handles = id(new PhabricatorHandleQuery())->setViewer($this->requireViewer())->withPHIDs($all_phids)->execute(); $author_handles = array_select_keys($all_handles, $author_phids); $owner_handles = array_select_keys($all_handles, $owner_phids); $subscriber_handles = array_select_keys($all_handles, $subscriber_phids); $project_handles = array_select_keys($all_handles, $project_phids); $with_unowned = $saved->getParameter('withUnowned', array()); $status_values = $saved->getParameter('statuses', array()); $status_values = array_fuse($status_values); $statuses = array(PhabricatorSearchRelationship::RELATIONSHIP_OPEN => pht('Open'), PhabricatorSearchRelationship::RELATIONSHIP_CLOSED => pht('Closed')); $status_control = id(new AphrontFormCheckboxControl())->setLabel(pht('Document Status')); foreach ($statuses as $status => $name) { $status_control->addCheckbox('statuses[]', $status, $name, isset($status_values[$status])); } $type_values = $saved->getParameter('types', array()); $type_values = array_fuse($type_values); $types = self::getIndexableDocumentTypes($this->requireViewer()); $types_control = id(new AphrontFormCheckboxControl())->setLabel(pht('Document Types')); foreach ($types as $type => $name) { $types_control->addCheckbox('types[]', $type, $name, isset($type_values[$type])); } $form->appendChild(phutil_tag('input', array('type' => 'hidden', 'name' => 'jump', 'value' => 'no')))->appendChild(id(new AphrontFormTextControl())->setLabel('Query')->setName('query')->setValue($saved->getParameter('query')))->appendChild($status_control)->appendChild($types_control)->appendChild(id(new AphrontFormTokenizerControl())->setName('authorPHIDs')->setLabel('Authors')->setDatasource(new PhabricatorPeopleDatasource())->setValue($author_handles))->appendChild(id(new AphrontFormTokenizerControl())->setName('ownerPHIDs')->setLabel('Owners')->setDatasource(new PhabricatorTypeaheadOwnerDatasource())->setValue($owner_handles))->appendChild(id(new AphrontFormCheckboxControl())->addCheckbox('withUnowned', 1, pht('Show only unowned documents.'), $with_unowned))->appendChild(id(new AphrontFormTokenizerControl())->setName('subscriberPHIDs')->setLabel('Subscribers')->setDatasource(new PhabricatorPeopleDatasource())->setValue($subscriber_handles))->appendChild(id(new AphrontFormTokenizerControl())->setName('projectPHIDs')->setLabel('In Any Project')->setDatasource(new PhabricatorProjectDatasource())->setValue($project_handles)); }
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; }
private static function renderOptions($selected, array $options, array $disabled = array()) { $disabled = array_fuse($disabled); $tags = array(); $already_selected = false; foreach ($options as $value => $thing) { if (is_array($thing)) { $tags[] = phutil_tag('optgroup', array('label' => $value), self::renderOptions($selected, $thing)); } else { // When there are a list of options including similar values like // "0" and "" (the empty string), only select the first matching // value. Ideally this should be more precise about matching, but we // have 2,000 of these controls at this point so hold that for a // broader rewrite. if (!$already_selected && $value == $selected) { $is_selected = 'selected'; $already_selected = true; } else { $is_selected = null; } $tags[] = phutil_tag('option', array('selected' => $is_selected, 'value' => $value, 'disabled' => isset($disabled[$value]) ? 'disabled' : null), $thing); } } return $tags; }
public function processRequest() { $request = $this->getRequest(); $viewer = $request->getUser(); $query = $request->getStr('q'); // Default this to the query string to make debugging a little bit easier. $raw_query = nonempty($request->getStr('raw'), $query); // This makes form submission easier in the debug view. $this->class = nonempty($request->getStr('class'), $this->class); $sources = id(new PhutilSymbolLoader())->setAncestorClass('PhabricatorTypeaheadDatasource')->loadObjects(); if (isset($sources[$this->class])) { $source = $sources[$this->class]; $source->setParameters($request->getRequestData()); $composite = new PhabricatorTypeaheadRuntimeCompositeDatasource(); $composite->addDatasource($source); $composite->setViewer($viewer)->setQuery($query)->setRawQuery($raw_query); $results = $composite->loadResults(); } else { $results = array(); } $content = mpull($results, 'getWireFormat'); if ($request->isAjax()) { return id(new AphrontAjaxResponse())->setContent($content); } // If there's a non-Ajax request to this endpoint, show results in a tabular // format to make it easier to debug typeahead output. $options = array_fuse(array_keys($sources)); asort($options); $form = id(new AphrontFormView())->setUser($viewer)->setAction('/typeahead/class/')->appendChild(id(new AphrontFormSelectControl())->setLabel(pht('Source Class'))->setName('class')->setValue($this->class)->setOptions($options))->appendChild(id(new AphrontFormTextControl())->setLabel(pht('Query'))->setName('q')->setValue($request->getStr('q')))->appendChild(id(new AphrontFormTextControl())->setLabel(pht('Raw Query'))->setName('raw')->setValue($request->getStr('raw')))->appendChild(id(new AphrontFormSubmitControl())->setValue(pht('Query'))); $form_box = id(new PHUIObjectBoxView())->setHeaderText(pht('Token Query'))->setForm($form); $table = new AphrontTableView($content); $table->setHeaders(array(pht('Name'), pht('URI'), pht('PHID'), pht('Priority'), pht('Display Name'), pht('Display Type'), pht('Image URI'), pht('Priority Type'), pht('Icon'), pht('Closed'), pht('Sprite'))); $result_box = id(new PHUIObjectBoxView())->setHeaderText(pht('Token Results (%s)', $this->class))->appendChild($table); return $this->buildApplicationPage(array($form_box, $result_box), array('title' => pht('Typeahead Results'), 'device' => false)); }
public function loadObjects(PhabricatorObjectQuery $object_query, array $phids) { static $queries; if ($queries === null) { $objects = id(new PhutilClassMapQuery())->setAncestorClass('PhabricatorApplicationTransactionQuery')->execute(); $queries = array(); foreach ($objects as $object) { $type = $object->getTemplateApplicationTransaction()->getApplicationTransactionType(); $queries[$type] = $object; } } $phid_subtypes = array(); foreach ($phids as $phid) { $subtype = phid_get_subtype($phid); if ($subtype) { $phid_subtypes[$subtype][] = $phid; } } $results = array(); foreach ($phid_subtypes as $subtype => $subtype_phids) { $query = idx($queries, $subtype); if (!$query) { continue; } $xaction_query = id(clone $query)->setViewer($object_query->getViewer())->setParentQuery($object_query)->withPHIDs($subtype_phids); if (!$xaction_query->canViewerUseQueryApplication()) { $object_query->addPolicyFilteredPHIDs(array_fuse($subtype_phids)); continue; } $xactions = $xaction_query->execute(); $results += mpull($xactions, null, 'getPHID'); } return $results; }
public function execute() { $phids = array_fuse($this->phids); $actors = array(); $type_map = array(); foreach ($phids as $phid) { $type_map[phid_get_type($phid)][] = $phid; } // TODO: Generalize this somewhere else. $results = array(); foreach ($type_map as $type => $phids) { switch ($type) { case PhabricatorProjectProjectPHIDType::TYPECONST: // NOTE: We're loading the projects here in order to respect policies. $projects = id(new PhabricatorProjectQuery())->setViewer($this->getViewer())->withPHIDs($phids)->execute(); $subscribers = id(new PhabricatorSubscribersQuery())->withObjectPHIDs($phids)->execute(); $projects = mpull($projects, null, 'getPHID'); foreach ($phids as $phid) { $project = idx($projects, $phid); if (!$project) { $results[$phid] = array(); } else { $results[$phid] = idx($subscribers, $phid, array()); } } break; default: break; } } return $results; }
public function execute() { $phids = array_fuse($this->phids); $actors = array(); $type_map = array(); foreach ($phids as $phid) { $type_map[phid_get_type($phid)][] = $phid; $actors[$phid] = id(new PhabricatorMetaMTAActor())->setPHID($phid); } // TODO: Move this to PhabricatorPHIDType, or the objects, or some // interface. foreach ($type_map as $type => $phids) { switch ($type) { case PhabricatorPeopleUserPHIDType::TYPECONST: $this->loadUserActors($actors, $phids); break; case PhabricatorPeopleExternalPHIDType::TYPECONST: $this->loadExternalUserActors($actors, $phids); break; default: $this->loadUnknownActors($actors, $phids); break; } } return $actors; }
public function handleRequest(AphrontRequest $request) { $viewer = $request->getViewer(); $id = $request->getURIData('id'); if ($id) { $account = id(new PhortuneAccountQuery())->setViewer($viewer)->withIDs(array($id))->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne(); if (!$account) { return new Aphront404Response(); } $is_new = false; } else { $account = PhortuneAccount::initializeNewAccount($viewer); $account->attachMemberPHIDs(array($viewer->getPHID())); $is_new = true; } $v_name = $account->getName(); $e_name = true; $v_members = $account->getMemberPHIDs(); $e_members = null; $validation_exception = null; if ($request->isFormPost()) { $v_name = $request->getStr('name'); $v_members = $request->getArr('memberPHIDs'); $type_name = PhortuneAccountTransaction::TYPE_NAME; $type_edge = PhabricatorTransactions::TYPE_EDGE; $xactions = array(); $xactions[] = id(new PhortuneAccountTransaction())->setTransactionType($type_name)->setNewValue($v_name); $xactions[] = id(new PhortuneAccountTransaction())->setTransactionType($type_edge)->setMetadataValue('edge:type', PhortuneAccountHasMemberEdgeType::EDGECONST)->setNewValue(array('=' => array_fuse($v_members))); $editor = id(new PhortuneAccountEditor())->setActor($viewer)->setContentSourceFromRequest($request)->setContinueOnNoEffect(true); try { $editor->applyTransactions($account, $xactions); $account_uri = $this->getApplicationURI($account->getID() . '/'); return id(new AphrontRedirectResponse())->setURI($account_uri); } catch (PhabricatorApplicationTransactionValidationException $ex) { $validation_exception = $ex; $e_name = $ex->getShortMessage($type_name); $e_members = $ex->getShortMessage($type_edge); } } $crumbs = $this->buildApplicationCrumbs(); $crumbs->setBorder(true); if ($is_new) { $cancel_uri = $this->getApplicationURI('account/'); $crumbs->addTextCrumb(pht('Accounts'), $cancel_uri); $crumbs->addTextCrumb(pht('Create Account')); $title = pht('Create Payment Account'); $submit_button = pht('Create Account'); } else { $cancel_uri = $this->getApplicationURI($account->getID() . '/'); $crumbs->addTextCrumb($account->getName(), $cancel_uri); $crumbs->addTextCrumb(pht('Edit')); $title = pht('Edit %s', $account->getName()); $submit_button = pht('Save Changes'); } $form = id(new AphrontFormView())->setUser($viewer)->appendChild(id(new AphrontFormTextControl())->setName('name')->setLabel(pht('Name'))->setValue($v_name)->setError($e_name))->appendControl(id(new AphrontFormTokenizerControl())->setDatasource(new PhabricatorPeopleDatasource())->setLabel(pht('Members'))->setName('memberPHIDs')->setValue($v_members)->setError($e_members))->appendChild(id(new AphrontFormSubmitControl())->setValue($submit_button)->addCancelButton($cancel_uri)); $box = id(new PHUIObjectBoxView())->setHeaderText(pht('Account'))->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)->setValidationException($validation_exception)->setForm($form); $header = id(new PHUIHeaderView())->setHeader($title)->setHeaderIcon('fa-pencil'); $view = id(new PHUITwoColumnView())->setHeader($header)->setFooter(array($box)); return $this->newPage()->setTitle($title)->setCrumbs($crumbs)->appendChild($view); }
protected function execute(ConduitAPIRequest $request) { $query = id(new DiffusionCommitQuery())->setViewer($request->getUser())->needAuditRequests(true); $auditor_phids = $request->getValue('auditorPHIDs', array()); if ($auditor_phids) { $query->withAuditorPHIDs($auditor_phids); } $commit_phids = $request->getValue('commitPHIDs', array()); if ($commit_phids) { $query->withPHIDs($commit_phids); } $status = $request->getValue('status', DiffusionCommitQuery::AUDIT_STATUS_ANY); $query->withAuditStatus($status); // NOTE: These affect the number of commits identified, which is sort of // reasonable but means the method may return an arbitrary number of // actual audit requests. $query->setOffset($request->getValue('offset', 0)); $query->setLimit($request->getValue('limit', 100)); $commits = $query->execute(); $auditor_map = array_fuse($auditor_phids); $results = array(); foreach ($commits as $commit) { $requests = $commit->getAudits(); foreach ($requests as $request) { // If this audit isn't triggered for one of the requested PHIDs, // skip it. if ($auditor_map && empty($auditor_map[$request->getAuditorPHID()])) { continue; } $results[] = array('id' => $request->getID(), 'commitPHID' => $request->getCommitPHID(), 'auditorPHID' => $request->getAuditorPHID(), 'reasons' => $request->getAuditReasons(), 'status' => $request->getAuditStatus()); } } return $results; }
protected function willFilterPage(array $handles) { // NOTE: This is used by the object selector dialog to exclude the object // you're looking at, so that, e.g., a task can't be set as a dependency // of itself in the UI. // TODO: Remove this after object selection moves to ApplicationSearch. $exclude = array(); if ($this->savedQuery) { $exclude_phids = $this->savedQuery->getParameter('excludePHIDs', array()); $exclude = array_fuse($exclude_phids); } foreach ($handles as $key => $handle) { if (!$handle->isComplete()) { unset($handles[$key]); continue; } if ($handle->getPolicyFiltered()) { unset($handles[$key]); continue; } if (isset($exclude[$handle->getPHID()])) { unset($handles[$key]); continue; } } return $handles; }
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'))); }
protected function applyRequire(array $phids) { $adapter = $this->getAdapter(); $edgetype_legal = LegalpadObjectNeedsSignatureEdgeType::EDGECONST; $current = $adapter->loadEdgePHIDs($edgetype_legal); $allowed_types = array(PhabricatorLegalpadDocumentPHIDType::TYPECONST); $targets = $this->loadStandardTargets($phids, $allowed_types, $current); if (!$targets) { return; } $phids = array_fuse(array_keys($targets)); $object = $adapter->getObject(); $author_phid = $object->getAuthorPHID(); $signatures = id(new LegalpadDocumentSignatureQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withDocumentPHIDs($phids)->withSignerPHIDs(array($author_phid))->execute(); $signatures = mpull($signatures, null, 'getDocumentPHID'); $signed = array(); foreach ($phids as $phid) { if (isset($signatures[$phid])) { $signed[] = $phid; unset($phids[$phid]); } } if ($signed) { $this->logEffect(self::DO_SIGNED, $phids); } if (!$phids) { return; } $xaction = $adapter->newTransaction()->setTransactionType(PhabricatorTransactions::TYPE_EDGE)->setMetadataValue('edge:type', $edgetype_legal)->setNewValue(array('+' => $phids)); $adapter->queueTransaction($xaction); $this->logEffect(self::DO_REQUIRED, $phids); }
public function buildCustomEditFields(PhabricatorEditEngine $engine, PhabricatorApplicationTransactionInterface $object) { $viewer = $engine->getViewer(); $editor = $object->getApplicationTransactionEditor(); $types = $editor->getTransactionTypesForObject($object); $types = array_fuse($types); $policies = id(new PhabricatorPolicyQuery())->setViewer($viewer)->setObject($object)->execute(); $map = array(PhabricatorTransactions::TYPE_VIEW_POLICY => array('key' => 'policy.view', 'aliases' => array('view'), 'capability' => PhabricatorPolicyCapability::CAN_VIEW, 'label' => pht('View Policy'), 'description' => pht('Controls who can view the object.'), 'edit' => 'view'), PhabricatorTransactions::TYPE_EDIT_POLICY => array('key' => 'policy.edit', 'aliases' => array('edit'), 'capability' => PhabricatorPolicyCapability::CAN_EDIT, 'label' => pht('Edit Policy'), 'description' => pht('Controls who can edit the object.'), 'edit' => 'edit'), PhabricatorTransactions::TYPE_JOIN_POLICY => array('key' => 'policy.join', 'aliases' => array('join'), 'capability' => PhabricatorPolicyCapability::CAN_JOIN, 'label' => pht('Join Policy'), 'description' => pht('Controls who can join the object.'), 'edit' => 'join')); $fields = array(); foreach ($map as $type => $spec) { if (empty($types[$type])) { continue; } $capability = $spec['capability']; $key = $spec['key']; $aliases = $spec['aliases']; $label = $spec['label']; $description = $spec['description']; $edit = $spec['edit']; $policy_field = id(new PhabricatorPolicyEditField())->setKey($key)->setLabel($label)->setDescription($description)->setAliases($aliases)->setIsCopyable(true)->setCapability($capability)->setPolicies($policies)->setTransactionType($type)->setEditTypeKey($edit)->setValue($object->getPolicy($capability)); $fields[] = $policy_field; if (!$object instanceof PhabricatorSpacesInterface) { if ($capability == PhabricatorPolicyCapability::CAN_VIEW) { $type_space = PhabricatorTransactions::TYPE_SPACE; if (isset($types[$type_space])) { $space_field = id(new PhabricatorSpaceEditField())->setKey('spacePHID')->setLabel(pht('Space'))->setEditTypeKey('space')->setDescription(pht('Shifts the object in the Spaces application.'))->setIsCopyable(true)->setIsReorderable(false)->setAliases(array('space', 'policy.space'))->setTransactionType($type_space)->setValue($object->getSpacePHID()); $fields[] = $space_field; $policy_field->setSpaceField($space_field); } } } } return $fields; }
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) { $where = parent::buildWhereClauseParts($conn); if ($this->callerPHIDs !== null) { $where[] = qsprintf($conn, 'callerPHID IN (%Ls)', $this->callerPHIDs); } if ($this->methods !== null) { $where[] = qsprintf($conn, 'method IN (%Ls)', $this->methods); } if ($this->methodStatuses !== null) { $statuses = array_fuse($this->methodStatuses); $methods = id(new PhabricatorConduitMethodQuery())->setViewer($this->getViewer())->execute(); $method_names = array(); foreach ($methods as $method) { $status = $method->getMethodStatus(); if (isset($statuses[$status])) { $method_names[] = $method->getAPIMethodName(); } } if (!$method_names) { throw new PhabricatorEmptyQueryException(); } $where[] = qsprintf($conn, 'method IN (%Ls)', $method_names); } return $where; }
public function getKeys(array $keys) { $remaining = array_fuse($keys); $results = array(); $missed = array(); try { foreach ($this->cachesForward as $cache) { $result = $cache->getKeys($remaining); $remaining = array_diff_key($remaining, $result); $results += $result; if (!$remaining) { while ($cache = array_pop($missed)) { // TODO: This sets too many results in the closer caches, although // it probably isn't a big deal in most cases; normally we're just // filling the request cache. $cache->setKeys($result, $this->nextTTL); } break; } $missed[] = $cache; } $this->nextTTL = null; } catch (Exception $ex) { $this->nextTTL = null; throw $ex; } return $results; }
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)); }
public function handleRequest(AphrontRequest $request) { $viewer = $request->getViewer(); $id = $request->getURIData('id'); $project = id(new PhabricatorProjectQuery())->setViewer($viewer)->withIDs(array($id))->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne(); if (!$project) { return new Aphront404Response(); } $this->setProject($project); $done_uri = "/project/members/{$id}/"; if (!$project->supportsEditMembers()) { $copy = pht('Parent projects and milestones do not support adding ' . 'members. You can add members directly to any non-parent subproject.'); return $this->newDialog()->setTitle(pht('Unsupported Project'))->appendParagraph($copy)->addCancelButton($done_uri); } if ($request->isFormPost()) { $member_phids = $request->getArr('memberPHIDs'); $type_member = PhabricatorProjectProjectHasMemberEdgeType::EDGECONST; $xactions = array(); $xactions[] = id(new PhabricatorProjectTransaction())->setTransactionType(PhabricatorTransactions::TYPE_EDGE)->setMetadataValue('edge:type', $type_member)->setNewValue(array('+' => array_fuse($member_phids))); $editor = id(new PhabricatorProjectTransactionEditor($project))->setActor($viewer)->setContentSourceFromRequest($request)->setContinueOnNoEffect(true)->setContinueOnMissingFields(true)->applyTransactions($project, $xactions); return id(new AphrontRedirectResponse())->setURI($done_uri); } $form = id(new AphrontFormView())->setUser($viewer)->appendControl(id(new AphrontFormTokenizerControl())->setName('memberPHIDs')->setLabel(pht('Members'))->setDatasource(new PhabricatorPeopleDatasource())); return $this->newDialog()->setTitle(pht('Add Members'))->appendForm($form)->addCancelButton($done_uri)->addSubmitButton(pht('Add Members')); }
public function buildTransactions(PhabricatorUser $viewer, PhabricatorApplicationTransactionInterface $object, PhabricatorMetaMTAReceivedMail $mail, $command, array $argv) { $subscriber_phids = id(new PhabricatorObjectListQuery())->setViewer($viewer)->setAllowedTypes(array(PhabricatorPeopleUserPHIDType::TYPECONST, PhabricatorProjectProjectPHIDType::TYPECONST))->setObjectList(implode(' ', $argv))->setAllowPartialResults(true)->execute(); $xactions = array(); $xactions[] = $object->getApplicationTransactionTemplate()->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS)->setNewValue(array('+' => array_fuse($subscriber_phids))); return $xactions; }