Path: blob/master/src/applications/maniphest/query/ManiphestTaskSearchEngine.php
12256 views
<?php12final class ManiphestTaskSearchEngine3extends PhabricatorApplicationSearchEngine {45private $showBatchControls;6private $baseURI;7private $isBoardView;89public function setIsBoardView($is_board_view) {10$this->isBoardView = $is_board_view;11return $this;12}1314public function getIsBoardView() {15return $this->isBoardView;16}1718public function setBaseURI($base_uri) {19$this->baseURI = $base_uri;20return $this;21}2223public function getBaseURI() {24return $this->baseURI;25}2627public function setShowBatchControls($show_batch_controls) {28$this->showBatchControls = $show_batch_controls;29return $this;30}3132public function getResultTypeDescription() {33return pht('Maniphest Tasks');34}3536public function getApplicationClassName() {37return 'PhabricatorManiphestApplication';38}3940public function newQuery() {41return id(new ManiphestTaskQuery())42->needProjectPHIDs(true);43}4445protected function buildCustomSearchFields() {46// Hide the "Subtypes" constraint from the web UI if the install only47// defines one task subtype, since it isn't of any use in this case.48$subtype_map = id(new ManiphestTask())->newEditEngineSubtypeMap();49$hide_subtypes = ($subtype_map->getCount() == 1);5051return array(52id(new PhabricatorOwnersSearchField())53->setLabel(pht('Assigned To'))54->setKey('assignedPHIDs')55->setConduitKey('assigned')56->setAliases(array('assigned'))57->setDescription(58pht('Search for tasks owned by a user from a list.')),59id(new PhabricatorUsersSearchField())60->setLabel(pht('Authors'))61->setKey('authorPHIDs')62->setAliases(array('author', 'authors'))63->setDescription(64pht('Search for tasks with given authors.')),65id(new PhabricatorSearchDatasourceField())66->setLabel(pht('Statuses'))67->setKey('statuses')68->setAliases(array('status'))69->setDescription(70pht('Search for tasks with given statuses.'))71->setDatasource(new ManiphestTaskStatusFunctionDatasource()),72id(new PhabricatorSearchDatasourceField())73->setLabel(pht('Priorities'))74->setKey('priorities')75->setAliases(array('priority'))76->setDescription(77pht('Search for tasks with given priorities.'))78->setConduitParameterType(new ConduitIntListParameterType())79->setDatasource(new ManiphestTaskPriorityDatasource()),80id(new PhabricatorSearchDatasourceField())81->setLabel(pht('Subtypes'))82->setKey('subtypes')83->setAliases(array('subtype'))84->setDescription(85pht('Search for tasks with given subtypes.'))86->setDatasource(new ManiphestTaskSubtypeDatasource())87->setIsHidden($hide_subtypes),88id(new PhabricatorPHIDsSearchField())89->setLabel(pht('Columns'))90->setKey('columnPHIDs')91->setAliases(array('column', 'columnPHID', 'columns')),92id(new PhabricatorSearchThreeStateField())93->setLabel(pht('Open Parents'))94->setKey('hasParents')95->setAliases(array('blocking'))96->setOptions(97pht('(Show All)'),98pht('Show Only Tasks With Open Parents'),99pht('Show Only Tasks Without Open Parents')),100id(new PhabricatorSearchThreeStateField())101->setLabel(pht('Open Subtasks'))102->setKey('hasSubtasks')103->setAliases(array('blocked'))104->setOptions(105pht('(Show All)'),106pht('Show Only Tasks With Open Subtasks'),107pht('Show Only Tasks Without Open Subtasks')),108id(new PhabricatorIDsSearchField())109->setLabel(pht('Parent IDs'))110->setKey('parentIDs')111->setAliases(array('parentID')),112id(new PhabricatorIDsSearchField())113->setLabel(pht('Subtask IDs'))114->setKey('subtaskIDs')115->setAliases(array('subtaskID')),116id(new PhabricatorSearchSelectField())117->setLabel(pht('Group By'))118->setKey('group')119->setOptions($this->getGroupOptions()),120id(new PhabricatorSearchDateField())121->setLabel(pht('Created After'))122->setKey('createdStart'),123id(new PhabricatorSearchDateField())124->setLabel(pht('Created Before'))125->setKey('createdEnd'),126id(new PhabricatorSearchDateField())127->setLabel(pht('Updated After'))128->setKey('modifiedStart'),129id(new PhabricatorSearchDateField())130->setLabel(pht('Updated Before'))131->setKey('modifiedEnd'),132id(new PhabricatorSearchDateField())133->setLabel(pht('Closed After'))134->setKey('closedStart'),135id(new PhabricatorSearchDateField())136->setLabel(pht('Closed Before'))137->setKey('closedEnd'),138id(new PhabricatorUsersSearchField())139->setLabel(pht('Closed By'))140->setKey('closerPHIDs')141->setAliases(array('closer', 'closerPHID', 'closers'))142->setDescription(pht('Search for tasks closed by certain users.')),143id(new PhabricatorSearchTextField())144->setLabel(pht('Page Size'))145->setKey('limit'),146);147}148149protected function getDefaultFieldOrder() {150return array(151'assignedPHIDs',152'projectPHIDs',153'authorPHIDs',154'subscriberPHIDs',155'statuses',156'priorities',157'subtypes',158'hasParents',159'hasSubtasks',160'parentIDs',161'subtaskIDs',162'group',163'order',164'ids',165'...',166'createdStart',167'createdEnd',168'modifiedStart',169'modifiedEnd',170'closedStart',171'closedEnd',172'closerPHIDs',173'limit',174);175}176177protected function getHiddenFields() {178$keys = array();179180if ($this->getIsBoardView()) {181$keys[] = 'group';182$keys[] = 'order';183$keys[] = 'limit';184}185186return $keys;187}188189protected function buildQueryFromParameters(array $map) {190$query = $this->newQuery();191192if ($map['assignedPHIDs']) {193$query->withOwners($map['assignedPHIDs']);194}195196if ($map['authorPHIDs']) {197$query->withAuthors($map['authorPHIDs']);198}199200if ($map['statuses']) {201$query->withStatuses($map['statuses']);202}203204if ($map['priorities']) {205$query->withPriorities($map['priorities']);206}207208if ($map['subtypes']) {209$query->withSubtypes($map['subtypes']);210}211212if ($map['createdStart']) {213$query->withDateCreatedAfter($map['createdStart']);214}215216if ($map['createdEnd']) {217$query->withDateCreatedBefore($map['createdEnd']);218}219220if ($map['modifiedStart']) {221$query->withDateModifiedAfter($map['modifiedStart']);222}223224if ($map['modifiedEnd']) {225$query->withDateModifiedBefore($map['modifiedEnd']);226}227228if ($map['closedStart'] || $map['closedEnd']) {229$query->withClosedEpochBetween($map['closedStart'], $map['closedEnd']);230}231232if ($map['closerPHIDs']) {233$query->withCloserPHIDs($map['closerPHIDs']);234}235236if ($map['hasParents'] !== null) {237$query->withOpenParents($map['hasParents']);238}239240if ($map['hasSubtasks'] !== null) {241$query->withOpenSubtasks($map['hasSubtasks']);242}243244if ($map['parentIDs']) {245$query->withParentTaskIDs($map['parentIDs']);246}247248if ($map['subtaskIDs']) {249$query->withSubtaskIDs($map['subtaskIDs']);250}251252if ($map['columnPHIDs']) {253$query->withColumnPHIDs($map['columnPHIDs']);254}255256$group = idx($map, 'group');257$group = idx($this->getGroupValues(), $group);258if ($group) {259$query->setGroupBy($group);260}261262if ($map['ids']) {263$ids = $map['ids'];264foreach ($ids as $key => $id) {265$id = trim($id, ' Tt');266if (!$id || !is_numeric($id)) {267unset($ids[$key]);268} else {269$ids[$key] = $id;270}271}272273if ($ids) {274$query->withIDs($ids);275}276}277278return $query;279}280281protected function getURI($path) {282if ($this->baseURI) {283return $this->baseURI.$path;284}285return '/maniphest/'.$path;286}287288protected function getBuiltinQueryNames() {289$names = array();290291if ($this->requireViewer()->isLoggedIn()) {292$names['assigned'] = pht('Assigned');293$names['authored'] = pht('Authored');294$names['subscribed'] = pht('Subscribed');295}296297$names['open'] = pht('Open Tasks');298$names['all'] = pht('All Tasks');299300return $names;301}302303public function buildSavedQueryFromBuiltin($query_key) {304305$query = $this->newSavedQuery();306$query->setQueryKey($query_key);307308$viewer_phid = $this->requireViewer()->getPHID();309310switch ($query_key) {311case 'all':312return $query;313case 'assigned':314return $query315->setParameter('assignedPHIDs', array($viewer_phid))316->setParameter(317'statuses',318ManiphestTaskStatus::getOpenStatusConstants());319case 'subscribed':320return $query321->setParameter('subscriberPHIDs', array($viewer_phid))322->setParameter(323'statuses',324ManiphestTaskStatus::getOpenStatusConstants());325case 'open':326return $query327->setParameter(328'statuses',329ManiphestTaskStatus::getOpenStatusConstants());330case 'authored':331return $query332->setParameter('authorPHIDs', array($viewer_phid))333->setParameter('order', 'created')334->setParameter('group', 'none');335}336337return parent::buildSavedQueryFromBuiltin($query_key);338}339340private function getGroupOptions() {341return array(342'priority' => pht('Priority'),343'assigned' => pht('Assigned'),344'status' => pht('Status'),345'project' => pht('Project'),346'none' => pht('None'),347);348}349350private function getGroupValues() {351return array(352'priority' => ManiphestTaskQuery::GROUP_PRIORITY,353'assigned' => ManiphestTaskQuery::GROUP_OWNER,354'status' => ManiphestTaskQuery::GROUP_STATUS,355'project' => ManiphestTaskQuery::GROUP_PROJECT,356'none' => ManiphestTaskQuery::GROUP_NONE,357);358}359360protected function renderResultList(361array $tasks,362PhabricatorSavedQuery $saved,363array $handles) {364365$viewer = $this->requireViewer();366367if ($this->isPanelContext()) {368$can_bulk_edit = false;369} else {370$can_bulk_edit = PhabricatorPolicyFilter::hasCapability(371$viewer,372$this->getApplication(),373ManiphestBulkEditCapability::CAPABILITY);374}375376$list = id(new ManiphestTaskResultListView())377->setUser($viewer)378->setTasks($tasks)379->setSavedQuery($saved)380->setCanBatchEdit($can_bulk_edit)381->setShowBatchControls($this->showBatchControls);382383$result = new PhabricatorApplicationSearchResultView();384$result->setContent($list);385386return $result;387}388389protected function willUseSavedQuery(PhabricatorSavedQuery $saved) {390391// The 'withUnassigned' parameter may be present in old saved queries from392// before parameterized typeaheads, and is retained for compatibility. We393// could remove it by migrating old saved queries.394$assigned_phids = $saved->getParameter('assignedPHIDs', array());395if ($saved->getParameter('withUnassigned')) {396$assigned_phids[] = PhabricatorPeopleNoOwnerDatasource::FUNCTION_TOKEN;397}398$saved->setParameter('assignedPHIDs', $assigned_phids);399400// The 'projects' and other parameters may be present in old saved queries401// from before parameterized typeaheads.402$project_phids = $saved->getParameter('projectPHIDs', array());403404$old = $saved->getParameter('projects', array());405foreach ($old as $phid) {406$project_phids[] = $phid;407}408409$all = $saved->getParameter('allProjectPHIDs', array());410foreach ($all as $phid) {411$project_phids[] = $phid;412}413414$any = $saved->getParameter('anyProjectPHIDs', array());415foreach ($any as $phid) {416$project_phids[] = 'any('.$phid.')';417}418419$not = $saved->getParameter('excludeProjectPHIDs', array());420foreach ($not as $phid) {421$project_phids[] = 'not('.$phid.')';422}423424$users = $saved->getParameter('userProjectPHIDs', array());425foreach ($users as $phid) {426$project_phids[] = 'projects('.$phid.')';427}428429$no = $saved->getParameter('withNoProject');430if ($no) {431$project_phids[] = 'null()';432}433434$saved->setParameter('projectPHIDs', $project_phids);435}436437protected function getNewUserBody() {438$viewer = $this->requireViewer();439440$create_button = id(new ManiphestEditEngine())441->setViewer($viewer)442->newNUXBUtton(pht('Create a Task'));443444$icon = $this->getApplication()->getIcon();445$app_name = $this->getApplication()->getName();446$view = id(new PHUIBigInfoView())447->setIcon($icon)448->setTitle(pht('Welcome to %s', $app_name))449->setDescription(450pht('Use Maniphest to track bugs, features, todos, or anything else '.451'you need to get done. Tasks assigned to you will appear here.'))452->addAction($create_button);453454return $view;455}456457458protected function newExportFields() {459$fields = array(460id(new PhabricatorStringExportField())461->setKey('monogram')462->setLabel(pht('Monogram')),463id(new PhabricatorPHIDExportField())464->setKey('authorPHID')465->setLabel(pht('Author PHID')),466id(new PhabricatorStringExportField())467->setKey('author')468->setLabel(pht('Author')),469id(new PhabricatorPHIDExportField())470->setKey('ownerPHID')471->setLabel(pht('Owner PHID')),472id(new PhabricatorStringExportField())473->setKey('owner')474->setLabel(pht('Owner')),475id(new PhabricatorStringExportField())476->setKey('status')477->setLabel(pht('Status')),478id(new PhabricatorStringExportField())479->setKey('statusName')480->setLabel(pht('Status Name')),481id(new PhabricatorEpochExportField())482->setKey('dateClosed')483->setLabel(pht('Date Closed')),484id(new PhabricatorPHIDExportField())485->setKey('closerPHID')486->setLabel(pht('Closer PHID')),487id(new PhabricatorStringExportField())488->setKey('closer')489->setLabel(pht('Closer')),490id(new PhabricatorStringExportField())491->setKey('priority')492->setLabel(pht('Priority')),493id(new PhabricatorStringExportField())494->setKey('priorityName')495->setLabel(pht('Priority Name')),496id(new PhabricatorStringExportField())497->setKey('subtype')498->setLabel('Subtype'),499id(new PhabricatorURIExportField())500->setKey('uri')501->setLabel(pht('URI')),502id(new PhabricatorStringExportField())503->setKey('title')504->setLabel(pht('Title')),505id(new PhabricatorStringExportField())506->setKey('description')507->setLabel(pht('Description')),508);509510if (ManiphestTaskPoints::getIsEnabled()) {511$fields[] = id(new PhabricatorDoubleExportField())512->setKey('points')513->setLabel('Points');514}515516return $fields;517}518519protected function newExportData(array $tasks) {520$viewer = $this->requireViewer();521522$phids = array();523foreach ($tasks as $task) {524$phids[] = $task->getAuthorPHID();525$phids[] = $task->getOwnerPHID();526$phids[] = $task->getCloserPHID();527}528$handles = $viewer->loadHandles($phids);529530$export = array();531foreach ($tasks as $task) {532533$author_phid = $task->getAuthorPHID();534if ($author_phid) {535$author_name = $handles[$author_phid]->getName();536} else {537$author_name = null;538}539540$owner_phid = $task->getOwnerPHID();541if ($owner_phid) {542$owner_name = $handles[$owner_phid]->getName();543} else {544$owner_name = null;545}546547$closer_phid = $task->getCloserPHID();548if ($closer_phid) {549$closer_name = $handles[$closer_phid]->getName();550} else {551$closer_name = null;552}553554$status_value = $task->getStatus();555$status_name = ManiphestTaskStatus::getTaskStatusName($status_value);556557$priority_value = $task->getPriority();558$priority_name = ManiphestTaskPriority::getTaskPriorityName(559$priority_value);560561$export[] = array(562'monogram' => $task->getMonogram(),563'authorPHID' => $author_phid,564'author' => $author_name,565'ownerPHID' => $owner_phid,566'owner' => $owner_name,567'status' => $status_value,568'statusName' => $status_name,569'priority' => $priority_value,570'priorityName' => $priority_name,571'points' => $task->getPoints(),572'subtype' => $task->getSubtype(),573'title' => $task->getTitle(),574'uri' => PhabricatorEnv::getProductionURI($task->getURI()),575'description' => $task->getDescription(),576'dateClosed' => $task->getClosedEpoch(),577'closerPHID' => $closer_phid,578'closer' => $closer_name,579);580}581582return $export;583}584}585586587