1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-01-11 07:11:04 +01:00

Countdown revamp 2

Summary:
Now has policy support (not really)
Now uses CountdownQuery
Now has handles
Now uses common way for remarkup
Remarkup still looks terrible

Test Plan: Added countdowns, edited countdowns. Did even embed some. Couldn't break it

Reviewers: epriestley

Reviewed By: epriestley

CC: aran, Korvin, AnhNhan

Maniphest Tasks: T2624

Differential Revision: https://secure.phabricator.com/D6012
This commit is contained in:
Lauri-Henrik Jalonen 2013-05-23 06:47:54 -07:00 committed by epriestley
parent bc9c8cc015
commit 689c6f2f30
14 changed files with 227 additions and 105 deletions

View file

@ -277,6 +277,7 @@ phutil_register_library_map(array(
'ConpherenceViewController' => 'applications/conpherence/controller/ConpherenceViewController.php', 'ConpherenceViewController' => 'applications/conpherence/controller/ConpherenceViewController.php',
'ConpherenceWidgetController' => 'applications/conpherence/controller/ConpherenceWidgetController.php', 'ConpherenceWidgetController' => 'applications/conpherence/controller/ConpherenceWidgetController.php',
'ConpherenceWidgetView' => 'applications/conpherence/view/ConpherenceWidgetView.php', 'ConpherenceWidgetView' => 'applications/conpherence/view/ConpherenceWidgetView.php',
'CountdownQuery' => 'applications/countdown/query/CountdownQuery.php',
'DarkConsoleController' => 'aphront/console/DarkConsoleController.php', 'DarkConsoleController' => 'aphront/console/DarkConsoleController.php',
'DarkConsoleCore' => 'aphront/console/DarkConsoleCore.php', 'DarkConsoleCore' => 'aphront/console/DarkConsoleCore.php',
'DarkConsoleDataController' => 'aphront/console/DarkConsoleDataController.php', 'DarkConsoleDataController' => 'aphront/console/DarkConsoleDataController.php',
@ -2087,6 +2088,7 @@ phutil_register_library_map(array(
'ConpherenceViewController' => 'ConpherenceController', 'ConpherenceViewController' => 'ConpherenceController',
'ConpherenceWidgetController' => 'ConpherenceController', 'ConpherenceWidgetController' => 'ConpherenceController',
'ConpherenceWidgetView' => 'AphrontView', 'ConpherenceWidgetView' => 'AphrontView',
'CountdownQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'DarkConsoleController' => 'PhabricatorController', 'DarkConsoleController' => 'PhabricatorController',
'DarkConsoleDataController' => 'PhabricatorController', 'DarkConsoleDataController' => 'PhabricatorController',
'DarkConsoleErrorLogPlugin' => 'DarkConsolePlugin', 'DarkConsoleErrorLogPlugin' => 'DarkConsolePlugin',
@ -2655,13 +2657,17 @@ phutil_register_library_map(array(
'PhabricatorContentSourceView' => 'AphrontView', 'PhabricatorContentSourceView' => 'AphrontView',
'PhabricatorController' => 'AphrontController', 'PhabricatorController' => 'AphrontController',
'PhabricatorCoreConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorCoreConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorCountdown' => 'PhabricatorCountdownDAO', 'PhabricatorCountdown' =>
array(
0 => 'PhabricatorCountdownDAO',
1 => 'PhabricatorPolicyInterface',
),
'PhabricatorCountdownController' => 'PhabricatorController', 'PhabricatorCountdownController' => 'PhabricatorController',
'PhabricatorCountdownDAO' => 'PhabricatorLiskDAO', 'PhabricatorCountdownDAO' => 'PhabricatorLiskDAO',
'PhabricatorCountdownDeleteController' => 'PhabricatorCountdownController', 'PhabricatorCountdownDeleteController' => 'PhabricatorCountdownController',
'PhabricatorCountdownEditController' => 'PhabricatorCountdownController', 'PhabricatorCountdownEditController' => 'PhabricatorCountdownController',
'PhabricatorCountdownListController' => 'PhabricatorCountdownController', 'PhabricatorCountdownListController' => 'PhabricatorCountdownController',
'PhabricatorCountdownRemarkupRule' => 'PhutilRemarkupRule', 'PhabricatorCountdownRemarkupRule' => 'PhabricatorRemarkupRuleObject',
'PhabricatorCountdownViewController' => 'PhabricatorCountdownController', 'PhabricatorCountdownViewController' => 'PhabricatorCountdownController',
'PhabricatorCountedToggleButtonsExample' => 'PhabricatorUIExample', 'PhabricatorCountedToggleButtonsExample' => 'PhabricatorUIExample',
'PhabricatorCrumbView' => 'AphrontView', 'PhabricatorCrumbView' => 'AphrontView',

View file

@ -1,5 +1,8 @@
<?php <?php
/**
* @group countdown
*/
final class PhabricatorApplicationCountdown extends PhabricatorApplication { final class PhabricatorApplicationCountdown extends PhabricatorApplication {
public function getBaseURI() { public function getBaseURI() {

View file

@ -1,5 +1,8 @@
<?php <?php
/**
* @group countdown
*/
abstract class PhabricatorCountdownController extends PhabricatorController { abstract class PhabricatorCountdownController extends PhabricatorController {
public function buildSideNavView() { public function buildSideNavView() {

View file

@ -1,5 +1,8 @@
<?php <?php
/**
* @group countdown
*/
final class PhabricatorCountdownDeleteController final class PhabricatorCountdownDeleteController
extends PhabricatorCountdownController { extends PhabricatorCountdownController {
@ -14,24 +17,28 @@ final class PhabricatorCountdownDeleteController
$request = $this->getRequest(); $request = $this->getRequest();
$user = $request->getUser(); $user = $request->getUser();
$timer = id(new PhabricatorCountdown())->load($this->id); $countdown = id(new CountdownQuery())
if (!$timer) { ->setViewer($user)
->withIDs(array($this->id))
->executeOne();
if (!$countdown) {
return new Aphront404Response(); return new Aphront404Response();
} }
if (($timer->getAuthorPHID() !== $user->getPHID()) if (($countdown->getAuthorPHID() !== $user->getPHID())
&& $user->getIsAdmin() === false) { && $user->getIsAdmin() === false) {
return new Aphront403Response(); return new Aphront403Response();
} }
if ($request->isFormPost()) { if ($request->isFormPost()) {
$timer->delete(); $countdown->delete();
return id(new AphrontRedirectResponse()) return id(new AphrontRedirectResponse())
->setURI('/countdown/'); ->setURI('/countdown/');
} }
$inst = pht('Are you sure you want to delete the countdown %s?', $inst = pht('Are you sure you want to delete the countdown %s?',
$timer->getTitle()); $countdown->getTitle());
$dialog = new AphrontDialogView(); $dialog = new AphrontDialogView();
$dialog->setUser($request->getUser()); $dialog->setUser($request->getUser());

View file

@ -1,5 +1,8 @@
<?php <?php
/**
* @group countdown
*/
final class PhabricatorCountdownEditController final class PhabricatorCountdownEditController
extends PhabricatorCountdownController { extends PhabricatorCountdownController {
@ -15,21 +18,25 @@ final class PhabricatorCountdownEditController
$action_label = pht('Create Countdown'); $action_label = pht('Create Countdown');
if ($this->id) { if ($this->id) {
$timer = id(new PhabricatorCountdown())->load($this->id); $countdown = id(new CountdownQuery())
// If no timer is found ->setViewer($user)
if (!$timer) { ->withIDs(array($this->id))
->executeOne();
// If no countdown is found
if (!$countdown) {
return new Aphront404Response(); return new Aphront404Response();
} }
if (($timer->getAuthorPHID() != $user->getPHID()) if (($countdown->getAuthorPHID() != $user->getPHID())
&& $user->getIsAdmin() == false) { && $user->getIsAdmin() == false) {
return new Aphront403Response(); return new Aphront403Response();
} }
$action_label = pht('Update Countdown'); $action_label = pht('Update Countdown');
} else { } else {
$timer = new PhabricatorCountdown(); $countdown = new PhabricatorCountdown();
$timer->setEpoch(time()); $countdown->setEpoch(time());
} }
$error_view = null; $error_view = null;
@ -60,14 +67,14 @@ final class PhabricatorCountdownEditController
$timestamp = null; $timestamp = null;
} }
$timer->setTitle($title); $countdown->setTitle($title);
$timer->setEpoch($timestamp); $countdown->setEpoch($timestamp);
if (!count($errors)) { if (!count($errors)) {
$timer->setAuthorPHID($user->getPHID()); $countdown->setAuthorPHID($user->getPHID());
$timer->save(); $countdown->save();
return id(new AphrontRedirectResponse()) return id(new AphrontRedirectResponse())
->setURI('/countdown/'.$timer->getID().'/'); ->setURI('/countdown/'.$countdown->getID().'/');
} else { } else {
$error_view = id(new AphrontErrorView()) $error_view = id(new AphrontErrorView())
->setErrors($errors) ->setErrors($errors)
@ -76,9 +83,9 @@ final class PhabricatorCountdownEditController
} }
} }
if ($timer->getEpoch()) { if ($countdown->getEpoch()) {
$display_epoch = phabricator_datetime( $display_epoch = phabricator_datetime(
$timer->getEpoch(), $countdown->getEpoch(),
$user); $user);
} else { } else {
$display_epoch = $request->getStr('epoch'); $display_epoch = $request->getStr('epoch');
@ -90,7 +97,7 @@ final class PhabricatorCountdownEditController
->appendChild( ->appendChild(
id(new AphrontFormTextControl()) id(new AphrontFormTextControl())
->setLabel(pht('Title')) ->setLabel(pht('Title'))
->setValue($timer->getTitle()) ->setValue($countdown->getTitle())
->setName('title')) ->setName('title'))
->appendChild( ->appendChild(
id(new AphrontFormTextControl()) id(new AphrontFormTextControl())

View file

@ -1,5 +1,8 @@
<?php <?php
/**
* @group countdown
*/
final class PhabricatorCountdownListController final class PhabricatorCountdownListController
extends PhabricatorCountdownController { extends PhabricatorCountdownController {
@ -8,22 +11,19 @@ final class PhabricatorCountdownListController
$request = $this->getRequest(); $request = $this->getRequest();
$user = $request->getUser(); $user = $request->getUser();
$pager = new AphrontPagerView(); $pager = new AphrontCursorPagerView();
$pager->setOffset($request->getInt('page')); $pager->readFromRequest($request);
$pager->setURI($request->getRequestURI(), 'page');
$timers = id(new PhabricatorCountdown())->loadAllWhere( $query = id(new CountdownQuery())
'1 = 1 ORDER BY id DESC LIMIT %d, %d', ->setViewer($user);
$pager->getOffset(),
$pager->getPageSize() + 1);
$timers = $pager->sliceResults($timers); $countdowns = $query->executeWithCursorPager($pager);
$phids = mpull($timers, 'getAuthorPHID'); $phids = mpull($countdowns, 'getAuthorPHID');
$handles = $this->loadViewerHandles($phids); $handles = $this->loadViewerHandles($phids);
$rows = array(); $rows = array();
foreach ($timers as $timer) { foreach ($countdowns as $timer) {
$edit_button = null; $edit_button = null;
$delete_button = null; $delete_button = null;
if ($user->getIsAdmin() || if ($user->getIsAdmin() ||

View file

@ -1,5 +1,8 @@
<?php <?php
/**
* @group countdown
*/
final class PhabricatorCountdownViewController final class PhabricatorCountdownViewController
extends PhabricatorCountdownController { extends PhabricatorCountdownController {
@ -14,8 +17,13 @@ final class PhabricatorCountdownViewController
$request = $this->getRequest(); $request = $this->getRequest();
$user = $request->getUser(); $user = $request->getUser();
$timer = id(new PhabricatorCountdown())->load($this->id);
if (!$timer) { $countdown = id(new CountdownQuery())
->setViewer($user)
->withIDs(array($this->id))
->executeOne();
if (!$countdown) {
return new Aphront404Response(); return new Aphront404Response();
} }
@ -49,8 +57,8 @@ final class PhabricatorCountdownViewController
%s %s
</div>', </div>',
$container, $container,
$timer->getTitle(), $countdown->getTitle(),
phabricator_datetime($timer->getEpoch(), $user), phabricator_datetime($countdown->getEpoch(), $user),
pht('Days'), pht('Days'),
pht('Hours'), pht('Hours'),
pht('Minutes'), pht('Minutes'),
@ -62,7 +70,7 @@ final class PhabricatorCountdownViewController
$chrome_link); $chrome_link);
Javelin::initBehavior('countdown-timer', array( Javelin::initBehavior('countdown-timer', array(
'timestamp' => $timer->getEpoch(), 'timestamp' => $countdown->getEpoch(),
'container' => $container, 'container' => $container,
)); ));
@ -72,7 +80,7 @@ final class PhabricatorCountdownViewController
->buildApplicationCrumbs() ->buildApplicationCrumbs()
->addCrumb( ->addCrumb(
id(new PhabricatorCrumbView()) id(new PhabricatorCrumbView())
->setName($timer->getTitle()) ->setName($countdown->getTitle())
->setHref($this->getApplicationURI($this->id.'/'))); ->setHref($this->getApplicationURI($this->id.'/')));
return $this->buildApplicationPage( return $this->buildApplicationPage(
@ -81,7 +89,7 @@ final class PhabricatorCountdownViewController
$panel, $panel,
), ),
array( array(
'title' => pht('Countdown: %s', $timer->getTitle()), 'title' => pht('Countdown: %s', $countdown->getTitle()),
'chrome' => $chrome_visible, 'chrome' => $chrome_visible,
'device' => true, 'device' => true,
)); ));

View file

@ -0,0 +1,75 @@
<?php
/**
* @group countdown
*/
final class CountdownQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $authorPHIDs;
public function withIDs(array $ids) {
$this->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;
}
protected function loadPage() {
$table = new PhabricatorCountdown();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
$countdowns = $table->loadAllFromArray($data);
return $countdowns;
}
private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
$where[] = $this->buildPagingClause($conn_r);
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->authorPHIDs) {
$where[] = qsprintf(
$conn_r,
'authorPHID in (%Ls)',
$this->authorPHIDs);
}
return $this->formatWhereClause($where);
}
}

View file

@ -1,66 +1,31 @@
<?php <?php
/** /**
* @group markup * @group countdown
*/ */
final class PhabricatorCountdownRemarkupRule extends PhutilRemarkupRule { final class PhabricatorCountdownRemarkupRule
extends PhabricatorRemarkupRuleObject {
const KEY_RULE_COUNTDOWN = 'rule.countdown'; protected function getObjectNamePrefix() {
return 'C';
public function apply($text) {
return preg_replace_callback(
"@\B{C(\d+)}\B@",
array($this, 'markupCountdown'),
$text);
} }
protected function markupCountdown($matches) { protected function loadObjects(array $ids) {
$countdown = id(new PhabricatorCountdown())->load($matches[1]); $viewer = $this->getEngine()->getConfig('viewer');
if (!$countdown) { return id(new CountdownQuery())
return $matches[0]; ->setViewer($viewer)
} ->withIDs($ids)
->execute();
$engine = $this->getEngine();
if ($engine->isTextMode()) {
$date = $countdown->getEpoch();
$viewer = $engine->getConfig('viewer');
if ($viewer) {
$date = phabricator_datetime($date, $viewer);
}
return $engine->storeText($date);
}
$id = celerity_generate_unique_node_id();
$token = $engine->storeText('');
$metadata_key = self::KEY_RULE_COUNTDOWN;
$metadata = $engine->getTextMetadata($metadata_key, array());
$metadata[$id] = array($countdown->getEpoch(), $token);
$engine->setTextMetadata($metadata_key, $metadata);
return $token;
}
public function didMarkupText() {
$engine = $this->getEngine();
$metadata_key = self::KEY_RULE_COUNTDOWN;
$metadata = $engine->getTextMetadata($metadata_key, array());
if (!$metadata) {
return;
} }
protected function renderObjectEmbed($object, $handle, $options) {
require_celerity_resource('javelin-behavior-countdown-timer'); require_celerity_resource('javelin-behavior-countdown-timer');
foreach ($metadata as $id => $info) {
list($time, $token) = $info;
$prefix = 'phabricator-timer-'; $prefix = 'phabricator-timer-';
$count = phutil_tag( $counter = phutil_tag(
'span', 'span',
array( array(
'id' => $id, 'id' => $object->getPHID(),
), ),
array( array(
javelin_tag('span', array('sigil' => $prefix.'days'), ''), 'd', javelin_tag('span', array('sigil' => $prefix.'days'), ''), 'd',
@ -68,14 +33,13 @@ final class PhabricatorCountdownRemarkupRule extends PhutilRemarkupRule {
javelin_tag('span', array('sigil' => $prefix.'minutes'), ''), 'm', javelin_tag('span', array('sigil' => $prefix.'minutes'), ''), 'm',
javelin_tag('span', array('sigil' => $prefix.'seconds'), ''), 's', javelin_tag('span', array('sigil' => $prefix.'seconds'), ''), 's',
)); ));
Javelin::initBehavior('countdown-timer', array( Javelin::initBehavior('countdown-timer', array(
'timestamp' => $time, 'timestamp' => $object->getEpoch(),
'container' => $id, 'container' => $object->getPHID(),
)); ));
$engine->overwriteStoredText($token, $count);
}
$engine->setTextMetadata($metadata_key, array()); return $counter;
} }
} }

View file

@ -1,12 +1,17 @@
<?php <?php
final class PhabricatorCountdown extends PhabricatorCountdownDAO { /**
* @group countdown
*/
final class PhabricatorCountdown extends PhabricatorCountdownDAO
implements PhabricatorPolicyInterface {
protected $id; protected $id;
protected $phid; protected $phid;
protected $title; protected $title;
protected $authorPHID; protected $authorPHID;
protected $epoch; protected $epoch;
// protected $viewPolicy; //commented out till we have it on countdown table
public function getConfiguration() { public function getConfiguration() {
return array( return array(
@ -18,4 +23,27 @@ final class PhabricatorCountdown extends PhabricatorCountdownDAO {
return PhabricatorPHID::generateNewPHID('CDWN'); return PhabricatorPHID::generateNewPHID('CDWN');
} }
public function getViewPolicy() {
return "users";
}
/* -( PhabricatorPolicyInterface Implementation )------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW
);
}
public function getPolicy($capability) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
return $this->getViewPolicy();
}
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
return ($viewer->getPHID() == $this->getAuthorPHID());
}
} }

View file

@ -1,5 +1,8 @@
<?php <?php
/**
* @group countdown
*/
abstract class PhabricatorCountdownDAO extends PhabricatorLiskDAO { abstract class PhabricatorCountdownDAO extends PhabricatorLiskDAO {
public function getApplicationName() { public function getApplicationName() {

View file

@ -39,6 +39,7 @@ final class PhabricatorPHIDConstants {
const PHID_TYPE_PAYM = 'PAYM'; const PHID_TYPE_PAYM = 'PAYM';
const PHID_TYPE_CHRG = 'CHRG'; const PHID_TYPE_CHRG = 'CHRG';
const PHID_TYPE_CART = 'CART'; const PHID_TYPE_CART = 'CART';
const PHID_TYPE_CDWN = 'CDWN';
const PHID_TYPE_XACT = 'XACT'; const PHID_TYPE_XACT = 'XACT';
const PHID_TYPE_XCMT = 'XCMT'; const PHID_TYPE_XCMT = 'XCMT';

View file

@ -705,6 +705,24 @@ final class PhabricatorObjectHandleData {
} }
break; break;
case PhabricatorPHIDConstants::PHID_TYPE_CDWN:
foreach ($phids as $phid) {
$handle = new PhabricatorObjectHandle();
$handle->setPHID($phid);
$handle->setType($type);
if (empty($objects[$phid])) {
$handle->setName('Unknown Countdown');
} else {
$countdown = $objects[$phid];
$handle->setName($countdown->getTitle());
$handle->setFullName($countdown->getTitle());
$handle->setURI('/countdown/'.$countdown->getID().'/');
$handle->setComplete(true);
}
$handles[$phid] = $handle;
}
break;
default: default:
$loader = null; $loader = null;
if (isset($external_loaders[$type])) { if (isset($external_loaders[$type])) {

View file

@ -22,7 +22,6 @@ final class PholioMockEmbedView extends AphrontView {
require_celerity_resource('pholio-css'); require_celerity_resource('pholio-css');
$mock_link = phutil_tag( $mock_link = phutil_tag(
'a', 'a',
array( array(