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 @@ -4126,6 +4126,7 @@ 'PhabricatorXHProfApplication' => 'applications/xhprof/application/PhabricatorXHProfApplication.php', 'PhabricatorXHProfController' => 'applications/xhprof/controller/PhabricatorXHProfController.php', 'PhabricatorXHProfDAO' => 'applications/xhprof/storage/PhabricatorXHProfDAO.php', + 'PhabricatorXHProfDropController' => 'applications/xhprof/controller/PhabricatorXHProfDropController.php', 'PhabricatorXHProfProfileController' => 'applications/xhprof/controller/PhabricatorXHProfProfileController.php', 'PhabricatorXHProfProfileSymbolView' => 'applications/xhprof/view/PhabricatorXHProfProfileSymbolView.php', 'PhabricatorXHProfProfileTopLevelView' => 'applications/xhprof/view/PhabricatorXHProfProfileTopLevelView.php', @@ -9440,6 +9441,7 @@ 'PhabricatorXHProfApplication' => 'PhabricatorApplication', 'PhabricatorXHProfController' => 'PhabricatorController', 'PhabricatorXHProfDAO' => 'PhabricatorLiskDAO', + 'PhabricatorXHProfDropController' => 'PhabricatorXHProfController', 'PhabricatorXHProfProfileController' => 'PhabricatorXHProfController', 'PhabricatorXHProfProfileSymbolView' => 'PhabricatorXHProfProfileView', 'PhabricatorXHProfProfileTopLevelView' => 'PhabricatorXHProfProfileView', diff --git a/src/applications/xhprof/application/PhabricatorXHProfApplication.php b/src/applications/xhprof/application/PhabricatorXHProfApplication.php --- a/src/applications/xhprof/application/PhabricatorXHProfApplication.php +++ b/src/applications/xhprof/application/PhabricatorXHProfApplication.php @@ -32,6 +32,7 @@ '' => 'PhabricatorXHProfSampleListController', 'list/(?P[^/]+)/' => 'PhabricatorXHProfSampleListController', 'profile/(?P[^/]+)/' => 'PhabricatorXHProfProfileController', + 'import/drop/' => 'PhabricatorXHProfDropController', ), ); } diff --git a/src/applications/xhprof/controller/PhabricatorXHProfDropController.php b/src/applications/xhprof/controller/PhabricatorXHProfDropController.php new file mode 100644 --- /dev/null +++ b/src/applications/xhprof/controller/PhabricatorXHProfDropController.php @@ -0,0 +1,54 @@ +getViewer(); + + if (!$request->validateCSRF()) { + return new Aphront400Response(); + } + + $cancel_uri = $this->getApplicationURI(); + + $ids = $request->getStrList('h'); + if ($ids) { + $files = id(new PhabricatorFileQuery()) + ->setViewer($viewer) + ->withIDs($ids) + ->setRaisePolicyExceptions(true) + ->execute(); + } else { + $files = array(); + } + + if (!$files) { + return $this->newDialog() + ->setTitle(pht('Nothing Uploaded')) + ->appendParagraph( + pht('Drag and drop .xhprof files to import them.')) + ->addCancelButton($cancel_uri, pht('Done')); + } + + $samples = array(); + foreach ($files as $file) { + $sample = PhabricatorXHProfSample::initializeNewSample() + ->setFilePHID($file->getPHID()) + ->setUserPHID($viewer->getPHID()) + ->save(); + + $samples[] = $sample; + } + + if (count($samples) == 1) { + $event = head($samples); + $next_uri = $event->getURI(); + } else { + $next_uri = $this->getApplicationURI(); + } + + return id(new AphrontRedirectResponse())->setURI($next_uri); + } + +} diff --git a/src/applications/xhprof/query/PhabricatorXHProfSampleSearchEngine.php b/src/applications/xhprof/query/PhabricatorXHProfSampleSearchEngine.php --- a/src/applications/xhprof/query/PhabricatorXHProfSampleSearchEngine.php +++ b/src/applications/xhprof/query/PhabricatorXHProfSampleSearchEngine.php @@ -63,10 +63,13 @@ $item = id(new PHUIObjectItemView()) ->setObjectName($sample->getID()) - ->setHeader($sample->getRequestPath()) - ->setHref($this->getApplicationURI('profile/'.$file_phid.'/')) - ->addAttribute( - number_format($sample->getUsTotal())." \xCE\xBCs"); + ->setHeader($sample->getDisplayName()) + ->setHref($sample->getURI()); + + $us_total = $sample->getUsTotal(); + if ($us_total) { + $item->addAttribute(pht("%s \xCE\xBCs", new PhutilNumber($us_total))); + } if ($sample->getController()) { $item->addAttribute($sample->getController()); @@ -88,10 +91,30 @@ $list->addItem($item); } - $result = new PhabricatorApplicationSearchResultView(); - $result->setObjectList($list); + return $this->newResultView() + ->setObjectList($list); + } + + + private function newResultView($content = null) { + // If we aren't rendering a dashboard panel, activate global drag-and-drop + // so you can import profiles by dropping them into the list. + + if (!$this->isPanelContext()) { + $drop_upload = id(new PhabricatorGlobalUploadTargetView()) + ->setViewer($this->requireViewer()) + ->setHintText("\xE2\x87\xAA ".pht('Drop .xhprof Files to Import')) + ->setSubmitURI('/xhprof/import/drop/') + ->setViewPolicy(PhabricatorPolicies::POLICY_NOONE); + + $content = array( + $drop_upload, + $content, + ); + } - return $result; + return id(new PhabricatorApplicationSearchResultView()) + ->setContent($content); } } 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 @@ -12,6 +12,12 @@ protected $controller; protected $userPHID; + public static function initializeNewSample() { + return id(new self()) + ->setUsTotal(0) + ->setSampleRate(0); + } + protected function getConfiguration() { return array( self::CONFIG_COLUMN_SCHEMA => array( @@ -31,6 +37,19 @@ ) + parent::getConfiguration(); } + public function getURI() { + return '/xhprof/profile/'.$this->getFilePHID().'/'; + } + + public function getDisplayName() { + $request_path = $this->getRequestPath(); + if (strlen($request_path)) { + return $request_path; + } + + return pht('Unnamed Sample'); + } + /* -( PhabricatorPolicyInterface )----------------------------------------- */