diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -4132,6 +4132,8 @@ 'PhabricatorXHProfProfileView' => 'applications/xhprof/view/PhabricatorXHProfProfileView.php', 'PhabricatorXHProfSample' => 'applications/xhprof/storage/PhabricatorXHProfSample.php', 'PhabricatorXHProfSampleListController' => 'applications/xhprof/controller/PhabricatorXHProfSampleListController.php', + 'PhabricatorXHProfSampleQuery' => 'applications/xhprof/query/PhabricatorXHProfSampleQuery.php', + 'PhabricatorXHProfSampleSearchEngine' => 'applications/xhprof/query/PhabricatorXHProfSampleSearchEngine.php', 'PhabricatorYoutubeRemarkupRule' => 'infrastructure/markup/rule/PhabricatorYoutubeRemarkupRule.php', 'Phame404Response' => 'applications/phame/site/Phame404Response.php', 'PhameBlog' => 'applications/phame/storage/PhameBlog.php', @@ -9442,8 +9444,13 @@ 'PhabricatorXHProfProfileSymbolView' => 'PhabricatorXHProfProfileView', 'PhabricatorXHProfProfileTopLevelView' => 'PhabricatorXHProfProfileView', 'PhabricatorXHProfProfileView' => 'AphrontView', - 'PhabricatorXHProfSample' => 'PhabricatorXHProfDAO', + 'PhabricatorXHProfSample' => array( + 'PhabricatorXHProfDAO', + 'PhabricatorPolicyInterface', + ), 'PhabricatorXHProfSampleListController' => 'PhabricatorXHProfController', + 'PhabricatorXHProfSampleQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', + 'PhabricatorXHProfSampleSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorYoutubeRemarkupRule' => 'PhutilRemarkupRule', 'Phame404Response' => 'AphrontHTMLResponse', 'PhameBlog' => array( diff --git a/src/applications/xhprof/controller/PhabricatorXHProfSampleListController.php b/src/applications/xhprof/controller/PhabricatorXHProfSampleListController.php --- a/src/applications/xhprof/controller/PhabricatorXHProfSampleListController.php +++ b/src/applications/xhprof/controller/PhabricatorXHProfSampleListController.php @@ -8,91 +8,9 @@ } public function handleRequest(AphrontRequest $request) { - $viewer = $request->getViewer(); - $view = $request->getURIData('view'); - - if (!$view) { - $view = 'all'; - } - - $pager = new PHUIPagerView(); - $pager->setOffset($request->getInt('page')); - - switch ($view) { - case 'sampled': - $clause = 'sampleRate > 0'; - $show_type = false; - break; - case 'my-runs': - $clause = qsprintf( - id(new PhabricatorXHProfSample())->establishConnection('r'), - 'sampleRate = 0 AND userPHID = %s', - $request->getUser()->getPHID()); - $show_type = false; - break; - case 'manual': - $clause = 'sampleRate = 0'; - $show_type = false; - break; - case 'all': - default: - $clause = '1 = 1'; - $show_type = true; - break; - } - - $samples = id(new PhabricatorXHProfSample())->loadAllWhere( - '%Q ORDER BY id DESC LIMIT %d, %d', - $clause, - $pager->getOffset(), - $pager->getPageSize() + 1); - - $samples = $pager->sliceResults($samples); - $pager->setURI($request->getRequestURI(), 'page'); - - $list = new PHUIObjectItemListView(); - foreach ($samples as $sample) { - $file_phid = $sample->getFilePHID(); - - $item = id(new PHUIObjectItemView()) - ->setObjectName($sample->getID()) - ->setHeader($sample->getRequestPath()) - ->setHref($this->getApplicationURI('profile/'.$file_phid.'/')) - ->addAttribute( - number_format($sample->getUsTotal())." \xCE\xBCs"); - - if ($sample->getController()) { - $item->addAttribute($sample->getController()); - } - - $item->addAttribute($sample->getHostName()); - - $rate = $sample->getSampleRate(); - if ($rate == 0) { - $item->addIcon('flag-6', pht('Manual Run')); - } else { - $item->addIcon('flag-7', pht('Sampled (1/%d)', $rate)); - } - - $item->addIcon( - 'none', - phabricator_datetime($sample->getDateCreated(), $viewer)); - - $list->addItem($item); - } - - $list->setPager($pager); - $list->setNoDataString(pht('There are no profiling samples.')); - - $crumbs = $this->buildApplicationCrumbs(); - $crumbs->addTextCrumb(pht('XHProf Samples')); - - $title = pht('XHProf Samples'); - - return $this->newPage() - ->setTitle($title) - ->setCrumbs($crumbs) - ->appendChild($list); - + return id(new PhabricatorXHProfSampleSearchEngine()) + ->setController($this) + ->buildResponse(); } + } diff --git a/src/applications/xhprof/query/PhabricatorXHProfSampleQuery.php b/src/applications/xhprof/query/PhabricatorXHProfSampleQuery.php new file mode 100644 --- /dev/null +++ b/src/applications/xhprof/query/PhabricatorXHProfSampleQuery.php @@ -0,0 +1,51 @@ +ids = $ids; + return $this; + } + + public function withPHIDs(array $phids) { + $this->phids = $phids; + return $this; + } + + public function newResultObject() { + return new PhabricatorXHProfSample(); + } + + protected function loadPage() { + return $this->loadStandardPage($this->newResultObject()); + } + + protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) { + $where = parent::buildWhereClauseParts($conn); + + if ($this->ids !== null) { + $where[] = qsprintf( + $conn, + 'id IN (%Ld)', + $this->ids); + } + + if ($this->phids !== null) { + $where[] = qsprintf( + $conn, + 'phid IN (%Ls)', + $this->phids); + } + + return $where; + } + + public function getQueryApplicationClass() { + return 'PhabricatorXHProfApplication'; + } + +} diff --git a/src/applications/xhprof/query/PhabricatorXHProfSampleSearchEngine.php b/src/applications/xhprof/query/PhabricatorXHProfSampleSearchEngine.php new file mode 100644 --- /dev/null +++ b/src/applications/xhprof/query/PhabricatorXHProfSampleSearchEngine.php @@ -0,0 +1,97 @@ +newQuery(); + + return $query; + } + + protected function buildCustomSearchFields() { + return array(); + } + + protected function getURI($path) { + return '/xhprof/'.$path; + } + + protected function getBuiltinQueryNames() { + $names = array( + 'all' => pht('All Samples'), + ); + + return $names; + } + + public function buildSavedQueryFromBuiltin($query_key) { + $query = $this->newSavedQuery(); + $query->setQueryKey($query_key); + + switch ($query_key) { + case 'all': + return $query; + } + + return parent::buildSavedQueryFromBuiltin($query_key); + } + + protected function renderResultList( + array $samples, + PhabricatorSavedQuery $query, + array $handles) { + assert_instances_of($samples, 'PhabricatorXHProfSample'); + + $viewer = $this->requireViewer(); + + $list = new PHUIObjectItemListView(); + foreach ($samples as $sample) { + $file_phid = $sample->getFilePHID(); + + $item = id(new PHUIObjectItemView()) + ->setObjectName($sample->getID()) + ->setHeader($sample->getRequestPath()) + ->setHref($this->getApplicationURI('profile/'.$file_phid.'/')) + ->addAttribute( + number_format($sample->getUsTotal())." \xCE\xBCs"); + + if ($sample->getController()) { + $item->addAttribute($sample->getController()); + } + + $item->addAttribute($sample->getHostName()); + + $rate = $sample->getSampleRate(); + if ($rate == 0) { + $item->addIcon('flag-6', pht('Manual Run')); + } else { + $item->addIcon('flag-7', pht('Sampled (1/%d)', $rate)); + } + + $item->addIcon( + 'none', + phabricator_datetime($sample->getDateCreated(), $viewer)); + + $list->addItem($item); + } + + $result = new PhabricatorApplicationSearchResultView(); + $result->setObjectList($list); + + return $result; + } + +} diff --git a/src/applications/xhprof/storage/PhabricatorXHProfSample.php b/src/applications/xhprof/storage/PhabricatorXHProfSample.php --- a/src/applications/xhprof/storage/PhabricatorXHProfSample.php +++ b/src/applications/xhprof/storage/PhabricatorXHProfSample.php @@ -1,6 +1,8 @@