Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/typeahead/application/PhabricatorTypeaheadApplication.php b/src/applications/typeahead/application/PhabricatorTypeaheadApplication.php
index b69d4f4223..fdae374f90 100644
--- a/src/applications/typeahead/application/PhabricatorTypeaheadApplication.php
+++ b/src/applications/typeahead/application/PhabricatorTypeaheadApplication.php
@@ -1,26 +1,26 @@
<?php
final class PhabricatorTypeaheadApplication extends PhabricatorApplication {
public function getName() {
return pht('Typeahead');
}
public function getRoutes() {
return array(
'/typeahead/' => array(
- 'class/(?:(?P<class>\w+)/)?'
+ '(?P<action>browse|class)/(?:(?P<class>\w+)/)?'
=> 'PhabricatorTypeaheadModularDatasourceController',
),
);
}
public function isLaunchable() {
return false;
}
public function canUninstall() {
return false;
}
}
diff --git a/src/applications/typeahead/controller/PhabricatorTypeaheadModularDatasourceController.php b/src/applications/typeahead/controller/PhabricatorTypeaheadModularDatasourceController.php
index a754d1362a..ffc8ce2af4 100644
--- a/src/applications/typeahead/controller/PhabricatorTypeaheadModularDatasourceController.php
+++ b/src/applications/typeahead/controller/PhabricatorTypeaheadModularDatasourceController.php
@@ -1,131 +1,167 @@
<?php
final class PhabricatorTypeaheadModularDatasourceController
extends PhabricatorTypeaheadDatasourceController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$request = $this->getRequest();
$viewer = $request->getUser();
$query = $request->getStr('q');
+ $is_browse = ($request->getURIData('action') == 'browse');
// 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.
$class = nonempty($request->getURIData('class'), $request->getStr('class'));
$sources = id(new PhutilSymbolLoader())
->setAncestorClass('PhabricatorTypeaheadDatasource')
->loadObjects();
if (isset($sources[$class])) {
$source = $sources[$class];
- if ($source->getDatasourceApplicationClass()) {
- if (!PhabricatorApplication::isClassInstalledForViewer(
- $source->getDatasourceApplicationClass(),
- $viewer)) {
- return id(new Aphront404Response());
- }
- }
-
$source->setParameters($request->getRequestData());
+ // NOTE: Wrapping the source in a Composite datasource ensures we perform
+ // application visibility checks for the viewer, so we do not need to do
+ // those separately.
$composite = new PhabricatorTypeaheadRuntimeCompositeDatasource();
$composite->addDatasource($source);
$composite
->setViewer($viewer)
->setQuery($query)
->setRawQuery($raw_query);
+ if ($is_browse) {
+ $limit = 3;
+ $offset = $request->getInt('offset');
+ $composite
+ ->setLimit($limit + 1)
+ ->setOffset($offset);
+ }
+
$results = $composite->loadResults();
+
+ if ($is_browse) {
+ $next_link = null;
+ if (count($results) > $limit) {
+ $results = array_slice($results, 0, $limit, $preserve_keys = true);
+ $next_link = phutil_tag(
+ 'a',
+ array(
+ 'href' => id(new PhutilURI($request->getRequestURI()))
+ ->setQueryParam('offset', $offset + $limit),
+ ),
+ pht('Next Page'));
+ }
+
+ $rows = array();
+ foreach ($results as $result) {
+ // TODO: Render nicely.
+ $rows[] = array_slice($result->getWireFormat(), 0, 3, true);
+ }
+
+ $table = id(new AphrontTableView($rows));
+
+ return $this->newDialog()
+ ->setWidth(AphrontDialogView::WIDTH_FORM)
+ ->setTitle(get_class($source)) // TODO: Provide nice names.
+ ->appendChild($table)
+ ->appendChild($next_link)
+ ->addCancelButton('/', pht('Close'));
+ }
+
+ } else if ($is_browse) {
+ return new Aphront404Response();
} 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.
foreach ($sources as $key => $source) {
// This can happen with composite sources like user or project, as well
// generic ones like NoOwner
if (!$source->getDatasourceApplicationClass()) {
continue;
}
if (!PhabricatorApplication::isClassInstalledForViewer(
$source->getDatasourceApplicationClass(),
$viewer)) {
unset($sources[$key]);
}
}
$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($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)', $class))
->appendChild($table);
return $this->buildApplicationPage(
array(
$form_box,
$result_box,
),
array(
'title' => pht('Typeahead Results'),
'device' => false,
));
}
}
diff --git a/src/applications/typeahead/datasource/PhabricatorTypeaheadCompositeDatasource.php b/src/applications/typeahead/datasource/PhabricatorTypeaheadCompositeDatasource.php
index 9c34af71c7..8990460505 100644
--- a/src/applications/typeahead/datasource/PhabricatorTypeaheadCompositeDatasource.php
+++ b/src/applications/typeahead/datasource/PhabricatorTypeaheadCompositeDatasource.php
@@ -1,49 +1,66 @@
<?php
abstract class PhabricatorTypeaheadCompositeDatasource
extends PhabricatorTypeaheadDatasource {
abstract public function getComponentDatasources();
public function getDatasourceApplicationClass() {
return null;
}
public function loadResults() {
+ $offset = $this->getOffset();
+ $limit = $this->getLimit();
+
$results = array();
foreach ($this->getUsableDatasources() as $source) {
$source
->setRawQuery($this->getRawQuery())
->setQuery($this->getQuery())
- ->setViewer($this->getViewer())
- ->setLimit($this->getLimit());
+ ->setViewer($this->getViewer());
+
+ if ($limit) {
+ $source->setLimit($offset + $limit);
+ }
$results[] = $source->loadResults();
}
- return array_mergev($results);
+
+ $results = array_mergev($results);
+ $results = msort($results, 'getName');
+
+ if ($offset || $limit) {
+ if (!$limit) {
+ $limit = count($results);
+ }
+ $results = array_slice($results, $offset, $limit, $preserve_keys = true);
+ }
+
+ return $results;
}
private function getUsableDatasources() {
$sources = $this->getComponentDatasources();
$usable = array();
foreach ($sources as $source) {
$application_class = $source->getDatasourceApplicationClass();
if ($application_class) {
$result = id(new PhabricatorApplicationQuery())
->setViewer($this->getViewer())
->withClasses(array($application_class))
->execute();
if (!$result) {
continue;
}
}
$usable[] = $source;
}
return $usable;
}
}
diff --git a/src/applications/typeahead/datasource/PhabricatorTypeaheadDatasource.php b/src/applications/typeahead/datasource/PhabricatorTypeaheadDatasource.php
index d08ea87685..ac29954fff 100644
--- a/src/applications/typeahead/datasource/PhabricatorTypeaheadDatasource.php
+++ b/src/applications/typeahead/datasource/PhabricatorTypeaheadDatasource.php
@@ -1,81 +1,91 @@
<?php
abstract class PhabricatorTypeaheadDatasource extends Phobject {
private $viewer;
private $query;
private $rawQuery;
+ private $offset;
private $limit;
private $parameters = array();
public function setLimit($limit) {
$this->limit = $limit;
return $this;
}
public function getLimit() {
return $this->limit;
}
+ public function setOffset($offset) {
+ $this->offset = $offset;
+ return $this;
+ }
+
+ public function getOffset() {
+ return $this->offset;
+ }
+
public function setViewer(PhabricatorUser $viewer) {
$this->viewer = $viewer;
return $this;
}
public function getViewer() {
return $this->viewer;
}
public function setRawQuery($raw_query) {
$this->rawQuery = $raw_query;
return $this;
}
public function getRawQuery() {
return $this->rawQuery;
}
public function setQuery($query) {
$this->query = $query;
return $this;
}
public function getQuery() {
return $this->query;
}
public function setParameters(array $params) {
$this->parameters = $params;
return $this;
}
public function getParameters() {
return $this->parameters;
}
public function getParameter($name, $default = null) {
return idx($this->parameters, $name, $default);
}
public function getDatasourceURI() {
$uri = new PhutilURI('/typeahead/class/'.get_class($this).'/');
$uri->setQueryParams($this->parameters);
return (string)$uri;
}
abstract public function getPlaceholderText();
abstract public function getDatasourceApplicationClass();
abstract public function loadResults();
public static function tokenizeString($string) {
$string = phutil_utf8_strtolower($string);
$string = trim($string);
if (!strlen($string)) {
return array();
}
$tokens = preg_split('/\s+|[-\[\]]/', $string);
return array_unique($tokens);
}
}
diff --git a/src/applications/typeahead/storage/PhabricatorTypeaheadResult.php b/src/applications/typeahead/storage/PhabricatorTypeaheadResult.php
index 37aa314ce9..4820a23e8c 100644
--- a/src/applications/typeahead/storage/PhabricatorTypeaheadResult.php
+++ b/src/applications/typeahead/storage/PhabricatorTypeaheadResult.php
@@ -1,120 +1,124 @@
<?php
final class PhabricatorTypeaheadResult {
private $name;
private $uri;
private $phid;
private $priorityString;
private $displayName;
private $displayType;
private $imageURI;
private $priorityType;
private $imageSprite;
private $icon;
private $closed;
public function setIcon($icon) {
$this->icon = $icon;
return $this;
}
public function setName($name) {
$this->name = $name;
return $this;
}
public function setURI($uri) {
$this->uri = $uri;
return $this;
}
public function setPHID($phid) {
$this->phid = $phid;
return $this;
}
public function setPriorityString($priority_string) {
$this->priorityString = $priority_string;
return $this;
}
public function setDisplayName($display_name) {
$this->displayName = $display_name;
return $this;
}
public function setDisplayType($display_type) {
$this->displayType = $display_type;
return $this;
}
public function setImageURI($image_uri) {
$this->imageURI = $image_uri;
return $this;
}
public function setPriorityType($priority_type) {
$this->priorityType = $priority_type;
return $this;
}
public function setImageSprite($image_sprite) {
$this->imageSprite = $image_sprite;
return $this;
}
public function setClosed($closed) {
$this->closed = $closed;
return $this;
}
+ public function getName() {
+ return $this->name;
+ }
+
public function getWireFormat() {
$data = array(
$this->name,
$this->uri ? (string)$this->uri : null,
$this->phid,
$this->priorityString,
$this->displayName,
$this->displayType,
$this->imageURI ? (string)$this->imageURI : null,
$this->priorityType,
($this->icon === null) ? $this->getDefaultIcon() : $this->icon,
$this->closed,
$this->imageSprite ? (string)$this->imageSprite : null,
);
while (end($data) === null) {
array_pop($data);
}
return $data;
}
/**
* If the datasource did not specify an icon explicitly, try to select a
* default based on PHID type.
*/
private function getDefaultIcon() {
static $icon_map;
if ($icon_map === null) {
$types = PhabricatorPHIDType::getAllTypes();
$map = array();
foreach ($types as $type) {
$icon = $type->getTypeIcon();
if ($icon !== null) {
$map[$type->getTypeConstant()] = "{$icon} bluegrey";
}
}
$icon_map = $map;
}
$phid_type = phid_get_type($this->phid);
if (isset($icon_map[$phid_type])) {
return $icon_map[$phid_type];
}
return null;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Jul 3, 7:19 PM (4 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
166245
Default Alt Text
(14 KB)

Event Timeline