1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-23 05:50:55 +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',
'ConpherenceWidgetController' => 'applications/conpherence/controller/ConpherenceWidgetController.php',
'ConpherenceWidgetView' => 'applications/conpherence/view/ConpherenceWidgetView.php',
'CountdownQuery' => 'applications/countdown/query/CountdownQuery.php',
'DarkConsoleController' => 'aphront/console/DarkConsoleController.php',
'DarkConsoleCore' => 'aphront/console/DarkConsoleCore.php',
'DarkConsoleDataController' => 'aphront/console/DarkConsoleDataController.php',
@ -2087,6 +2088,7 @@ phutil_register_library_map(array(
'ConpherenceViewController' => 'ConpherenceController',
'ConpherenceWidgetController' => 'ConpherenceController',
'ConpherenceWidgetView' => 'AphrontView',
'CountdownQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'DarkConsoleController' => 'PhabricatorController',
'DarkConsoleDataController' => 'PhabricatorController',
'DarkConsoleErrorLogPlugin' => 'DarkConsolePlugin',
@ -2655,13 +2657,17 @@ phutil_register_library_map(array(
'PhabricatorContentSourceView' => 'AphrontView',
'PhabricatorController' => 'AphrontController',
'PhabricatorCoreConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorCountdown' => 'PhabricatorCountdownDAO',
'PhabricatorCountdown' =>
array(
0 => 'PhabricatorCountdownDAO',
1 => 'PhabricatorPolicyInterface',
),
'PhabricatorCountdownController' => 'PhabricatorController',
'PhabricatorCountdownDAO' => 'PhabricatorLiskDAO',
'PhabricatorCountdownDeleteController' => 'PhabricatorCountdownController',
'PhabricatorCountdownEditController' => 'PhabricatorCountdownController',
'PhabricatorCountdownListController' => 'PhabricatorCountdownController',
'PhabricatorCountdownRemarkupRule' => 'PhutilRemarkupRule',
'PhabricatorCountdownRemarkupRule' => 'PhabricatorRemarkupRuleObject',
'PhabricatorCountdownViewController' => 'PhabricatorCountdownController',
'PhabricatorCountedToggleButtonsExample' => 'PhabricatorUIExample',
'PhabricatorCrumbView' => 'AphrontView',

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,5 +1,8 @@
<?php
/**
* @group countdown
*/
final class PhabricatorCountdownViewController
extends PhabricatorCountdownController {
@ -14,8 +17,13 @@ final class PhabricatorCountdownViewController
$request = $this->getRequest();
$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();
}
@ -49,8 +57,8 @@ final class PhabricatorCountdownViewController
%s
</div>',
$container,
$timer->getTitle(),
phabricator_datetime($timer->getEpoch(), $user),
$countdown->getTitle(),
phabricator_datetime($countdown->getEpoch(), $user),
pht('Days'),
pht('Hours'),
pht('Minutes'),
@ -62,7 +70,7 @@ final class PhabricatorCountdownViewController
$chrome_link);
Javelin::initBehavior('countdown-timer', array(
'timestamp' => $timer->getEpoch(),
'timestamp' => $countdown->getEpoch(),
'container' => $container,
));
@ -72,7 +80,7 @@ final class PhabricatorCountdownViewController
->buildApplicationCrumbs()
->addCrumb(
id(new PhabricatorCrumbView())
->setName($timer->getTitle())
->setName($countdown->getTitle())
->setHref($this->getApplicationURI($this->id.'/')));
return $this->buildApplicationPage(
@ -81,7 +89,7 @@ final class PhabricatorCountdownViewController
$panel,
),
array(
'title' => pht('Countdown: %s', $timer->getTitle()),
'title' => pht('Countdown: %s', $countdown->getTitle()),
'chrome' => $chrome_visible,
'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,81 +1,45 @@
<?php
/**
* @group markup
* @group countdown
*/
final class PhabricatorCountdownRemarkupRule extends PhutilRemarkupRule {
final class PhabricatorCountdownRemarkupRule
extends PhabricatorRemarkupRuleObject {
const KEY_RULE_COUNTDOWN = 'rule.countdown';
public function apply($text) {
return preg_replace_callback(
"@\B{C(\d+)}\B@",
array($this, 'markupCountdown'),
$text);
protected function getObjectNamePrefix() {
return 'C';
}
protected function markupCountdown($matches) {
$countdown = id(new PhabricatorCountdown())->load($matches[1]);
if (!$countdown) {
return $matches[0];
}
$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;
protected function loadObjects(array $ids) {
$viewer = $this->getEngine()->getConfig('viewer');
return id(new CountdownQuery())
->setViewer($viewer)
->withIDs($ids)
->execute();
}
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');
foreach ($metadata as $id => $info) {
list($time, $token) = $info;
$prefix = 'phabricator-timer-';
$count = phutil_tag(
'span',
array(
'id' => $id,
),
array(
javelin_tag('span', array('sigil' => $prefix.'days'), ''), 'd',
javelin_tag('span', array('sigil' => $prefix.'hours'), ''), 'h',
javelin_tag('span', array('sigil' => $prefix.'minutes'), ''), 'm',
javelin_tag('span', array('sigil' => $prefix.'seconds'), ''), 's',
));
Javelin::initBehavior('countdown-timer', array(
'timestamp' => $time,
'container' => $id,
$prefix = 'phabricator-timer-';
$counter = phutil_tag(
'span',
array(
'id' => $object->getPHID(),
),
array(
javelin_tag('span', array('sigil' => $prefix.'days'), ''), 'd',
javelin_tag('span', array('sigil' => $prefix.'hours'), ''), 'h',
javelin_tag('span', array('sigil' => $prefix.'minutes'), ''), 'm',
javelin_tag('span', array('sigil' => $prefix.'seconds'), ''), 's',
));
$engine->overwriteStoredText($token, $count);
}
$engine->setTextMetadata($metadata_key, array());
Javelin::initBehavior('countdown-timer', array(
'timestamp' => $object->getEpoch(),
'container' => $object->getPHID(),
));
return $counter;
}
}

View file

@ -1,12 +1,17 @@
<?php
final class PhabricatorCountdown extends PhabricatorCountdownDAO {
/**
* @group countdown
*/
final class PhabricatorCountdown extends PhabricatorCountdownDAO
implements PhabricatorPolicyInterface {
protected $id;
protected $phid;
protected $title;
protected $authorPHID;
protected $epoch;
// protected $viewPolicy; //commented out till we have it on countdown table
public function getConfiguration() {
return array(
@ -18,4 +23,27 @@ final class PhabricatorCountdown extends PhabricatorCountdownDAO {
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
/**
* @group countdown
*/
abstract class PhabricatorCountdownDAO extends PhabricatorLiskDAO {
public function getApplicationName() {

View file

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

View file

@ -705,6 +705,24 @@ final class PhabricatorObjectHandleData {
}
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:
$loader = null;
if (isset($external_loaders[$type])) {

View file

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