mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-23 14:00:56 +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:
parent
bc9c8cc015
commit
689c6f2f30
14 changed files with 227 additions and 105 deletions
|
@ -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',
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @group countdown
|
||||
*/
|
||||
final class PhabricatorApplicationCountdown extends PhabricatorApplication {
|
||||
|
||||
public function getBaseURI() {
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @group countdown
|
||||
*/
|
||||
abstract class PhabricatorCountdownController extends PhabricatorController {
|
||||
|
||||
public function buildSideNavView() {
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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() ||
|
||||
|
|
|
@ -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,
|
||||
));
|
||||
|
|
75
src/applications/countdown/query/CountdownQuery.php
Normal file
75
src/applications/countdown/query/CountdownQuery.php
Normal 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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @group countdown
|
||||
*/
|
||||
abstract class PhabricatorCountdownDAO extends PhabricatorLiskDAO {
|
||||
|
||||
public function getApplicationName() {
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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])) {
|
||||
|
|
|
@ -22,7 +22,6 @@ final class PholioMockEmbedView extends AphrontView {
|
|||
|
||||
require_celerity_resource('pholio-css');
|
||||
|
||||
|
||||
$mock_link = phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
|
|
Loading…
Reference in a new issue