Page MenuHomePhabricator

Allow third-party code to extend the list of functions that function datasources support
Closed, ResolvedPublic

Assigned To
None
Authored By
epriestley
Feb 14 2018, 4:56 PM
Referenced Files
F5431286: Screen Shot 2018-02-14 at 5.59.53 PM.png
Feb 15 2018, 2:01 AM
Tokens
"Dat Boi" token, awarded by jcox."Like" token, awarded by avivey.

Description

See PHI368. An install would like to be able to specify custom ad-hoc groups using typeahead functions, like people-named-jake().

We can support this by:

  • Lifting QuickSearchEngineExtension from D18760 up into DatasourceEngineExtension.
  • Probably doing the jump nav changes while touching this.
  • Adding a callback for providing additional function datasources.

This API may change when x-y-z() becomes x(y(z())). I plan to consider making this change first but likely give up on it.

Event Timeline

epriestley triaged this task as Normal priority.Feb 14 2018, 4:56 PM
epriestley created this task.
epriestley renamed this task from Modularize typeahead function datasources to Allow third-party code to extend the list of functions that function datasources support.Feb 14 2018, 11:29 PM

@avivey, heads up that I'm renaming PhabricatorQuickSearchEngineExtension to PhabricatorDatasourceEngineExtension. I'm leaving an empty subclass in master for now so that nothing breaks, but will delete it sooner or later, so rename QuickSearch to Datasource in your extends ... statements (and, ideally, class names) at some point before then to keep things working smoothly.

After D19089, you can probably emit a projects(people-named-jake()) token or whatever and have it work for some values of "work" and "whatever". Tentatively, it doesn't look like this needs a lot of API changes, so I'm going to move forward with the simple version of the original request.

Example usage (for simplicity, requires at least one user named "Jake" on your install to function correctly):

JakeDatasourceEngineExtension.php
<?php

final class JakeDatasourceEngineExtension
  extends PhabricatorDatasourceEngineExtension {

  public function newDatasourcesForCompositeDatasource(
    PhabricatorTypeaheadCompositeDatasource $datasource) {

    $can_extend =
      ($datasource instanceof PhabricatorPeopleUserFunctionDatasource) ||
      ($datasource instanceof PhabricatorPeopleOwnerDatasource);

    if (!$can_extend) {
      return array();
    }

    return array(
      new JakeDatasource(),
    );
  }

}
JakeDatasource.php
<?php

final class JakeDatasource
  extends PhabricatorTypeaheadDatasource {

  public function getBrowseTitle() {
    return pht('Browse Jakes');
  }

  public function getPlaceholderText() {
    return pht('Type users-named-jake()...');
  }

  public function getDatasourceApplicationClass() {
    return 'PhabricatorPeopleApplication';
  }

  public function getDatasourceFunctions() {
    return array(
      'users-named-jake' => array(
        'name' => pht('Users Named Jake'),
        'summary' => pht('Use users named Jake.'),
        'description' => pht(
          "This function allows you to select all users named Jake."),
      ),
    );
  }

  public function loadResults() {
    if ($this->getViewer()->getPHID()) {
      $results = array($this->renderJakeFunctionToken());
    } else {
      $results = array();
    }

    return $this->filterResultsAgainstTokens($results);
  }

  protected function evaluateFunction($function, array $argv_list) {
    $results = array();
    foreach ($argv_list as $argv) {
      foreach ($this->loadJakePHIDs() as $jake_phid) {
        $results[] = $jake_phid;
      }
    }
    return $results;
  }

  public function renderFunctionTokens($function, array $argv_list) {
    $tokens = array();
    foreach ($argv_list as $argv) {
      $tokens[] = PhabricatorTypeaheadTokenView::newFromTypeaheadResult(
        $this->renderJakeFunctionToken());
    }
    return $tokens;
  }

  private function renderJakeFunctionToken() {
    return $this->newFunctionResult()
      ->setName(pht('Users Named Jake'))
      ->setPHID('users-named-jake()')
      ->setIcon('fa-user')
      ->setUnique(true)
      ->addAttribute(pht('Select users named Jake.'));
  }

  private function loadJakePHIDs() {
    $users = id(new PhabricatorUser())->loadAllWhere(
      'realName LIKE %>',
      'Jake ');

    $jake_phids = mpull($users, 'getPHID');

    return array_values($jake_phids);
  }

}

Screen Shot 2018-02-14 at 5.59.53 PM.png (234×486 px, 17 KB)