[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/search/controller/ -> PhabricatorApplicationSearchController.php (source)

   1  <?php
   2  
   3  final class PhabricatorApplicationSearchController
   4    extends PhabricatorSearchBaseController {
   5  
   6    private $searchEngine;
   7    private $navigation;
   8    private $queryKey;
   9    private $preface;
  10  
  11    public function setPreface($preface) {
  12      $this->preface = $preface;
  13      return $this;
  14    }
  15  
  16    public function getPreface() {
  17      return $this->preface;
  18    }
  19  
  20    public function setQueryKey($query_key) {
  21      $this->queryKey = $query_key;
  22      return $this;
  23    }
  24  
  25    protected function getQueryKey() {
  26      return $this->queryKey;
  27    }
  28  
  29    public function setNavigation(AphrontSideNavFilterView $navigation) {
  30      $this->navigation = $navigation;
  31      return $this;
  32    }
  33  
  34    protected function getNavigation() {
  35      return $this->navigation;
  36    }
  37  
  38    public function setSearchEngine(
  39      PhabricatorApplicationSearchEngine $search_engine) {
  40      $this->searchEngine = $search_engine;
  41      return $this;
  42    }
  43  
  44    protected function getSearchEngine() {
  45      return $this->searchEngine;
  46    }
  47  
  48    protected function validateDelegatingController() {
  49      $parent = $this->getDelegatingController();
  50  
  51      if (!$parent) {
  52        throw new Exception(
  53          'You must delegate to this controller, not invoke it directly.');
  54      }
  55  
  56      $engine = $this->getSearchEngine();
  57      if (!$engine) {
  58        throw new Exception(
  59          'Call setEngine() before delegating to this controller!');
  60      }
  61  
  62      $nav = $this->getNavigation();
  63      if (!$nav) {
  64        throw new Exception(
  65          'Call setNavigation() before delegating to this controller!');
  66      }
  67  
  68      $engine->setViewer($this->getRequest()->getUser());
  69  
  70      $parent = $this->getDelegatingController();
  71    }
  72  
  73    public function processRequest() {
  74      $this->validateDelegatingController();
  75  
  76      $key = $this->getQueryKey();
  77      if ($key == 'edit') {
  78        return $this->processEditRequest();
  79      } else {
  80        return $this->processSearchRequest();
  81      }
  82    }
  83  
  84    private function processSearchRequest() {
  85      $parent = $this->getDelegatingController();
  86      $request = $this->getRequest();
  87      $user = $request->getUser();
  88      $engine = $this->getSearchEngine();
  89      $nav = $this->getNavigation();
  90  
  91      if ($request->isFormPost()) {
  92        $saved_query = $engine->buildSavedQueryFromRequest($request);
  93        $engine->saveQuery($saved_query);
  94        return id(new AphrontRedirectResponse())->setURI(
  95          $engine->getQueryResultsPageURI($saved_query->getQueryKey()).'#R');
  96      }
  97  
  98      $named_query = null;
  99      $run_query = true;
 100      $query_key = $this->queryKey;
 101      if ($this->queryKey == 'advanced') {
 102        $run_query = false;
 103        $query_key = $request->getStr('query');
 104      } else if (!strlen($this->queryKey)) {
 105        $found_query_data = false;
 106  
 107        if ($request->isHTTPGet()) {
 108          // If this is a GET request and it has some query data, don't
 109          // do anything unless it's only before= or after=. We'll build and
 110          // execute a query from it below. This allows external tools to build
 111          // URIs like "/query/?users=a,b".
 112          $pt_data = $request->getPassthroughRequestData();
 113  
 114          foreach ($pt_data as $pt_key => $pt_value) {
 115            if ($pt_key != 'before' && $pt_key != 'after') {
 116              $found_query_data = true;
 117              break;
 118            }
 119          }
 120        }
 121  
 122        if (!$found_query_data) {
 123          // Otherwise, there's no query data so just run the user's default
 124          // query for this application.
 125          $query_key = head_key($engine->loadEnabledNamedQueries());
 126        }
 127      }
 128  
 129      if ($engine->isBuiltinQuery($query_key)) {
 130        $saved_query = $engine->buildSavedQueryFromBuiltin($query_key);
 131        $named_query = idx($engine->loadEnabledNamedQueries(), $query_key);
 132      } else if ($query_key) {
 133        $saved_query = id(new PhabricatorSavedQueryQuery())
 134          ->setViewer($user)
 135          ->withQueryKeys(array($query_key))
 136          ->executeOne();
 137  
 138        if (!$saved_query) {
 139          return new Aphront404Response();
 140        }
 141  
 142        $named_query = idx($engine->loadEnabledNamedQueries(), $query_key);
 143      } else {
 144        $saved_query = $engine->buildSavedQueryFromRequest($request);
 145  
 146        // Save the query to generate a query key, so "Save Custom Query..." and
 147        // other features like Maniphest's "Export..." work correctly.
 148        $engine->saveQuery($saved_query);
 149      }
 150  
 151      $nav->selectFilter(
 152        'query/'.$saved_query->getQueryKey(),
 153        'query/advanced');
 154  
 155      $form = id(new AphrontFormView())
 156        ->setUser($user)
 157        ->setAction($request->getPath());
 158  
 159      $engine->buildSearchForm($form, $saved_query);
 160  
 161      $errors = $engine->getErrors();
 162      if ($errors) {
 163        $run_query = false;
 164        $errors = id(new AphrontErrorView())
 165          ->setTitle(pht('Query Errors'))
 166          ->setErrors($errors);
 167      }
 168  
 169      $submit = id(new AphrontFormSubmitControl())
 170        ->setValue(pht('Execute Query'));
 171  
 172      if ($run_query && !$named_query && $user->isLoggedIn()) {
 173        $submit->addCancelButton(
 174          '/search/edit/'.$saved_query->getQueryKey().'/',
 175          pht('Save Custom Query...'));
 176      }
 177  
 178      // TODO: A "Create Dashboard Panel" action goes here somewhere once
 179      // we sort out T5307.
 180  
 181      $form->appendChild($submit);
 182      $filter_view = id(new AphrontListFilterView())->appendChild($form);
 183  
 184      if ($run_query && $named_query) {
 185        if ($named_query->getIsBuiltin()) {
 186          $description = pht(
 187            'Showing results for query "%s".',
 188            $named_query->getQueryName());
 189        } else {
 190          $description = pht(
 191            'Showing results for saved query "%s".',
 192            $named_query->getQueryName());
 193        }
 194  
 195        $filter_view->setCollapsed(
 196          pht('Edit Query...'),
 197          pht('Hide Query'),
 198          $description,
 199          $this->getApplicationURI('query/advanced/?query='.$query_key));
 200      }
 201  
 202      if ($this->getPreface()) {
 203        $nav->appendChild($this->getPreface());
 204      }
 205  
 206      $nav->appendChild($filter_view);
 207  
 208      if ($run_query) {
 209        $nav->appendChild(
 210          $anchor = id(new PhabricatorAnchorView())
 211            ->setAnchorName('R'));
 212  
 213        $query = $engine->buildQueryFromSavedQuery($saved_query);
 214  
 215        $pager = $engine->newPagerForSavedQuery($saved_query);
 216        $pager->readFromRequest($request);
 217  
 218        $objects = $engine->executeQuery($query, $pager);
 219  
 220        // TODO: To support Dashboard panels, rendering is moving into
 221        // SearchEngines. Move it all the way in and then get rid of this.
 222  
 223        $interface = 'PhabricatorApplicationSearchResultsControllerInterface';
 224        if ($parent instanceof $interface) {
 225          $list = $parent->renderResultsList($objects, $saved_query);
 226        } else {
 227          $engine->setRequest($request);
 228  
 229          $list = $engine->renderResults(
 230            $objects,
 231            $saved_query);
 232        }
 233  
 234        $nav->appendChild($list);
 235  
 236        // TODO: This is a bit hacky.
 237        if ($list instanceof PHUIObjectItemListView) {
 238          $list->setNoDataString(pht('No results found for this query.'));
 239          $list->setPager($pager);
 240        } else {
 241          if ($pager->willShowPagingControls()) {
 242            $pager_box = id(new PHUIBoxView())
 243              ->addPadding(PHUI::PADDING_MEDIUM)
 244              ->addMargin(PHUI::MARGIN_LARGE)
 245              ->setBorder(true)
 246              ->appendChild($pager);
 247            $nav->appendChild($pager_box);
 248          }
 249        }
 250      }
 251  
 252      if ($errors) {
 253        $nav->appendChild($errors);
 254      }
 255  
 256      if ($named_query) {
 257        $title = pht('Query: %s', $named_query->getQueryName());
 258      } else {
 259        $title = pht('Advanced Search');
 260      }
 261  
 262      $crumbs = $parent
 263        ->buildApplicationCrumbs()
 264        ->addTextCrumb($title);
 265  
 266      $nav->setCrumbs($crumbs);
 267  
 268      return $this->buildApplicationPage(
 269        $nav,
 270        array(
 271          'title' => $title,
 272        ));
 273    }
 274  
 275    private function processEditRequest() {
 276      $parent = $this->getDelegatingController();
 277      $request = $this->getRequest();
 278      $user = $request->getUser();
 279      $engine = $this->getSearchEngine();
 280      $nav = $this->getNavigation();
 281  
 282      $named_queries = $engine->loadAllNamedQueries();
 283  
 284      $list_id = celerity_generate_unique_node_id();
 285  
 286      $list = new PHUIObjectItemListView();
 287      $list->setUser($user);
 288      $list->setID($list_id);
 289  
 290      Javelin::initBehavior(
 291        'search-reorder-queries',
 292        array(
 293          'listID' => $list_id,
 294          'orderURI' => '/search/order/'.get_class($engine).'/',
 295        ));
 296  
 297      foreach ($named_queries as $named_query) {
 298        $class = get_class($engine);
 299        $key = $named_query->getQueryKey();
 300  
 301        $item = id(new PHUIObjectItemView())
 302          ->setHeader($named_query->getQueryName())
 303          ->setHref($engine->getQueryResultsPageURI($key));
 304  
 305        if ($named_query->getIsBuiltin() && $named_query->getIsDisabled()) {
 306          $icon = 'fa-plus';
 307        } else {
 308          $icon = 'fa-times';
 309        }
 310  
 311        $item->addAction(
 312          id(new PHUIListItemView())
 313            ->setIcon($icon)
 314            ->setHref('/search/delete/'.$key.'/'.$class.'/')
 315            ->setWorkflow(true));
 316  
 317        if ($named_query->getIsBuiltin()) {
 318          if ($named_query->getIsDisabled()) {
 319            $item->addIcon('fa-times lightgreytext', pht('Disabled'));
 320            $item->setDisabled(true);
 321          } else {
 322            $item->addIcon('fa-lock lightgreytext', pht('Builtin'));
 323          }
 324        } else {
 325          $item->addAction(
 326            id(new PHUIListItemView())
 327              ->setIcon('fa-pencil')
 328              ->setHref('/search/edit/'.$key.'/'));
 329        }
 330  
 331        $item->setGrippable(true);
 332        $item->addSigil('named-query');
 333        $item->setMetadata(
 334          array(
 335            'queryKey' => $named_query->getQueryKey(),
 336          ));
 337  
 338        $list->addItem($item);
 339      }
 340  
 341      $list->setNoDataString(pht('No saved queries.'));
 342  
 343      $crumbs = $parent
 344        ->buildApplicationCrumbs()
 345        ->addTextCrumb(pht('Saved Queries'), $engine->getQueryManagementURI());
 346  
 347      $nav->selectFilter('query/edit');
 348      $nav->setCrumbs($crumbs);
 349      $nav->appendChild($list);
 350  
 351      return $parent->buildApplicationPage(
 352        $nav,
 353        array(
 354          'title' => pht('Saved Queries'),
 355        ));
 356    }
 357  
 358    protected function buildApplicationMenu() {
 359      return $this->getDelegatingController()->buildApplicationMenu();
 360    }
 361  
 362  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1