diff --git a/src/applications/countdown/query/PhabricatorCountdownQuery.php b/src/applications/countdown/query/PhabricatorCountdownQuery.php index 17fde126f8..e6c410ee49 100644 --- a/src/applications/countdown/query/PhabricatorCountdownQuery.php +++ b/src/applications/countdown/query/PhabricatorCountdownQuery.php @@ -1,77 +1,108 @@ ids = $ids; return $this; } public function withPHIDs(array $phids) { $this->phids = $phids; return $this; } public function withAuthorPHIDs(array $author_phids) { $this->authorPHIDs = $author_phids; return $this; } public function withUpcoming() { $this->upcoming = true; return $this; } protected function loadPage() { return $this->loadStandardPage($this->newResultObject()); } public function newResultObject() { return new PhabricatorCountdown(); } 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); } if ($this->authorPHIDs !== null) { $where[] = qsprintf( $conn, 'authorPHID in (%Ls)', $this->authorPHIDs); } if ($this->upcoming !== null) { $where[] = qsprintf( $conn, 'epoch >= %d', PhabricatorTime::getNow()); } return $where; } public function getQueryApplicationClass() { return 'PhabricatorCountdownApplication'; } + public function getBuiltinOrders() { + return array( + 'ending' => array( + 'vector' => array('-epoch', '-id'), + 'name' => pht('End Date (Past to Future)'), + ), + 'unending' => array( + 'vector' => array('epoch', 'id'), + 'name' => pht('End Date (Future to Past)'), + ), + ) + parent::getBuiltinOrders(); + } + + public function getOrderableColumns() { + return array( + 'epoch' => array( + 'table' => $this->getPrimaryTableAlias(), + 'column' => 'epoch', + 'type' => 'int', + ), + ) + parent::getOrderableColumns(); + } + + protected function getPagingValueMap($cursor, array $keys) { + $countdown = $this->loadCursorObject($cursor); + return array( + 'epoch' => $countdown->getEpoch(), + 'id' => $countdown->getID(), + ); + } + } diff --git a/src/applications/countdown/query/PhabricatorCountdownSearchEngine.php b/src/applications/countdown/query/PhabricatorCountdownSearchEngine.php index 79b329385a..93aec9a037 100644 --- a/src/applications/countdown/query/PhabricatorCountdownSearchEngine.php +++ b/src/applications/countdown/query/PhabricatorCountdownSearchEngine.php @@ -1,168 +1,166 @@ newQuery(); if ($map['authorPHIDs']) { $query->withAuthorPHIDs($map['authorPHIDs']); } if ($map['upcoming'] && $map['upcoming'][0] == 'upcoming') { $query->withUpcoming(); } return $query; } protected function buildCustomSearchFields() { - return array( - id(new PhabricatorUsersSearchField()) - ->setLabel(pht('Authors')) - ->setKey('authorPHIDs') - ->setAliases(array('author', 'authors')), - - id(new PhabricatorSearchCheckboxesField()) - ->setKey('upcoming') - ->setOptions(array( + id(new PhabricatorUsersSearchField()) + ->setLabel(pht('Authors')) + ->setKey('authorPHIDs') + ->setAliases(array('author', 'authors')), + id(new PhabricatorSearchCheckboxesField()) + ->setKey('upcoming') + ->setOptions( + array( 'upcoming' => pht('Show only upcoming countdowns.'), )), - ); - + ); } protected function getURI($path) { return '/countdown/'.$path; } protected function getBuiltinQueryNames() { $names = array( 'upcoming' => pht('Upcoming'), 'all' => pht('All'), ); if ($this->requireViewer()->getPHID()) { $names['authored'] = pht('Authored'); } return $names; } public function buildSavedQueryFromBuiltin($query_key) { $query = $this->newSavedQuery(); $query->setQueryKey($query_key); switch ($query_key) { case 'all': return $query; case 'authored': return $query->setParameter( 'authorPHIDs', array($this->requireViewer()->getPHID())); case 'upcoming': return $query->setParameter('upcoming', array('upcoming')); } return parent::buildSavedQueryFromBuiltin($query_key); } protected function getRequiredHandlePHIDsForResultList( array $countdowns, PhabricatorSavedQuery $query) { return mpull($countdowns, 'getAuthorPHID'); } protected function renderResultList( array $countdowns, PhabricatorSavedQuery $query, array $handles) { assert_instances_of($countdowns, 'PhabricatorCountdown'); $viewer = $this->requireViewer(); $list = new PHUIObjectItemListView(); $list->setUser($viewer); foreach ($countdowns as $countdown) { $id = $countdown->getID(); $ended = false; $epoch = $countdown->getEpoch(); if ($epoch <= PhabricatorTime::getNow()) { $ended = true; } $item = id(new PHUIObjectItemView()) ->setUser($viewer) ->setObject($countdown) ->setObjectName("C{$id}") ->setHeader($countdown->getTitle()) ->setHref($this->getApplicationURI("{$id}/")) ->addByline( pht( 'Created by %s', $handles[$countdown->getAuthorPHID()]->renderLink())); if ($ended) { $item->addAttribute( pht('Launched on %s', phabricator_datetime($epoch, $viewer))); $item->setDisabled(true); } else { $time_left = ($epoch - PhabricatorTime::getNow()); $num = round($time_left / (60 * 60 * 24)); $noun = pht('Days'); if ($num < 1) { $num = round($time_left / (60 * 60), 1); $noun = pht('Hours'); } $item->setCountdown($num, $noun); $item->addAttribute( phabricator_datetime($epoch, $viewer)); } $list->addItem($item); } $result = new PhabricatorApplicationSearchResultView(); $result->setObjectList($list); $result->setNoDataString(pht('No countdowns found.')); return $result; } protected function getNewUserBody() { $create_button = id(new PHUIButtonView()) ->setTag('a') ->setText(pht('Create a Countdown')) ->setHref('/countdown/create/') ->setColor(PHUIButtonView::GREEN); $icon = $this->getApplication()->getIcon(); $app_name = $this->getApplication()->getName(); $view = id(new PHUIBigInfoView()) ->setIcon($icon) ->setTitle(pht('Welcome to %s', $app_name)) ->setDescription( pht('Keep track of upcoming launch dates with '. 'embeddable counters.')) ->addAction($create_button); return $view; } } diff --git a/src/applications/countdown/storage/PhabricatorCountdown.php b/src/applications/countdown/storage/PhabricatorCountdown.php index 1a985b0b83..ad9b1b33aa 100644 --- a/src/applications/countdown/storage/PhabricatorCountdown.php +++ b/src/applications/countdown/storage/PhabricatorCountdown.php @@ -1,144 +1,152 @@ setViewer($actor) ->withClasses(array('PhabricatorCountdownApplication')) ->executeOne(); $view_policy = $app->getPolicy( PhabricatorCountdownDefaultViewCapability::CAPABILITY); $edit_policy = $app->getPolicy( PhabricatorCountdownDefaultEditCapability::CAPABILITY); return id(new PhabricatorCountdown()) ->setAuthorPHID($actor->getPHID()) ->setViewPolicy($view_policy) ->setEditPolicy($edit_policy) ->setSpacePHID($actor->getDefaultSpacePHID()); } protected function getConfiguration() { return array( self::CONFIG_AUX_PHID => true, self::CONFIG_COLUMN_SCHEMA => array( 'title' => 'text255', 'description' => 'text', 'mailKey' => 'bytes20', ), + self::CONFIG_KEY_SCHEMA => array( + 'key_epoch' => array( + 'columns' => array('epoch'), + ), + 'key_author' => array( + 'columns' => array('authorPHID', 'epoch'), + ), + ), ) + parent::getConfiguration(); } public function generatePHID() { return PhabricatorPHID::generateNewPHID( PhabricatorCountdownCountdownPHIDType::TYPECONST); } public function getMonogram() { return 'C'.$this->getID(); } public function getURI() { return '/'.$this->getMonogram(); } public function save() { if (!$this->getMailKey()) { $this->setMailKey(Filesystem::readRandomCharacters(20)); } return parent::save(); } /* -( PhabricatorSubscribableInterface )----------------------------------- */ public function isAutomaticallySubscribed($phid) { return ($phid == $this->getAuthorPHID()); } /* -( PhabricatorApplicationTransactionInterface )------------------------- */ public function getApplicationTransactionEditor() { return new PhabricatorCountdownEditor(); } public function getApplicationTransactionObject() { return $this; } public function getApplicationTransactionTemplate() { return new PhabricatorCountdownTransaction(); } public function willRenderTimeline( PhabricatorApplicationTransactionView $timeline, AphrontRequest $request) { return $timeline; } /* -( PhabricatorTokenReceiverInterface )---------------------------------- */ public function getUsersToNotifyOfTokenGiven() { return array($this->getAuthorPHID()); } /* -( PhabricatorPolicyInterface )----------------------------------------- */ public function getCapabilities() { return array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, ); } public function getPolicy($capability) { switch ($capability) { case PhabricatorPolicyCapability::CAN_VIEW: return $this->getViewPolicy(); case PhabricatorPolicyCapability::CAN_EDIT: return $this->getEditPolicy(); } } public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { return false; } public function describeAutomaticCapability($capability) { return false; } /* -( PhabricatorSpacesInterface )------------------------------------------- */ public function getSpacePHID() { return $this->spacePHID; } }