Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/phid/conduit/ConduitAPI_phid_lookup_Method.php b/src/applications/phid/conduit/ConduitAPI_phid_lookup_Method.php
index d69987afd8..ea602ec3cb 100644
--- a/src/applications/phid/conduit/ConduitAPI_phid_lookup_Method.php
+++ b/src/applications/phid/conduit/ConduitAPI_phid_lookup_Method.php
@@ -1,52 +1,52 @@
<?php
/**
* @group conduit
*/
final class ConduitAPI_phid_lookup_Method
extends ConduitAPI_phid_Method {
public function getMethodDescription() {
return "Look up objects by name.";
}
public function defineParamTypes() {
return array(
'names' => 'required list<string>',
);
}
public function defineReturnType() {
return 'nonempty dict<string, wild>';
}
public function defineErrorTypes() {
return array();
}
protected function execute(ConduitAPIRequest $request) {
$names = $request->getValue('names');
$phids = array();
foreach ($names as $name) {
- $phid = PhabricatorPHID::fromObjectName($name);
+ $phid = PhabricatorPHID::fromObjectName($name, $request->getUser());
if ($phid) {
$phids[$name] = $phid;
}
}
$handles = id(new PhabricatorObjectHandleData($phids))
->setViewer($request->getUser())
->loadHandles();
$result = array();
foreach ($phids as $name => $phid) {
if (isset($handles[$phid]) && $handles[$phid]->isComplete()) {
$result[$name] = $this->buildHandleInformationDictionary(
$handles[$phid]);
}
}
return $result;
}
}
diff --git a/src/applications/phid/storage/PhabricatorPHID.php b/src/applications/phid/storage/PhabricatorPHID.php
index 2e8d114318..5f32bd15ab 100644
--- a/src/applications/phid/storage/PhabricatorPHID.php
+++ b/src/applications/phid/storage/PhabricatorPHID.php
@@ -1,65 +1,73 @@
<?php
final class PhabricatorPHID {
protected $phid;
protected $phidType;
protected $ownerPHID;
protected $parentPHID;
public static function generateNewPHID($type, $subtype = null) {
if (!$type) {
throw new Exception("Can not generate PHID with no type.");
}
if ($subtype === null) {
$uniq_len = 20;
$type_str = "{$type}";
} else {
$uniq_len = 15;
$type_str = "{$type}-{$subtype}";
}
$uniq = Filesystem::readRandomCharacters($uniq_len);
return "PHID-{$type_str}-{$uniq}";
}
- public static function fromObjectName($name) {
+ public static function fromObjectName($name, PhabricatorUser $viewer) {
$object = null;
$match = null;
if (preg_match('/^PHID-[A-Z]+-.{20}$/', $name)) {
// It's already a PHID! Yay.
return $name;
}
if (preg_match('/^r([A-Z]+)(\S*)$/', $name, $match)) {
$repository = id(new PhabricatorRepository())
->loadOneWhere('callsign = %s', $match[1]);
if ($match[2] == '') {
$object = $repository;
} else if ($repository) {
$object = id(new PhabricatorRepositoryCommit())->loadOneWhere(
'repositoryID = %d AND commitIdentifier = %s',
$repository->getID(),
$match[2]);
if (!$object) {
try {
$object = id(new PhabricatorRepositoryCommit())->loadOneWhere(
'repositoryID = %d AND commitIdentifier LIKE %>',
$repository->getID(),
$match[2]);
} catch (AphrontQueryCountException $ex) {
// Ambiguous; return nothing.
}
}
}
} else if (preg_match('/^d(\d+)$/i', $name, $match)) {
$object = id(new DifferentialRevision())->load($match[1]);
} else if (preg_match('/^t(\d+)$/i', $name, $match)) {
$object = id(new ManiphestTask())->load($match[1]);
+ } else if (preg_match('/^m(\d+)$/i', $name, $match)) {
+ $objects = id(new PholioMockQuery())
+ ->setViewer($viewer)
+ ->withIDs(array($match[1]))
+ ->execute();
+ $object = head($objects);
}
+
if ($object) {
return $object->getPHID();
}
+
return null;
}
}
diff --git a/src/applications/search/controller/PhabricatorSearchController.php b/src/applications/search/controller/PhabricatorSearchController.php
index 2293c97c0c..6bb6654d01 100644
--- a/src/applications/search/controller/PhabricatorSearchController.php
+++ b/src/applications/search/controller/PhabricatorSearchController.php
@@ -1,272 +1,272 @@
<?php
/**
* @group search
*/
final class PhabricatorSearchController
extends PhabricatorSearchBaseController {
private $key;
public function willProcessRequest(array $data) {
$this->key = idx($data, 'key');
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
if ($this->key) {
$query = id(new PhabricatorSearchQuery())->loadOneWhere(
'queryKey = %s',
$this->key);
if (!$query) {
return new Aphront404Response();
}
} else {
$query = new PhabricatorSearchQuery();
if ($request->isFormPost()) {
$query_str = $request->getStr('query');
$pref_jump = PhabricatorUserPreferences::PREFERENCE_SEARCHBAR_JUMP;
if ($request->getStr('jump') != 'no' &&
$user && $user->loadPreferences()->getPreference($pref_jump, 1)) {
$response = PhabricatorJumpNavHandler::jumpPostResponse($query_str);
} else {
$response = null;
}
if ($response) {
return $response;
} else {
$query->setQuery($query_str);
if ($request->getStr('scope')) {
switch ($request->getStr('scope')) {
case PhabricatorSearchScope::SCOPE_OPEN_REVISIONS:
$query->setParameter('open', 1);
$query->setParameter(
'type',
PhabricatorPHIDConstants::PHID_TYPE_DREV);
break;
case PhabricatorSearchScope::SCOPE_OPEN_TASKS:
$query->setParameter('open', 1);
$query->setParameter(
'type',
PhabricatorPHIDConstants::PHID_TYPE_TASK);
break;
case PhabricatorSearchScope::SCOPE_WIKI:
$query->setParameter(
'type',
PhabricatorPHIDConstants::PHID_TYPE_WIKI);
break;
case PhabricatorSearchScope::SCOPE_COMMITS:
$query->setParameter(
'type',
PhabricatorPHIDConstants::PHID_TYPE_CMIT);
break;
default:
break;
}
} else {
if (strlen($request->getStr('type'))) {
$query->setParameter('type', $request->getStr('type'));
}
if ($request->getArr('author')) {
$query->setParameter('author', $request->getArr('author'));
}
if ($request->getArr('owner')) {
$query->setParameter('owner', $request->getArr('owner'));
}
if ($request->getArr('subscribers')) {
$query->setParameter('subscribers',
$request->getArr('subscribers'));
}
if ($request->getInt('open')) {
$query->setParameter('open', $request->getInt('open'));
}
if ($request->getArr('project')) {
$query->setParameter('project', $request->getArr('project'));
}
}
$query->save();
return id(new AphrontRedirectResponse())
->setURI('/search/'.$query->getQueryKey().'/');
}
}
}
$options = array(
'' => 'All Documents',
) + PhabricatorSearchAbstractDocument::getSupportedTypes();
$status_options = array(
0 => 'Open and Closed Documents',
1 => 'Open Documents',
);
$phids = array_merge(
$query->getParameter('author', array()),
$query->getParameter('owner', array()),
$query->getParameter('subscribers', array()),
$query->getParameter('project', array()));
$handles = $this->loadViewerHandles($phids);
$author_value = array_select_keys(
$handles,
$query->getParameter('author', array()));
$author_value = mpull($author_value, 'getFullName', 'getPHID');
$owner_value = array_select_keys(
$handles,
$query->getParameter('owner', array()));
$owner_value = mpull($owner_value, 'getFullName', 'getPHID');
$subscribers_value = array_select_keys(
$handles,
$query->getParameter('subscribers', array()));
$subscribers_value = mpull($subscribers_value, 'getFullName', 'getPHID');
$project_value = array_select_keys(
$handles,
$query->getParameter('project', array()));
$project_value = mpull($project_value, 'getFullName', 'getPHID');
$search_form = new AphrontFormView();
$search_form
->setUser($user)
->setAction('/search/')
->appendChild(
phutil_tag(
'input',
array(
'type' => 'hidden',
'name' => 'jump',
'value' => 'no',
)))
->appendChild(
id(new AphrontFormTextControl())
->setLabel('Search')
->setName('query')
->setValue($query->getQuery()))
->appendChild(
id(new AphrontFormSelectControl())
->setLabel('Document Type')
->setName('type')
->setOptions($options)
->setValue($query->getParameter('type')))
->appendChild(
id(new AphrontFormSelectControl())
->setLabel('Document Status')
->setName('open')
->setOptions($status_options)
->setValue($query->getParameter('open')))
->appendChild(
id(new AphrontFormTokenizerControl())
->setName('author')
->setLabel('Author')
->setDatasource('/typeahead/common/users/')
->setValue($author_value))
->appendChild(
id(new AphrontFormTokenizerControl())
->setName('owner')
->setLabel('Owner')
->setDatasource('/typeahead/common/searchowner/')
->setValue($owner_value)
->setCaption(
'Tip: search for "Up For Grabs" to find unowned documents.'))
->appendChild(
id(new AphrontFormTokenizerControl())
->setName('subscribers')
->setLabel('Subscribers')
->setDatasource('/typeahead/common/users/')
->setValue($subscribers_value))
->appendChild(
id(new AphrontFormTokenizerControl())
->setName('project')
->setLabel('Project')
->setDatasource('/typeahead/common/projects/')
->setValue($project_value))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue('Search'));
$search_panel = new AphrontPanelView();
$search_panel->setHeader('Search Phabricator');
$search_panel->appendChild($search_form);
require_celerity_resource('phabricator-search-results-css');
if ($query->getID()) {
$limit = 20;
$pager = new AphrontPagerView();
$pager->setURI($request->getRequestURI(), 'page');
$pager->setPageSize($limit);
$pager->setOffset($request->getInt('page'));
$query->setParameter('limit', $limit + 1);
$query->setParameter('offset', $pager->getOffset());
$engine = PhabricatorSearchEngineSelector::newSelector()->newEngine();
$results = $engine->executeSearch($query);
$results = $pager->sliceResults($results);
if (!$request->getInt('page')) {
- $jump = PhabricatorPHID::fromObjectName($query->getQuery());
+ $jump = PhabricatorPHID::fromObjectName($query->getQuery(), $user);
if ($jump) {
array_unshift($results, $jump);
}
}
if ($results) {
$loader = id(new PhabricatorObjectHandleData($results))
->setViewer($user);
$handles = $loader->loadHandles();
$objects = $loader->loadObjects();
$results = array();
foreach ($handles as $phid => $handle) {
$view = id(new PhabricatorSearchResultView())
->setHandle($handle)
->setQuery($query)
->setObject(idx($objects, $phid));
$results[] = $view->render();
}
$results = hsprintf(
'<div class="phabricator-search-result-list">'.
'%s'.
'<div class="search-results-pager">%s</div>'.
'</div>',
phutil_implode_html("\n", $results),
$pager->render());
} else {
$results = hsprintf(
'<div class="phabricator-search-result-list">'.
'<p class="phabricator-search-no-results">No search results.</p>'.
'</div>');
}
} else {
$results = null;
}
return $this->buildStandardPageResponse(
array(
$search_panel,
$results,
),
array(
'title' => 'Search Results',
));
}
}
diff --git a/src/applications/search/management/PhabricatorSearchManagementIndexWorkflow.php b/src/applications/search/management/PhabricatorSearchManagementIndexWorkflow.php
index acd0b6108a..10863b3c60 100644
--- a/src/applications/search/management/PhabricatorSearchManagementIndexWorkflow.php
+++ b/src/applications/search/management/PhabricatorSearchManagementIndexWorkflow.php
@@ -1,136 +1,138 @@
<?php
/**
* @group search
*/
final class PhabricatorSearchManagementIndexWorkflow
extends PhabricatorSearchManagementWorkflow {
protected function didConstruct() {
$this
->setName('index')
->setSynopsis('Build or rebuild search indexes.')
->setExamples(
"**index** D123\n".
"**index** --type DREV\n".
"**index** --all")
->setArguments(
array(
array(
'name' => 'all',
'help' => 'Reindex all documents.',
),
array(
'name' => 'type',
'param' => 'TYPE',
'help' => 'PHID type to reindex, like "TASK" or "DREV".',
),
array(
'name' => 'background',
'help' => 'Instead of indexing in this process, queue tasks for '.
'the daemons. This is better if you are indexing a lot '.
'of stuff, but less helpful for debugging.',
),
array(
'name' => 'foreground',
'help' => 'Index in this process, even if there are many objects '.
'to index. This is helpful for debugging.',
),
array(
'name' => 'objects',
'wildcard' => true,
),
));
}
public function execute(PhutilArgumentParser $args) {
$console = PhutilConsole::getConsole();
$is_all = $args->getArg('all');
$is_type = $args->getArg('type');
$obj_names = $args->getArg('objects');
if ($obj_names && ($is_all || $is_type)) {
throw new PhutilArgumentUsageException(
"You can not name objects to index alongside the '--all' or '--type' ".
"flags.");
} else if (!$obj_names && !($is_all || $is_type)) {
throw new PhutilArgumentUsageException(
"Provide one of '--all', '--type' or a list of object names.");
}
if ($obj_names) {
$phids = $this->loadPHIDsByNames($obj_names);
} else {
$phids = $this->loadPHIDsByTypes($is_type);
}
if (!$phids) {
throw new PhutilArgumentUsageException(
"Nothing to index!");
}
$groups = phid_group_by_type($phids);
foreach ($groups as $group_type => $group) {
$console->writeOut(
pht(
"Indexing %d object(s) of type %s.",
count($group),
$group_type)."\n");
}
$indexer = new PhabricatorSearchIndexer();
foreach ($phids as $phid) {
$indexer->indexDocumentByPHID($phid);
$console->writeOut(pht("Indexing '%s'...\n", $phid));
}
$console->writeOut("Done.\n");
}
private function loadPHIDsByNames(array $names) {
$phids = array();
foreach ($names as $name) {
- $phid = PhabricatorPHID::fromObjectName($name);
+ $phid = PhabricatorPHID::fromObjectName(
+ $name,
+ PhabricatorUser::getOmnipotentUser());
if (!$phid) {
throw new PhutilArgumentUsageException(
"'{$name}' is not the name of a known object.");
}
$phids[] = $phid;
}
return $phids;
}
private function loadPHIDsByTypes($type) {
$indexer_symbols = id(new PhutilSymbolLoader())
->setAncestorClass('PhabricatorSearchDocumentIndexer')
->setConcreteOnly(true)
->setType('class')
->selectAndLoadSymbols();
$indexers = array();
foreach ($indexer_symbols as $symbol) {
$indexers[] = newv($symbol['name'], array());
}
$phids = array();
foreach ($indexers as $indexer) {
$indexer_phid = $indexer->getIndexableObject()->generatePHID();
$indexer_type = phid_get_type($indexer_phid);
if ($type && ($indexer_type != $type)) {
continue;
}
$iterator = $indexer->getIndexIterator();
foreach ($iterator as $object) {
$phids[] = $object->getPHID();
}
}
return $phids;
}
}
diff --git a/src/infrastructure/daemon/bot/handler/PhabricatorBotObjectNameHandler.php b/src/infrastructure/daemon/bot/handler/PhabricatorBotObjectNameHandler.php
index 588bd39017..4f43b04399 100644
--- a/src/infrastructure/daemon/bot/handler/PhabricatorBotObjectNameHandler.php
+++ b/src/infrastructure/daemon/bot/handler/PhabricatorBotObjectNameHandler.php
@@ -1,194 +1,193 @@
<?php
/**
* Looks for Dxxxx, Txxxx and links to them.
*
* @group irc
*/
final class PhabricatorBotObjectNameHandler extends PhabricatorBotHandler {
/**
* Map of PHIDs to the last mention of them (as an epoch timestamp); prevents
* us from spamming chat when a single object is discussed.
*/
private $recentlyMentioned = array();
public function receiveMessage(PhabricatorBotMessage $original_message) {
switch ($original_message->getCommand()) {
case 'MESSAGE':
$message = $original_message->getBody();
$matches = null;
+ $paste_ids = array();
+ $commit_names = array();
+ $vote_ids = array();
+ $file_ids = array();
+ $object_names = array();
+ $output = array();
+
$pattern =
'@'.
- '(?<!/)(?:^|\b)'. // Negative lookbehind prevent matching "/D123".
- '(D|T|P|V|F)(\d+)'.
+ '(?<!/)(?:^|\b)'.
+ '(R2D2)'.
'(?:\b|$)'.
'@';
- $revision_ids = array();
- $task_ids = array();
- $paste_ids = array();
- $commit_names = array();
- $vote_ids = array();
- $file_ids = array();
+ if (preg_match_all($pattern, $message, $matches, PREG_SET_ORDER)) {
+ foreach ($matches as $match) {
+ switch ($match[1]) {
+ case 'R2D2':
+ $output[$match[1]] = pht('beep hoop bop');
+ break;
+ }
+ }
+ }
+
+ $pattern =
+ '@'.
+ '(?<!/)(?:^|\b)'. // Negative lookbehind prevent matching "/D123".
+ '([A-Z])(\d+)'.
+ '(?:\b|$)'.
+ '@';
if (preg_match_all($pattern, $message, $matches, PREG_SET_ORDER)) {
foreach ($matches as $match) {
switch ($match[1]) {
- case 'D':
- $revision_ids[] = $match[2];
- break;
- case 'T':
- $task_ids[] = $match[2];
- break;
- case 'P':
- $paste_ids[] = $match[2];
- break;
- case 'V':
- $vote_ids[] = $match[2];
- break;
- case 'F':
- $file_ids[] = $match[2];
- break;
+ case 'P':
+ $paste_ids[] = $match[2];
+ break;
+ case 'V':
+ $vote_ids[] = $match[2];
+ break;
+ case 'F':
+ $file_ids[] = $match[2];
+ break;
+ default:
+ $name = $match[1].$match[2];
+ switch ($name) {
+ case 'T1000':
+ $output[$name] = pht(
+ 'T1000: A mimetic poly-alloy assassin controlled by '.
+ 'Skynet');
+ break;
+ default:
+ $object_names[] = $name;
+ break;
+ }
+ break;
}
}
}
$pattern =
'@'.
'(?<!/)(?:^|\b)'.
'(r[A-Z]+[0-9a-z]{1,40})'.
'(?:\b|$)'.
'@';
if (preg_match_all($pattern, $message, $matches, PREG_SET_ORDER)) {
foreach ($matches as $match) {
$commit_names[] = $match[1];
}
}
- $output = array();
-
- if ($revision_ids) {
- $revisions = $this->getConduit()->callMethodSynchronous(
- 'differential.query',
+ if ($object_names) {
+ $objects = $this->getConduit()->callMethodSynchronous(
+ 'phid.lookup',
array(
- 'ids' => $revision_ids,
+ 'names' => $object_names,
));
- $revisions = array_select_keys(
- ipull($revisions, null, 'id'),
- $revision_ids);
- foreach ($revisions as $revision) {
- $output[$revision['phid']] =
- 'D'.$revision['id'].' '.$revision['title'].' - '.
- $revision['uri'];
- }
- }
-
- if ($task_ids) {
- foreach ($task_ids as $task_id) {
- if ($task_id == 1000) {
- $output[1000] = 'T1000: A nanomorph mimetic poly-alloy'
- .'(liquid metal) assassin controlled by Skynet: '
- .'http://en.wikipedia.org/wiki/T-1000';
- continue;
- }
- $task = $this->getConduit()->callMethodSynchronous(
- 'maniphest.info',
- array(
- 'task_id' => $task_id,
- ));
- $output[$task['phid']] = 'T'.$task['id'].': '.$task['title'].
- ' (Priority: '.$task['priority'].') - '.$task['uri'];
+ foreach ($objects as $object) {
+ $output[$object['phid']] = $object['fullName'].' - '.$object['uri'];
}
}
if ($vote_ids) {
foreach ($vote_ids as $vote_id) {
$vote = $this->getConduit()->callMethodSynchronous(
'slowvote.info',
array(
'poll_id' => $vote_id,
));
$output[$vote['phid']] = 'V'.$vote['id'].': '.$vote['question'].
' Come Vote '.$vote['uri'];
}
}
if ($file_ids) {
foreach ($file_ids as $file_id) {
$file = $this->getConduit()->callMethodSynchronous(
'file.info',
array(
'id' => $file_id,
));
$output[$file['phid']] = $file['objectName'].": ".$file['uri']." - ".
$file['name'];
}
}
if ($paste_ids) {
foreach ($paste_ids as $paste_id) {
$paste = $this->getConduit()->callMethodSynchronous(
'paste.info',
array(
'paste_id' => $paste_id,
));
// Eventually I'd like to show the username of the paster as well,
// however that will need something like a user.username_from_phid
// since we (ideally) want to keep the bot to Conduit calls...and
// not call to Phabricator-specific stuff (like actually loading
// the User object and fetching his/her username.)
$output[$paste['phid']] = 'P'.$paste['id'].': '.$paste['uri'].' - '.
$paste['title'];
if ($paste['language']) {
$output[$paste['phid']] .= ' ('.$paste['language'].')';
}
}
}
if ($commit_names) {
$commits = $this->getConduit()->callMethodSynchronous(
'diffusion.getcommits',
array(
'commits' => $commit_names,
));
foreach ($commits as $commit) {
if (isset($commit['error'])) {
continue;
}
$output[$commit['commitPHID']] = $commit['uri'];
}
}
foreach ($output as $phid => $description) {
// Don't mention the same object more than once every 10 minutes
// in public channels, so we avoid spamming the chat over and over
// again for discsussions of a specific revision, for example.
$target_name = $original_message->getTarget()->getName();
if (empty($this->recentlyMentioned[$target_name])) {
$this->recentlyMentioned[$target_name] = array();
}
$quiet_until = idx(
$this->recentlyMentioned[$target_name],
$phid,
0) + (60 * 10);
if (time() < $quiet_until) {
// Remain quiet on this channel.
continue;
}
$this->recentlyMentioned[$target_name][$phid] = time();
$this->replyTo($original_message, $description);
}
break;
}
}
}

File Metadata

Mime Type
text/x-diff
Expires
Mon, Apr 28, 2:10 AM (7 h, 45 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
107654
Default Alt Text
(25 KB)

Event Timeline