1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-22 23:02:42 +01:00
Summary:
Yup, it's sitevars.

No conduit or caching or fancy stuff yet.

Ref T2793.

Test Plan:
{F36525}
{F36526}
{F36527}
{F36528}
{F36529}

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T2793

Differential Revision: https://secure.phabricator.com/D5397
This commit is contained in:
epriestley 2013-03-20 18:01:52 -07:00
parent eca49cb91f
commit 9a515171f4
16 changed files with 772 additions and 0 deletions

View file

@ -0,0 +1,32 @@
CREATE TABLE {$NAMESPACE}_phlux.phlux_variable (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
phid VARCHAR(64) NOT NULL COLLATE utf8_bin,
variableKey VARCHAR(64) NOT NULL COLLATE utf8_bin,
variableValue LONGTEXT NOT NULL COLLATE utf8_bin,
viewPolicy VARCHAR(64) NOT NULL COLLATE utf8_bin,
editPolicy VARCHAR(64) NOT NULL COLLATE utf8_bin,
dateCreated INT UNSIGNED NOT NULL,
dateModified INT UNSIGNED NOT NULL,
UNIQUE KEY `key_phid` (phid),
UNIQUE KEY `key_key` (variableKey)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE {$NAMESPACE}_phlux.phlux_transaction (
id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
phid VARCHAR(64) NOT NULL COLLATE utf8_bin,
authorPHID VARCHAR(64) NOT NULL COLLATE utf8_bin,
objectPHID VARCHAR(64) NOT NULL COLLATE utf8_bin,
viewPolicy VARCHAR(64) NOT NULL COLLATE utf8_bin,
editPolicy VARCHAR(64) NOT NULL COLLATE utf8_bin,
commentPHID VARCHAR(64) COLLATE utf8_bin,
commentVersion INT UNSIGNED NOT NULL,
transactionType VARCHAR(32) NOT NULL COLLATE utf8_bin,
oldValue LONGTEXT NOT NULL COLLATE utf8_bin,
newValue LONGTEXT NOT NULL COLLATE utf8_bin,
contentSource LONGTEXT NOT NULL COLLATE utf8_bin,
dateCreated INT UNSIGNED NOT NULL,
dateModified INT UNSIGNED NOT NULL,
UNIQUE KEY `key_phid` (phid),
KEY `key_object` (objectPHID)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

View file

@ -700,6 +700,7 @@ phutil_register_library_map(array(
'PhabricatorApplicationPaste' => 'applications/paste/application/PhabricatorApplicationPaste.php',
'PhabricatorApplicationPeople' => 'applications/people/application/PhabricatorApplicationPeople.php',
'PhabricatorApplicationPhame' => 'applications/phame/application/PhabricatorApplicationPhame.php',
'PhabricatorApplicationPhlux' => 'applications/phlux/application/PhabricatorApplicationPhlux.php',
'PhabricatorApplicationPholio' => 'applications/pholio/application/PhabricatorApplicationPholio.php',
'PhabricatorApplicationPhriction' => 'applications/phriction/application/PhabricatorApplicationPhriction.php',
'PhabricatorApplicationPonder' => 'applications/ponder/application/PhabricatorApplicationPonder.php',
@ -1482,6 +1483,16 @@ phutil_register_library_map(array(
'PhamePostViewController' => 'applications/phame/controller/post/PhamePostViewController.php',
'PhameResourceController' => 'applications/phame/controller/PhameResourceController.php',
'PhameSkinSpecification' => 'applications/phame/skins/PhameSkinSpecification.php',
'PhluxController' => 'applications/phlux/controller/PhluxController.php',
'PhluxDAO' => 'applications/phlux/storage/PhluxDAO.php',
'PhluxEditController' => 'applications/phlux/controller/PhluxEditController.php',
'PhluxListController' => 'applications/phlux/controller/PhluxListController.php',
'PhluxTransaction' => 'applications/phlux/storage/PhluxTransaction.php',
'PhluxTransactionQuery' => 'applications/phlux/query/PhluxTransactionQuery.php',
'PhluxVariable' => 'applications/phlux/storage/PhluxVariable.php',
'PhluxVariableEditor' => 'applications/phlux/editor/PhluxVariableEditor.php',
'PhluxVariableQuery' => 'applications/phlux/query/PhluxVariableQuery.php',
'PhluxViewController' => 'applications/phlux/controller/PhluxViewController.php',
'PholioConstants' => 'applications/pholio/constants/PholioConstants.php',
'PholioController' => 'applications/pholio/controller/PholioController.php',
'PholioDAO' => 'applications/pholio/storage/PholioDAO.php',
@ -2310,6 +2321,7 @@ phutil_register_library_map(array(
'PhabricatorApplicationPaste' => 'PhabricatorApplication',
'PhabricatorApplicationPeople' => 'PhabricatorApplication',
'PhabricatorApplicationPhame' => 'PhabricatorApplication',
'PhabricatorApplicationPhlux' => 'PhabricatorApplication',
'PhabricatorApplicationPholio' => 'PhabricatorApplication',
'PhabricatorApplicationPhriction' => 'PhabricatorApplication',
'PhabricatorApplicationPonder' => 'PhabricatorApplication',
@ -3080,6 +3092,20 @@ phutil_register_library_map(array(
'PhamePostView' => 'AphrontView',
'PhamePostViewController' => 'PhameController',
'PhameResourceController' => 'CelerityResourceController',
'PhluxController' => 'PhabricatorController',
'PhluxDAO' => 'PhabricatorLiskDAO',
'PhluxEditController' => 'PhluxController',
'PhluxListController' => 'PhluxController',
'PhluxTransaction' => 'PhabricatorApplicationTransaction',
'PhluxTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhluxVariable' =>
array(
0 => 'PhluxDAO',
1 => 'PhabricatorPolicyInterface',
),
'PhluxVariableEditor' => 'PhabricatorApplicationTransactionEditor',
'PhluxVariableQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhluxViewController' => 'PhluxController',
'PholioController' => 'PhabricatorController',
'PholioDAO' => 'PhabricatorLiskDAO',
'PholioImage' =>

View file

@ -32,6 +32,7 @@ final class PhabricatorPHIDConstants {
const PHID_TYPE_MCRO = 'MCRO';
const PHID_TYPE_CONF = 'CONF';
const PHID_TYPE_CONP = 'CONP';
const PHID_TYPE_PVAR = 'PVAR';
const PHID_TYPE_XACT = 'XACT';
const PHID_TYPE_XCMT = 'XCMT';

View file

@ -184,6 +184,13 @@ final class PhabricatorObjectHandleData {
->execute();
return mpull($posts, null, 'getPHID');
case PhabricatorPHIDConstants::PHID_TYPE_PVAR:
$vars = id(new PhluxVariableQuery())
->withPHIDs($phids)
->setViewer($this->viewer)
->execute();
return mpull($vars, null, 'getPHID');
}
}
@ -619,6 +626,25 @@ final class PhabricatorObjectHandleData {
}
break;
case PhabricatorPHIDConstants::PHID_TYPE_PVAR:
foreach ($phids as $phid) {
$handle = new PhabricatorObjectHandle();
$handle->setPHID($phid);
$handle->setType($type);
if (empty($objects[$phid])) {
$handle->setName('Unknown Variable');
} else {
$var = $objects[$phid];
$key = $var->getVariableKey();
$handle->setName($key);
$handle->setFullName('Phlux Variable "'.$key.'"');
$handle->setURI('/phlux/view/'.$key.'/');
$handle->setComplete(true);
}
$handles[$phid] = $handle;
}
break;
default:
$loader = null;
if (isset($external_loaders[$type])) {

View file

@ -0,0 +1,39 @@
<?php
final class PhabricatorApplicationPhlux extends PhabricatorApplication {
public function getBaseURI() {
return '/phlux/';
}
public function getShortDescription() {
return pht('Configuration Store');
}
public function getIconName() {
return 'phlux';
}
public function getTitleGlyph() {
return "\xE2\x98\xBD";
}
public function getApplicationGroup() {
return self::GROUP_UTILITIES;
}
public function isBeta() {
return true;
}
public function getRoutes() {
return array(
'/phlux/' => array(
'' => 'PhluxListController',
'view/(?P<key>[^/]+)/' => 'PhluxViewController',
'edit/(?:(?P<key>[^/]+)/)?' => 'PhluxEditController',
),
);
}
}

View file

@ -0,0 +1,16 @@
<?php
abstract class PhluxController extends PhabricatorController {
protected function buildApplicationCrumbs() {
$crumbs = parent::buildApplicationCrumbs();
$crumbs->addAction(
id(new PhabricatorMenuItemView())
->setName(pht('Create Variable'))
->setHref($this->getApplicationURI('/edit/'))
->setIcon('create'));
return $crumbs;
}
}

View file

@ -0,0 +1,201 @@
<?php
final class PhluxEditController extends PhluxController {
private $key;
public function willProcessRequest(array $data) {
$this->key = idx($data, 'key');
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$is_new = ($this->key === null);
if ($is_new) {
$var = new PhluxVariable();
$var->setViewPolicy(PhabricatorPolicies::POLICY_USER);
$var->setEditPolicy(PhabricatorPolicies::POLICY_USER);
} else {
$var = id(new PhluxVariableQuery())
->setViewer($user)
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->withKeys(array($this->key))
->executeOne();
if (!$var) {
return new Aphront404Response();
}
$view_uri = $this->getApplicationURI('/view/'.$this->key.'/');
}
$e_key = ($is_new ? true : null);
$e_value = true;
$errors = array();
$key = $var->getVariableKey();
$display_value = null;
$value = $var->getVariableValue();
if ($request->isFormPost()) {
if ($is_new) {
$key = $request->getStr('key');
if (!strlen($key)) {
$errors[] = pht('Variable key is required.');
$e_key = pht('Required');
} else if (!preg_match('/^[a-z0-9.-]+$/', $key)) {
$errors[] = pht(
'Variable key "%s" must contain only lowercase letters, digits, '.
'period, and hyphen.',
$key);
$e_key = pht('Invalid');
}
}
$raw_value = $request->getStr('value');
$value = json_decode($raw_value, true);
if ($value === null && strtolower($raw_value) !== 'null') {
$e_value = pht('Invalid');
$errors[] = pht('Variable value must be valid JSON.');
$display_value = $raw_value;
}
if (!$errors) {
$editor = id(new PhluxVariableEditor())
->setActor($user)
->setContinueOnNoEffect(true)
->setContentSource(
PhabricatorContentSource::newForSource(
PhabricatorContentSource::SOURCE_WEB,
array(
'ip' => $request->getRemoteAddr(),
)));
$xactions = array();
$xactions[] = id(new PhluxTransaction())
->setTransactionType(PhluxTransaction::TYPE_EDIT_KEY)
->setNewValue($key);
$xactions[] = id(new PhluxTransaction())
->setTransactionType(PhluxTransaction::TYPE_EDIT_VALUE)
->setNewValue($value);
$xactions[] = id(new PhluxTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)
->setNewValue($request->getStr('viewPolicy'));
$xactions[] = id(new PhluxTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY)
->setNewValue($request->getStr('editPolicy'));
try {
$editor->applyTransactions($var, $xactions);
$view_uri = $this->getApplicationURI('/view/'.$key.'/');
return id(new AphrontRedirectResponse())->setURI($view_uri);
} catch (AphrontQueryDuplicateKeyException $ex) {
$e_key = pht('Not Unique');
$errors[] = pht('Variable key must be unique.');
}
}
}
if ($display_value === null) {
if (is_array($value) &&
(array_keys($value) !== array_keys(array_values($value)))) {
$json = new PhutilJSON();
$display_value = $json->encodeFormatted($value);
} else {
$display_value = json_encode($value);
}
}
if ($errors) {
$errors = id(new AphrontErrorView())
->setErrors($errors);
}
$policies = id(new PhabricatorPolicyQuery())
->setViewer($user)
->setObject($var)
->execute();
$form = id(new AphrontFormView())
->setUser($user)
->appendChild(
id(new AphrontFormTextControl())
->setValue($var->getVariableKey())
->setLabel(pht('Key'))
->setName('key')
->setError($e_key)
->setCaption(pht('Lowercase letters, digits, dot and hyphen only.'))
->setDisabled(!$is_new))
->appendChild(
id(new AphrontFormTextAreaControl())
->setValue($display_value)
->setLabel(pht('Value'))
->setName('value')
->setCaption(pht('Enter value as JSON.'))
->setError($e_value))
->appendChild(
id(new AphrontFormPolicyControl())
->setName('viewPolicy')
->setPolicyObject($var)
->setCapability(PhabricatorPolicyCapability::CAN_VIEW)
->setPolicies($policies))
->appendChild(
id(new AphrontFormPolicyControl())
->setName('editPolicy')
->setPolicyObject($var)
->setCapability(PhabricatorPolicyCapability::CAN_EDIT)
->setPolicies($policies));
if ($is_new) {
$form->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Create Variable')));
} else {
$form->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Update Variable'))
->addCancelButton($view_uri));
}
$crumbs = $this->buildApplicationCrumbs();
if ($is_new) {
$title = pht('Create Variable');
$crumbs->addCrumb(
id(new PhabricatorCrumbView())
->setName($title)
->setHref($request->getRequestURI()));
} else {
$title = pht('Edit %s', $this->key);
$crumbs->addCrumb(
id(new PhabricatorCrumbView())
->setName($title)
->setHref($request->getRequestURI()));
}
$header = id(new PhabricatorHeaderView())
->setHeader($title);
return $this->buildApplicationPage(
array(
$crumbs,
$header,
$errors,
$form,
),
array(
'title' => $title,
'device' => true,
'dust' => true,
));
}
}

View file

@ -0,0 +1,56 @@
<?php
final class PhluxListController extends PhluxController {
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$pager = new AphrontCursorPagerView();
$pager->readFromRequest($request);
$query = id(new PhluxVariableQuery())
->setViewer($user);
$vars = $query->executeWithCursorPager($pager);
$view = new PhabricatorObjectItemListView();
foreach ($vars as $var) {
$key = $var->getVariableKey();
$item = new PhabricatorObjectItemView();
$item->setHeader($key);
$item->setHref($this->getApplicationURI('/view/'.$key.'/'));
$item->addIcon(
'none',
phabricator_datetime($var->getDateModified(), $user));
$view->addItem($item);
}
$crumbs = $this->buildApplicationCrumbs();
$title = pht('Variable List');
$crumbs->addCrumb(
id(new PhabricatorCrumbView())
->setName($title)
->setHref($this->getApplicationURI()));
$header = id(new PhabricatorHeaderView())
->setHeader($title);
return $this->buildApplicationPage(
array(
$crumbs,
$header,
$view,
$pager,
),
array(
'title' => $title,
'device' => true,
'dust' => true,
));
}
}

View file

@ -0,0 +1,99 @@
<?php
final class PhluxViewController extends PhluxController {
private $key;
public function willProcessRequest(array $data) {
$this->key = $data['key'];
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$var = id(new PhluxVariableQuery())
->setViewer($user)
->withKeys(array($this->key))
->executeOne();
if (!$var) {
return new Aphront404Response();
}
$crumbs = $this->buildApplicationCrumbs();
$title = $var->getVariableKey();
$crumbs->addCrumb(
id(new PhabricatorCrumbView())
->setName($title)
->setHref($request->getRequestURI()));
$header = id(new PhabricatorHeaderView())
->setHeader($title);
$actions = id(new PhabricatorActionListView())
->setUser($user)
->setObject($var);
$can_edit = PhabricatorPolicyFilter::hasCapability(
$user,
$var,
PhabricatorPolicyCapability::CAN_EDIT);
$actions->addAction(
id(new PhabricatorActionView())
->setIcon('edit')
->setName(pht('Edit Variable'))
->setHref($this->getApplicationURI('/edit/'.$var->getVariableKey().'/'))
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit));
$display_value = json_encode($var->getVariableValue());
$descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions(
$user,
$var);
$properties = id(new PhabricatorPropertyListView())
->setUser($user)
->setObject($var)
->addProperty(pht('Value'), $display_value)
->addProperty(
pht('Visible To'),
$descriptions[PhabricatorPolicyCapability::CAN_VIEW])
->addProperty(
pht('Editable By'),
$descriptions[PhabricatorPolicyCapability::CAN_EDIT]);
$xactions = id(new PhluxTransactionQuery())
->setViewer($user)
->withObjectPHIDs(array($var->getPHID()))
->execute();
$engine = id(new PhabricatorMarkupEngine())
->setViewer($user);
$xaction_view = id(new PhabricatorApplicationTransactionView())
->setUser($user)
->setTransactions($xactions)
->setMarkupEngine($engine);
return $this->buildApplicationPage(
array(
$crumbs,
$header,
$actions,
$properties,
$xaction_view,
),
array(
'title' => $title,
'device' => true,
'dust' => true,
));
}
}

View file

@ -0,0 +1,70 @@
<?php
final class PhluxVariableEditor
extends PhabricatorApplicationTransactionEditor {
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhluxTransaction::TYPE_EDIT_KEY;
$types[] = PhluxTransaction::TYPE_EDIT_VALUE;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types;
}
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhluxTransaction::TYPE_EDIT_KEY:
return $object->getVariableKey();
case PhluxTransaction::TYPE_EDIT_VALUE:
return $object->getVariableValue();
}
return parent::getCustomTransactionOldValue($object, $xaction);
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhluxTransaction::TYPE_EDIT_KEY:
case PhluxTransaction::TYPE_EDIT_VALUE:
return $xaction->getNewValue();
}
return parent::getCustomTransactionNewValue($object, $xaction);
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhluxTransaction::TYPE_EDIT_KEY:
$object->setVariableKey($xaction->getNewValue());
return;
case PhluxTransaction::TYPE_EDIT_VALUE:
$object->setVariableValue($xaction->getNewValue());
return;
case PhabricatorTransactions::TYPE_VIEW_POLICY:
$object->setViewPolicy($xaction->getNewValue());
return;
case PhabricatorTransactions::TYPE_EDIT_POLICY:
$object->setEditPolicy($xaction->getNewValue());
return;
}
return parent::applyCustomInternalTransaction($object, $xaction);
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhluxTransaction::TYPE_EDIT_KEY:
case PhluxTransaction::TYPE_EDIT_VALUE:
return;
}
return parent::applyCustomExternalTransaction($object, $xaction);
}
}

View file

@ -0,0 +1,10 @@
<?php
final class PhluxTransactionQuery
extends PhabricatorApplicationTransactionQuery {
protected function getTemplateApplicationTransaction() {
return new PhluxTransaction();
}
}

View file

@ -0,0 +1,68 @@
<?php
final class PhluxVariableQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $keys;
private $phids;
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withKeys(array $keys) {
$this->keys = $keys;
return $this;
}
protected function loadPage() {
$table = new PhluxVariable();
$conn_r = $table->establishConnection('r');
$rows = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($rows);
}
private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
$where[] = $this->buildPagingClause($conn_r);
if ($this->keys) {
$where[] = qsprintf(
$conn_r,
'variableKey IN (%Ls)',
$this->keys);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
return $this->formatWhereClause($where);
}
protected function getPagingColumn() {
return 'variableKey';
}
protected function getPagingValue($result) {
return $result->getVariableKey();
}
protected function getReversePaging() {
return true;
}
}

View file

@ -0,0 +1,9 @@
<?php
abstract class PhluxDAO extends PhabricatorLiskDAO {
public function getApplicationName() {
return 'phlux';
}
}

View file

@ -0,0 +1,62 @@
<?php
final class PhluxTransaction extends PhabricatorApplicationTransaction {
const TYPE_EDIT_KEY = 'phlux:key';
const TYPE_EDIT_VALUE = 'phlux:value';
public function getApplicationName() {
return 'phlux';
}
public function getApplicationTransactionType() {
return PhabricatorPHIDConstants::PHID_TYPE_PVAR;
}
public function getApplicationTransactionCommentObject() {
return null;
}
public function getApplicationObjectTypeName() {
return pht('variable');
}
public function getTitle() {
$author_phid = $this->getAuthorPHID();
switch ($this->getTransactionType()) {
case self::TYPE_EDIT_KEY:
return pht(
'%s created this variable.',
$this->renderHandleLink($author_phid));
case self::TYPE_EDIT_VALUE:
return pht(
'%s updated this variable.',
$this->renderHandleLink($author_phid));
}
return parent::getTitle();
}
public function hasChangeDetails() {
switch ($this->getTransactionType()) {
case self::TYPE_EDIT_VALUE:
return true;
}
return parent::hasChangeDetails();
}
public function renderChangeDetails(PhabricatorUser $viewer) {
$old = $this->getOldValue();
$new = $this->getNewValue();
$view = id(new PhabricatorApplicationTransactionTextDiffDetailView())
->setUser($viewer)
->setOldText(json_encode($old))
->setNewText(json_encode($new));
return $view->render();
}
}

View file

@ -0,0 +1,49 @@
<?php
final class PhluxVariable extends PhluxDAO
implements PhabricatorPolicyInterface {
protected $variableKey;
protected $variableValue;
protected $viewPolicy;
protected $editPolicy;
public function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_SERIALIZATION => array(
'variableValue' => self::SERIALIZATION_JSON
),
) + parent::getConfiguration();
}
public function generatePHID() {
return PhabricatorPHID::generateNewPHID(
PhabricatorPHIDConstants::PHID_TYPE_PVAR);
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
);
}
public function getPolicy($capability) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
return $this->viewPolicy;
case PhabricatorPolicyCapability::CAN_EDIT:
return $this->editPolicy;
}
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
return false;
}
}

View file

@ -175,6 +175,10 @@ final class PhabricatorBuiltinPatchList extends PhabricatorSQLPatchList {
'type' => 'db',
'name' => 'releeph',
),
'db.phlux' => array(
'type' => 'db',
'name' => 'phlux',
),
'0000.legacy.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('0000.legacy.sql'),
@ -1178,6 +1182,10 @@ final class PhabricatorBuiltinPatchList extends PhabricatorSQLPatchList {
'name' => $this->getPatchPath(
'20130319.phabricatorfileexplicitupload.sql'),
),
'20130320.phlux.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130320.phlux.sql'),
),
);
}