mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-18 19:40:55 +01:00
Add "Spaces", an application for managing policy namespaces
Summary: Ref T3820. This doesn't actually do anything yet, but dumps in all the plumbing. Test Plan: {F156989} {F156990} {F156991} Reviewers: btrahan Reviewed By: btrahan Subscribers: eadler, wienczny, jdloft, devurandom, thz, hwinkel, 20after4, sascha-egerer, seporaitis, joshuaspence, chad, epriestley Maniphest Tasks: T3820 Differential Revision: https://secure.phabricator.com/D9204
This commit is contained in:
parent
7a9174fa21
commit
541b4c86b4
21 changed files with 1045 additions and 0 deletions
12
resources/sql/autopatches/20150601.spaces.1.namespace.sql
Normal file
12
resources/sql/autopatches/20150601.spaces.1.namespace.sql
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
CREATE TABLE {$NAMESPACE}_spaces.spaces_namespace (
|
||||||
|
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
phid VARBINARY(64) NOT NULL,
|
||||||
|
namespaceName VARCHAR(255) NOT NULL COLLATE {$COLLATE_TEXT},
|
||||||
|
viewPolicy VARBINARY(64) NOT NULL,
|
||||||
|
editPolicy VARBINARY(64) NOT NULL,
|
||||||
|
isDefaultNamespace BOOL,
|
||||||
|
dateCreated INT UNSIGNED NOT NULL,
|
||||||
|
dateModified INT UNSIGNED NOT NULL,
|
||||||
|
UNIQUE KEY `key_phid` (phid),
|
||||||
|
UNIQUE KEY `key_default` (isDefaultNamespace)
|
||||||
|
) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
|
19
resources/sql/autopatches/20150601.spaces.2.xaction.sql
Normal file
19
resources/sql/autopatches/20150601.spaces.2.xaction.sql
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
CREATE TABLE {$NAMESPACE}_spaces.spaces_namespacetransaction (
|
||||||
|
id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||||
|
phid VARBINARY(64) NOT NULL,
|
||||||
|
authorPHID VARBINARY(64) NOT NULL,
|
||||||
|
objectPHID VARBINARY(64) NOT NULL,
|
||||||
|
viewPolicy VARBINARY(64) NOT NULL,
|
||||||
|
editPolicy VARBINARY(64) NOT NULL,
|
||||||
|
commentPHID VARBINARY(64),
|
||||||
|
commentVersion INT UNSIGNED NOT NULL,
|
||||||
|
transactionType VARCHAR(32) NOT NULL COLLATE {$COLLATE_TEXT},
|
||||||
|
oldValue LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT},
|
||||||
|
newValue LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT},
|
||||||
|
contentSource LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT},
|
||||||
|
metadata LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT},
|
||||||
|
dateCreated INT UNSIGNED NOT NULL,
|
||||||
|
dateModified INT UNSIGNED NOT NULL,
|
||||||
|
UNIQUE KEY `key_phid` (phid),
|
||||||
|
KEY `key_object` (objectPHID)
|
||||||
|
) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
|
|
@ -1318,6 +1318,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorApplicationSearchController' => 'applications/search/controller/PhabricatorApplicationSearchController.php',
|
'PhabricatorApplicationSearchController' => 'applications/search/controller/PhabricatorApplicationSearchController.php',
|
||||||
'PhabricatorApplicationSearchEngine' => 'applications/search/engine/PhabricatorApplicationSearchEngine.php',
|
'PhabricatorApplicationSearchEngine' => 'applications/search/engine/PhabricatorApplicationSearchEngine.php',
|
||||||
'PhabricatorApplicationSearchResultsControllerInterface' => 'applications/search/interface/PhabricatorApplicationSearchResultsControllerInterface.php',
|
'PhabricatorApplicationSearchResultsControllerInterface' => 'applications/search/interface/PhabricatorApplicationSearchResultsControllerInterface.php',
|
||||||
|
'PhabricatorApplicationSpaces' => 'applications/spaces/application/PhabricatorApplicationSpaces.php',
|
||||||
'PhabricatorApplicationStatusView' => 'applications/meta/view/PhabricatorApplicationStatusView.php',
|
'PhabricatorApplicationStatusView' => 'applications/meta/view/PhabricatorApplicationStatusView.php',
|
||||||
'PhabricatorApplicationTransaction' => 'applications/transactions/storage/PhabricatorApplicationTransaction.php',
|
'PhabricatorApplicationTransaction' => 'applications/transactions/storage/PhabricatorApplicationTransaction.php',
|
||||||
'PhabricatorApplicationTransactionComment' => 'applications/transactions/storage/PhabricatorApplicationTransactionComment.php',
|
'PhabricatorApplicationTransactionComment' => 'applications/transactions/storage/PhabricatorApplicationTransactionComment.php',
|
||||||
|
@ -2561,6 +2562,22 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorSlugTestCase' => 'infrastructure/util/__tests__/PhabricatorSlugTestCase.php',
|
'PhabricatorSlugTestCase' => 'infrastructure/util/__tests__/PhabricatorSlugTestCase.php',
|
||||||
'PhabricatorSortTableUIExample' => 'applications/uiexample/examples/PhabricatorSortTableUIExample.php',
|
'PhabricatorSortTableUIExample' => 'applications/uiexample/examples/PhabricatorSortTableUIExample.php',
|
||||||
'PhabricatorSourceCodeView' => 'view/layout/PhabricatorSourceCodeView.php',
|
'PhabricatorSourceCodeView' => 'view/layout/PhabricatorSourceCodeView.php',
|
||||||
|
'PhabricatorSpacesCapabilityCreateSpaces' => 'applications/spaces/capability/PhabricatorSpacesCapabilityCreateSpaces.php',
|
||||||
|
'PhabricatorSpacesCapabilityDefaultEdit' => 'applications/spaces/capability/PhabricatorSpacesCapabilityDefaultEdit.php',
|
||||||
|
'PhabricatorSpacesCapabilityDefaultView' => 'applications/spaces/capability/PhabricatorSpacesCapabilityDefaultView.php',
|
||||||
|
'PhabricatorSpacesController' => 'applications/spaces/controller/PhabricatorSpacesController.php',
|
||||||
|
'PhabricatorSpacesDAO' => 'applications/spaces/storage/PhabricatorSpacesDAO.php',
|
||||||
|
'PhabricatorSpacesEditController' => 'applications/spaces/controller/PhabricatorSpacesEditController.php',
|
||||||
|
'PhabricatorSpacesInterface' => 'applications/spaces/interface/PhabricatorSpacesInterface.php',
|
||||||
|
'PhabricatorSpacesListController' => 'applications/spaces/controller/PhabricatorSpacesListController.php',
|
||||||
|
'PhabricatorSpacesNamespace' => 'applications/spaces/storage/PhabricatorSpacesNamespace.php',
|
||||||
|
'PhabricatorSpacesNamespaceEditor' => 'applications/spaces/editor/PhabricatorSpacesNamespaceEditor.php',
|
||||||
|
'PhabricatorSpacesNamespacePHIDType' => 'applications/spaces/phid/PhabricatorSpacesNamespacePHIDType.php',
|
||||||
|
'PhabricatorSpacesNamespaceQuery' => 'applications/spaces/query/PhabricatorSpacesNamespaceQuery.php',
|
||||||
|
'PhabricatorSpacesNamespaceSearchEngine' => 'applications/spaces/query/PhabricatorSpacesNamespaceSearchEngine.php',
|
||||||
|
'PhabricatorSpacesNamespaceTransaction' => 'applications/spaces/storage/PhabricatorSpacesNamespaceTransaction.php',
|
||||||
|
'PhabricatorSpacesNamespaceTransactionQuery' => 'applications/spaces/query/PhabricatorSpacesNamespaceTransactionQuery.php',
|
||||||
|
'PhabricatorSpacesViewController' => 'applications/spaces/controller/PhabricatorSpacesViewController.php',
|
||||||
'PhabricatorStandardCustomField' => 'infrastructure/customfield/standard/PhabricatorStandardCustomField.php',
|
'PhabricatorStandardCustomField' => 'infrastructure/customfield/standard/PhabricatorStandardCustomField.php',
|
||||||
'PhabricatorStandardCustomFieldBool' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldBool.php',
|
'PhabricatorStandardCustomFieldBool' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldBool.php',
|
||||||
'PhabricatorStandardCustomFieldCredential' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldCredential.php',
|
'PhabricatorStandardCustomFieldCredential' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldCredential.php',
|
||||||
|
@ -4647,6 +4664,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorApplicationPanelController' => 'PhabricatorApplicationsController',
|
'PhabricatorApplicationPanelController' => 'PhabricatorApplicationsController',
|
||||||
'PhabricatorApplicationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
'PhabricatorApplicationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||||
'PhabricatorApplicationSearchController' => 'PhabricatorSearchBaseController',
|
'PhabricatorApplicationSearchController' => 'PhabricatorSearchBaseController',
|
||||||
|
'PhabricatorApplicationSpaces' => 'PhabricatorApplication',
|
||||||
'PhabricatorApplicationStatusView' => 'AphrontView',
|
'PhabricatorApplicationStatusView' => 'AphrontView',
|
||||||
'PhabricatorApplicationTransaction' => array(
|
'PhabricatorApplicationTransaction' => array(
|
||||||
'PhabricatorLiskDAO',
|
'PhabricatorLiskDAO',
|
||||||
|
@ -6027,6 +6045,26 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorSlugTestCase' => 'PhabricatorTestCase',
|
'PhabricatorSlugTestCase' => 'PhabricatorTestCase',
|
||||||
'PhabricatorSortTableUIExample' => 'PhabricatorUIExample',
|
'PhabricatorSortTableUIExample' => 'PhabricatorUIExample',
|
||||||
'PhabricatorSourceCodeView' => 'AphrontView',
|
'PhabricatorSourceCodeView' => 'AphrontView',
|
||||||
|
'PhabricatorSpacesCapabilityCreateSpaces' => 'PhabricatorPolicyCapability',
|
||||||
|
'PhabricatorSpacesCapabilityDefaultEdit' => 'PhabricatorPolicyCapability',
|
||||||
|
'PhabricatorSpacesCapabilityDefaultView' => 'PhabricatorPolicyCapability',
|
||||||
|
'PhabricatorSpacesController' => 'PhabricatorController',
|
||||||
|
'PhabricatorSpacesDAO' => 'PhabricatorLiskDAO',
|
||||||
|
'PhabricatorSpacesEditController' => 'PhabricatorSpacesController',
|
||||||
|
'PhabricatorSpacesInterface' => 'PhabricatorPHIDInterface',
|
||||||
|
'PhabricatorSpacesListController' => 'PhabricatorSpacesController',
|
||||||
|
'PhabricatorSpacesNamespace' => array(
|
||||||
|
'PhabricatorSpacesDAO',
|
||||||
|
'PhabricatorPolicyInterface',
|
||||||
|
'PhabricatorApplicationTransactionInterface',
|
||||||
|
),
|
||||||
|
'PhabricatorSpacesNamespaceEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||||
|
'PhabricatorSpacesNamespacePHIDType' => 'PhabricatorPHIDType',
|
||||||
|
'PhabricatorSpacesNamespaceQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||||
|
'PhabricatorSpacesNamespaceSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||||
|
'PhabricatorSpacesNamespaceTransaction' => 'PhabricatorApplicationTransaction',
|
||||||
|
'PhabricatorSpacesNamespaceTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||||
|
'PhabricatorSpacesViewController' => 'PhabricatorSpacesController',
|
||||||
'PhabricatorStandardCustomField' => 'PhabricatorCustomField',
|
'PhabricatorStandardCustomField' => 'PhabricatorCustomField',
|
||||||
'PhabricatorStandardCustomFieldBool' => 'PhabricatorStandardCustomField',
|
'PhabricatorStandardCustomFieldBool' => 'PhabricatorStandardCustomField',
|
||||||
'PhabricatorStandardCustomFieldCredential' => 'PhabricatorStandardCustomField',
|
'PhabricatorStandardCustomFieldCredential' => 'PhabricatorStandardCustomField',
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorApplicationSpaces extends PhabricatorApplication {
|
||||||
|
|
||||||
|
public function getBaseURI() {
|
||||||
|
return '/spaces/';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName() {
|
||||||
|
return pht('Spaces');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getShortDescription() {
|
||||||
|
return pht('Policy Namespaces');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFontIcon() {
|
||||||
|
return 'fa-compass';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTitleGlyph() {
|
||||||
|
return "\xE2\x97\x8B";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFlavorText() {
|
||||||
|
return pht('Control access to groups of objects.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getApplicationGroup() {
|
||||||
|
return self::GROUP_UTILITIES;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function canUninstall() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isPrototype() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRoutes() {
|
||||||
|
return array(
|
||||||
|
'/S(?P<id>[1-9]\d*)' => 'PhabricatorSpacesViewController',
|
||||||
|
'/spaces/' => array(
|
||||||
|
'(?:query/(?P<queryKey>[^/]+)/)?' => 'PhabricatorSpacesListController',
|
||||||
|
'create/' => 'PhabricatorSpacesEditController',
|
||||||
|
'edit/(?:(?P<id>\d+)/)?' => 'PhabricatorSpacesEditController',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getCustomCapabilities() {
|
||||||
|
return array(
|
||||||
|
PhabricatorSpacesCapabilityCreateSpaces::CAPABILITY => array(
|
||||||
|
'default' => PhabricatorPolicies::POLICY_ADMIN,
|
||||||
|
),
|
||||||
|
PhabricatorSpacesCapabilityDefaultView::CAPABILITY => array(
|
||||||
|
'caption' => pht('Default view policy for newly created spaces.'),
|
||||||
|
),
|
||||||
|
PhabricatorSpacesCapabilityDefaultEdit::CAPABILITY => array(
|
||||||
|
'caption' => pht('Default edit policy for newly created spaces.'),
|
||||||
|
'default' => PhabricatorPolicies::POLICY_ADMIN,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorSpacesCapabilityCreateSpaces
|
||||||
|
extends PhabricatorPolicyCapability {
|
||||||
|
|
||||||
|
const CAPABILITY = 'spaces.create';
|
||||||
|
|
||||||
|
public function getCapabilityName() {
|
||||||
|
return pht('Can Create Spaces');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function describeCapabilityRejection() {
|
||||||
|
return pht('You do not have permission to create spaces.');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorSpacesCapabilityDefaultEdit
|
||||||
|
extends PhabricatorPolicyCapability {
|
||||||
|
|
||||||
|
const CAPABILITY = 'spaces.default.edit';
|
||||||
|
|
||||||
|
public function getCapabilityName() {
|
||||||
|
return pht('Default Edit Policy');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorSpacesCapabilityDefaultView
|
||||||
|
extends PhabricatorPolicyCapability {
|
||||||
|
|
||||||
|
const CAPABILITY = 'spaces.default.view';
|
||||||
|
|
||||||
|
public function getCapabilityName() {
|
||||||
|
return pht('Default View Policy');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function shouldAllowPublicPolicySetting() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
abstract class PhabricatorSpacesController extends PhabricatorController {}
|
|
@ -0,0 +1,174 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorSpacesEditController
|
||||||
|
extends PhabricatorSpacesController {
|
||||||
|
|
||||||
|
public function handleRequest(AphrontRequest $request) {
|
||||||
|
$viewer = $request->getUser();
|
||||||
|
|
||||||
|
$make_default = false;
|
||||||
|
|
||||||
|
$id = $request->getURIData('id');
|
||||||
|
if ($id) {
|
||||||
|
$space = id(new PhabricatorSpacesNamespaceQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withIDs(array($id))
|
||||||
|
->requireCapabilities(
|
||||||
|
array(
|
||||||
|
PhabricatorPolicyCapability::CAN_VIEW,
|
||||||
|
PhabricatorPolicyCapability::CAN_EDIT,
|
||||||
|
))
|
||||||
|
->executeOne();
|
||||||
|
if (!$space) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
$is_new = false;
|
||||||
|
$cancel_uri = '/'.$space->getMonogram();
|
||||||
|
|
||||||
|
$header_text = pht('Edit %s', $space->getNamespaceName());
|
||||||
|
$title = pht('Edit Space');
|
||||||
|
$button_text = pht('Save Changes');
|
||||||
|
} else {
|
||||||
|
$this->requireApplicationCapability(
|
||||||
|
PhabricatorSpacesCapabilityCreateSpaces::CAPABILITY);
|
||||||
|
|
||||||
|
$space = PhabricatorSpacesNamespace::initializeNewNamespace($viewer);
|
||||||
|
|
||||||
|
$is_new = true;
|
||||||
|
$cancel_uri = $this->getApplicationURI();
|
||||||
|
|
||||||
|
$header_text = pht('Create Space');
|
||||||
|
$title = pht('Create Space');
|
||||||
|
$button_text = pht('Create Space');
|
||||||
|
|
||||||
|
$default = id(new PhabricatorSpacesNamespaceQuery())
|
||||||
|
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||||
|
->withIsDefaultNamespace(true)
|
||||||
|
->execute();
|
||||||
|
if (!$default) {
|
||||||
|
$make_default = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$validation_exception = null;
|
||||||
|
$e_name = true;
|
||||||
|
$v_name = $space->getNamespaceName();
|
||||||
|
$v_view = $space->getViewPolicy();
|
||||||
|
$v_edit = $space->getEditPolicy();
|
||||||
|
|
||||||
|
if ($request->isFormPost()) {
|
||||||
|
$xactions = array();
|
||||||
|
$e_name = null;
|
||||||
|
|
||||||
|
$v_name = $request->getStr('name');
|
||||||
|
$v_view = $request->getStr('viewPolicy');
|
||||||
|
$v_edit = $request->getStr('editPolicy');
|
||||||
|
|
||||||
|
$type_name = PhabricatorSpacesNamespaceTransaction::TYPE_NAME;
|
||||||
|
$type_default = PhabricatorSpacesNamespaceTransaction::TYPE_DEFAULT;
|
||||||
|
$type_view = PhabricatorTransactions::TYPE_VIEW_POLICY;
|
||||||
|
$type_edit = PhabricatorTransactions::TYPE_EDIT_POLICY;
|
||||||
|
|
||||||
|
$xactions[] = id(new PhabricatorSpacesNamespaceTransaction())
|
||||||
|
->setTransactionType($type_name)
|
||||||
|
->setNewValue($v_name);
|
||||||
|
|
||||||
|
$xactions[] = id(new PhabricatorSpacesNamespaceTransaction())
|
||||||
|
->setTransactionType($type_view)
|
||||||
|
->setNewValue($v_view);
|
||||||
|
|
||||||
|
$xactions[] = id(new PhabricatorSpacesNamespaceTransaction())
|
||||||
|
->setTransactionType($type_edit)
|
||||||
|
->setNewValue($v_edit);
|
||||||
|
|
||||||
|
if ($make_default) {
|
||||||
|
$xactions[] = id(new PhabricatorSpacesNamespaceTransaction())
|
||||||
|
->setTransactionType($type_default)
|
||||||
|
->setNewValue(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$editor = id(new PhabricatorSpacesNamespaceEditor())
|
||||||
|
->setActor($viewer)
|
||||||
|
->setContinueOnNoEffect(true)
|
||||||
|
->setContentSourceFromRequest($request);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$editor->applyTransactions($space, $xactions);
|
||||||
|
|
||||||
|
return id(new AphrontRedirectResponse())
|
||||||
|
->setURI('/'.$space->getMonogram());
|
||||||
|
} catch (PhabricatorApplicationTransactionValidationException $ex) {
|
||||||
|
$validation_exception = $ex;
|
||||||
|
|
||||||
|
$e_name = $ex->getShortMessage($type_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$policies = id(new PhabricatorPolicyQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->setObject($space)
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$form = id(new AphrontFormView())
|
||||||
|
->setUser($viewer);
|
||||||
|
|
||||||
|
if ($make_default) {
|
||||||
|
$form->appendRemarkupInstructions(
|
||||||
|
pht(
|
||||||
|
'NOTE: You are creating the **default space**. All existing '.
|
||||||
|
'objects will be put into this space. You must create a default '.
|
||||||
|
'space before you can create other spaces.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$form
|
||||||
|
->appendChild(
|
||||||
|
id(new AphrontFormTextControl())
|
||||||
|
->setLabel(pht('Name'))
|
||||||
|
->setName('name')
|
||||||
|
->setValue($v_name)
|
||||||
|
->setError($e_name))
|
||||||
|
->appendChild(
|
||||||
|
id(new AphrontFormPolicyControl())
|
||||||
|
->setUser($viewer)
|
||||||
|
->setCapability(PhabricatorPolicyCapability::CAN_VIEW)
|
||||||
|
->setPolicyObject($space)
|
||||||
|
->setPolicies($policies)
|
||||||
|
->setValue($v_view)
|
||||||
|
->setName('viewPolicy'))
|
||||||
|
->appendChild(
|
||||||
|
id(new AphrontFormPolicyControl())
|
||||||
|
->setUser($viewer)
|
||||||
|
->setCapability(PhabricatorPolicyCapability::CAN_EDIT)
|
||||||
|
->setPolicyObject($space)
|
||||||
|
->setPolicies($policies)
|
||||||
|
->setValue($v_edit)
|
||||||
|
->setName('editPolicy'))
|
||||||
|
->appendChild(
|
||||||
|
id(new AphrontFormSubmitControl())
|
||||||
|
->setValue($button_text)
|
||||||
|
->addCancelButton($cancel_uri));
|
||||||
|
|
||||||
|
$box = id(new PHUIObjectBoxView())
|
||||||
|
->setHeaderText($header_text)
|
||||||
|
->setValidationException($validation_exception)
|
||||||
|
->appendChild($form);
|
||||||
|
|
||||||
|
$crumbs = $this->buildApplicationCrumbs();
|
||||||
|
if (!$is_new) {
|
||||||
|
$crumbs->addTextCrumb(
|
||||||
|
$space->getMonogram(),
|
||||||
|
$cancel_uri);
|
||||||
|
}
|
||||||
|
$crumbs->addTextCrumb($title);
|
||||||
|
|
||||||
|
return $this->buildApplicationPage(
|
||||||
|
array(
|
||||||
|
$crumbs,
|
||||||
|
$box,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'title' => $title,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorSpacesListController
|
||||||
|
extends PhabricatorSpacesController {
|
||||||
|
|
||||||
|
public function shouldAllowPublic() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleRequest(AphrontRequest $request) {
|
||||||
|
$request = $this->getRequest();
|
||||||
|
$controller = id(new PhabricatorApplicationSearchController($request))
|
||||||
|
->setQueryKey($request->getURIData('queryKey'))
|
||||||
|
->setSearchEngine(new PhabricatorSpacesNamespaceSearchEngine())
|
||||||
|
->setNavigation($this->buildSideNavView());
|
||||||
|
|
||||||
|
return $this->delegateToController($controller);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildSideNavView($for_app = false) {
|
||||||
|
$user = $this->getRequest()->getUser();
|
||||||
|
|
||||||
|
$nav = new AphrontSideNavFilterView();
|
||||||
|
$nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
|
||||||
|
|
||||||
|
id(new PhabricatorSpacesNamespaceSearchEngine())
|
||||||
|
->setViewer($user)
|
||||||
|
->addNavigationItems($nav->getMenu());
|
||||||
|
|
||||||
|
$nav->selectFilter(null);
|
||||||
|
|
||||||
|
return $nav;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildApplicationCrumbs() {
|
||||||
|
$crumbs = parent::buildApplicationCrumbs();
|
||||||
|
|
||||||
|
$can_create = $this->hasApplicationCapability(
|
||||||
|
PhabricatorSpacesCapabilityCreateSpaces::CAPABILITY);
|
||||||
|
|
||||||
|
$crumbs->addAction(
|
||||||
|
id(new PHUIListItemView())
|
||||||
|
->setName(pht('Create Space'))
|
||||||
|
->setHref($this->getApplicationURI('create/'))
|
||||||
|
->setIcon('fa-plus-square')
|
||||||
|
->setDisabled(!$can_create)
|
||||||
|
->setWorkflow(!$can_create));
|
||||||
|
|
||||||
|
return $crumbs;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,104 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorSpacesViewController
|
||||||
|
extends PhabricatorSpacesController {
|
||||||
|
|
||||||
|
public function shouldAllowPublic() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleRequest(AphrontRequest $request) {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
|
$space = id(new PhabricatorSpacesNamespaceQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withIDs(array($request->getURIData('id')))
|
||||||
|
->executeOne();
|
||||||
|
if (!$space) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
$action_list = $this->buildActionListView($space);
|
||||||
|
$property_list = $this->buildPropertyListView($space);
|
||||||
|
$property_list->setActionList($action_list);
|
||||||
|
|
||||||
|
$xactions = id(new PhabricatorSpacesNamespaceTransactionQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withObjectPHIDs(array($space->getPHID()))
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$timeline = $this->buildTransactionTimeline(
|
||||||
|
$space,
|
||||||
|
new PhabricatorSpacesNamespaceTransactionQuery());
|
||||||
|
$timeline->setShouldTerminate(true);
|
||||||
|
|
||||||
|
$header = id(new PHUIHeaderView())
|
||||||
|
->setUser($viewer)
|
||||||
|
->setHeader($space->getNamespaceName())
|
||||||
|
->setPolicyObject($space);
|
||||||
|
|
||||||
|
$box = id(new PHUIObjectBoxView())
|
||||||
|
->setHeader($header)
|
||||||
|
->addPropertyList($property_list);
|
||||||
|
|
||||||
|
$crumbs = $this->buildApplicationCrumbs();
|
||||||
|
$crumbs->addTextCrumb($space->getMonogram());
|
||||||
|
|
||||||
|
return $this->buildApplicationPage(
|
||||||
|
array(
|
||||||
|
$crumbs,
|
||||||
|
$box,
|
||||||
|
$timeline,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'title' => array($space->getMonogram(), $space->getNamespaceName()),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildPropertyListView(PhabricatorSpacesNamespace $space) {
|
||||||
|
$viewer = $this->getRequest()->getUser();
|
||||||
|
|
||||||
|
$list = id(new PHUIPropertyListView())
|
||||||
|
->setUser($viewer);
|
||||||
|
|
||||||
|
$list->addProperty(
|
||||||
|
pht('Default Space'),
|
||||||
|
$space->getIsDefaultNamespace()
|
||||||
|
? pht('Yes')
|
||||||
|
: pht('No'));
|
||||||
|
|
||||||
|
$descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions(
|
||||||
|
$viewer,
|
||||||
|
$space);
|
||||||
|
|
||||||
|
$list->addProperty(
|
||||||
|
pht('Editable By'),
|
||||||
|
$descriptions[PhabricatorPolicyCapability::CAN_EDIT]);
|
||||||
|
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildActionListView(PhabricatorSpacesNamespace $space) {
|
||||||
|
$viewer = $this->getRequest()->getUser();
|
||||||
|
|
||||||
|
$list = id(new PhabricatorActionListView())
|
||||||
|
->setUser($viewer)
|
||||||
|
->setObjectURI('/'.$space->getMonogram());
|
||||||
|
|
||||||
|
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
||||||
|
$viewer,
|
||||||
|
$space,
|
||||||
|
PhabricatorPolicyCapability::CAN_EDIT);
|
||||||
|
|
||||||
|
$list->addAction(
|
||||||
|
id(new PhabricatorActionView())
|
||||||
|
->setName(pht('Edit Space'))
|
||||||
|
->setIcon('fa-pencil')
|
||||||
|
->setHref($this->getApplicationURI('edit/'.$space->getID().'/'))
|
||||||
|
->setWorkflow(!$can_edit)
|
||||||
|
->setDisabled(!$can_edit));
|
||||||
|
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,132 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorSpacesNamespaceEditor
|
||||||
|
extends PhabricatorApplicationTransactionEditor {
|
||||||
|
|
||||||
|
public function getEditorApplicationClass() {
|
||||||
|
return pht('PhabricatorSpacesApplication');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEditorObjectsDescription() {
|
||||||
|
return pht('Spaces');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTransactionTypes() {
|
||||||
|
$types = parent::getTransactionTypes();
|
||||||
|
|
||||||
|
$types[] = PhabricatorSpacesNamespaceTransaction::TYPE_NAME;
|
||||||
|
$types[] = PhabricatorSpacesNamespaceTransaction::TYPE_DEFAULT;
|
||||||
|
|
||||||
|
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
|
||||||
|
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
|
||||||
|
|
||||||
|
return $types;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getCustomTransactionOldValue(
|
||||||
|
PhabricatorLiskDAO $object,
|
||||||
|
PhabricatorApplicationTransaction $xaction) {
|
||||||
|
|
||||||
|
switch ($xaction->getTransactionType()) {
|
||||||
|
case PhabricatorSpacesNamespaceTransaction::TYPE_NAME:
|
||||||
|
$name = $object->getNamespaceName();
|
||||||
|
if (!strlen($name)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return $name;
|
||||||
|
case PhabricatorSpacesNamespaceTransaction::TYPE_DEFAULT:
|
||||||
|
return $object->getIsDefaultNamespace() ? 1 : null;
|
||||||
|
case PhabricatorTransactions::TYPE_VIEW_POLICY:
|
||||||
|
return $object->getViewPolicy();
|
||||||
|
case PhabricatorTransactions::TYPE_EDIT_POLICY:
|
||||||
|
return $object->getEditPolicy();
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::getCustomTransactionOldValue($object, $xaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getCustomTransactionNewValue(
|
||||||
|
PhabricatorLiskDAO $object,
|
||||||
|
PhabricatorApplicationTransaction $xaction) {
|
||||||
|
|
||||||
|
switch ($xaction->getTransactionType()) {
|
||||||
|
case PhabricatorSpacesNamespaceTransaction::TYPE_NAME:
|
||||||
|
case PhabricatorTransactions::TYPE_VIEW_POLICY:
|
||||||
|
case PhabricatorTransactions::TYPE_EDIT_POLICY:
|
||||||
|
return $xaction->getNewValue();
|
||||||
|
case PhabricatorSpacesNamespaceTransaction::TYPE_DEFAULT:
|
||||||
|
return $xaction->getNewValue() ? 1 : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::getCustomTransactionNewValue($object, $xaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function applyCustomInternalTransaction(
|
||||||
|
PhabricatorLiskDAO $object,
|
||||||
|
PhabricatorApplicationTransaction $xaction) {
|
||||||
|
|
||||||
|
$new = $xaction->getNewValue();
|
||||||
|
|
||||||
|
switch ($xaction->getTransactionType()) {
|
||||||
|
case PhabricatorSpacesNamespaceTransaction::TYPE_NAME:
|
||||||
|
$object->setNamespaceName($new);
|
||||||
|
return;
|
||||||
|
case PhabricatorSpacesNamespaceTransaction::TYPE_DEFAULT:
|
||||||
|
$object->setIsDefaultNamespace($new ? 1 : null);
|
||||||
|
return;
|
||||||
|
case PhabricatorTransactions::TYPE_VIEW_POLICY:
|
||||||
|
$object->setViewPolicy($new);
|
||||||
|
return;
|
||||||
|
case PhabricatorTransactions::TYPE_EDIT_POLICY:
|
||||||
|
$object->setEditPolicy($new);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::applyCustomInternalTransaction($object, $xaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function applyCustomExternalTransaction(
|
||||||
|
PhabricatorLiskDAO $object,
|
||||||
|
PhabricatorApplicationTransaction $xaction) {
|
||||||
|
|
||||||
|
switch ($xaction->getTransactionType()) {
|
||||||
|
case PhabricatorSpacesNamespaceTransaction::TYPE_NAME:
|
||||||
|
case PhabricatorSpacesNamespaceTransaction::TYPE_DEFAULT:
|
||||||
|
case PhabricatorTransactions::TYPE_VIEW_POLICY:
|
||||||
|
case PhabricatorTransactions::TYPE_EDIT_POLICY:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::applyCustomExternalTransaction($object, $xaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function validateTransaction(
|
||||||
|
PhabricatorLiskDAO $object,
|
||||||
|
$type,
|
||||||
|
array $xactions) {
|
||||||
|
|
||||||
|
$errors = parent::validateTransaction($object, $type, $xactions);
|
||||||
|
|
||||||
|
switch ($type) {
|
||||||
|
case PhabricatorSpacesNamespaceTransaction::TYPE_NAME:
|
||||||
|
$missing = $this->validateIsEmptyTextField(
|
||||||
|
$object->getNamespaceName(),
|
||||||
|
$xactions);
|
||||||
|
|
||||||
|
if ($missing) {
|
||||||
|
$error = new PhabricatorApplicationTransactionValidationError(
|
||||||
|
$type,
|
||||||
|
pht('Required'),
|
||||||
|
pht('Spaces must have a name.'),
|
||||||
|
nonempty(last($xactions), null));
|
||||||
|
|
||||||
|
$error->setIsMissingFieldError(true);
|
||||||
|
$errors[] = $error;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
interface PhabricatorSpacesInterface extends PhabricatorPHIDInterface {}
|
|
@ -0,0 +1,64 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorSpacesNamespacePHIDType
|
||||||
|
extends PhabricatorPHIDType {
|
||||||
|
|
||||||
|
const TYPECONST = 'SPCE';
|
||||||
|
|
||||||
|
public function getTypeName() {
|
||||||
|
return pht('Space');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newObject() {
|
||||||
|
return new PhabricatorSpacesNamespace();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function buildQueryForObjects(
|
||||||
|
PhabricatorObjectQuery $query,
|
||||||
|
array $phids) {
|
||||||
|
|
||||||
|
return id(new PhabricatorSpacesNamespaceQuery())
|
||||||
|
->withPHIDs($phids);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function loadHandles(
|
||||||
|
PhabricatorHandleQuery $query,
|
||||||
|
array $handles,
|
||||||
|
array $objects) {
|
||||||
|
|
||||||
|
foreach ($handles as $phid => $handle) {
|
||||||
|
$namespace = $objects[$phid];
|
||||||
|
$handle->setName($namespace->getNamespaceName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function canLoadNamedObject($name) {
|
||||||
|
return preg_match('/^S[1-9]\d*$/i', $name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function loadNamedObjects(
|
||||||
|
PhabricatorObjectQuery $query,
|
||||||
|
array $names) {
|
||||||
|
|
||||||
|
$id_map = array();
|
||||||
|
foreach ($names as $name) {
|
||||||
|
$id = (int)substr($name, 1);
|
||||||
|
$id_map[$id][] = $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
$objects = id(new PhabricatorSpacesNamespaceQuery())
|
||||||
|
->setViewer($query->getViewer())
|
||||||
|
->withIDs(array_keys($id_map))
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$results = array();
|
||||||
|
foreach ($objects as $id => $object) {
|
||||||
|
foreach (idx($id_map, $id, array()) as $name) {
|
||||||
|
$results[$name] = $object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorSpacesNamespaceQuery
|
||||||
|
extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||||
|
|
||||||
|
private $ids;
|
||||||
|
private $phids;
|
||||||
|
private $isDefaultNamespace;
|
||||||
|
|
||||||
|
public function withIDs(array $ids) {
|
||||||
|
$this->ids = $ids;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function withPHIDs(array $phids) {
|
||||||
|
$this->phids = $phids;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function withIsDefaultNamespace($default) {
|
||||||
|
$this->isDefaultNamespace = $default;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getQueryApplicationClass() {
|
||||||
|
return 'PhabricatorApplicationSpaces';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function loadPage() {
|
||||||
|
$table = new PhabricatorSpacesNamespace();
|
||||||
|
$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);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
|
||||||
|
$where = array();
|
||||||
|
|
||||||
|
if ($this->ids !== null) {
|
||||||
|
$where[] = qsprintf(
|
||||||
|
$conn_r,
|
||||||
|
'id IN (%Ld)',
|
||||||
|
$this->ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->phids !== null) {
|
||||||
|
$where[] = qsprintf(
|
||||||
|
$conn_r,
|
||||||
|
'phid IN (%Ls)',
|
||||||
|
$this->phids);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->isDefaultNamespace !== null) {
|
||||||
|
if ($this->isDefaultNamespace) {
|
||||||
|
$where[] = qsprintf(
|
||||||
|
$conn_r,
|
||||||
|
'isDefaultNamespace = 1');
|
||||||
|
} else {
|
||||||
|
$where[] = qsprintf(
|
||||||
|
$conn_r,
|
||||||
|
'isDefaultNamespace IS NULL');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$where[] = $this->buildPagingClause($conn_r);
|
||||||
|
return $this->formatWhereClause($where);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorSpacesNamespaceSearchEngine
|
||||||
|
extends PhabricatorApplicationSearchEngine {
|
||||||
|
|
||||||
|
public function getApplicationClassName() {
|
||||||
|
return 'PhabricatorSpacesApplication';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getResultTypeDescription() {
|
||||||
|
return pht('Spaces');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildSavedQueryFromRequest(AphrontRequest $request) {
|
||||||
|
$saved = new PhabricatorSavedQuery();
|
||||||
|
|
||||||
|
return $saved;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
|
||||||
|
$query = id(new PhabricatorSpacesNamespaceQuery());
|
||||||
|
|
||||||
|
return $query;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildSearchForm(
|
||||||
|
AphrontFormView $form,
|
||||||
|
PhabricatorSavedQuery $saved_query) {}
|
||||||
|
|
||||||
|
protected function getURI($path) {
|
||||||
|
return '/spaces/'.$path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBuiltinQueryNames() {
|
||||||
|
$names = array(
|
||||||
|
'all' => pht('All Spaces'),
|
||||||
|
);
|
||||||
|
|
||||||
|
return $names;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildSavedQueryFromBuiltin($query_key) {
|
||||||
|
|
||||||
|
$query = $this->newSavedQuery();
|
||||||
|
$query->setQueryKey($query_key);
|
||||||
|
|
||||||
|
switch ($query_key) {
|
||||||
|
case 'all':
|
||||||
|
return $query;
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::buildSavedQueryFromBuiltin($query_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function renderResultList(
|
||||||
|
array $spaces,
|
||||||
|
PhabricatorSavedQuery $query,
|
||||||
|
array $handles) {
|
||||||
|
assert_instances_of($spaces, 'PhabricatorSpacesNamespace');
|
||||||
|
|
||||||
|
$viewer = $this->requireViewer();
|
||||||
|
|
||||||
|
$list = new PHUIObjectItemListView();
|
||||||
|
$list->setUser($viewer);
|
||||||
|
foreach ($spaces as $space) {
|
||||||
|
$item = id(new PHUIObjectItemView())
|
||||||
|
->setObjectName($space->getMonogram())
|
||||||
|
->setHeader($space->getNamespaceName())
|
||||||
|
->setHref('/'.$space->getMonogram());
|
||||||
|
|
||||||
|
if ($space->getIsDefaultNamespace()) {
|
||||||
|
$item->addIcon('fa-certificate', pht('Default Space'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$list->addItem($item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorSpacesNamespaceTransactionQuery
|
||||||
|
extends PhabricatorApplicationTransactionQuery {
|
||||||
|
|
||||||
|
public function getTemplateApplicationTransaction() {
|
||||||
|
return new PhabricatorSpacesNamespaceTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
9
src/applications/spaces/storage/PhabricatorSpacesDAO.php
Normal file
9
src/applications/spaces/storage/PhabricatorSpacesDAO.php
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
abstract class PhabricatorSpacesDAO extends PhabricatorLiskDAO {
|
||||||
|
|
||||||
|
public function getApplicationName() {
|
||||||
|
return 'spaces';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
106
src/applications/spaces/storage/PhabricatorSpacesNamespace.php
Normal file
106
src/applications/spaces/storage/PhabricatorSpacesNamespace.php
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorSpacesNamespace
|
||||||
|
extends PhabricatorSpacesDAO
|
||||||
|
implements
|
||||||
|
PhabricatorPolicyInterface,
|
||||||
|
PhabricatorApplicationTransactionInterface {
|
||||||
|
|
||||||
|
protected $namespaceName;
|
||||||
|
protected $viewPolicy;
|
||||||
|
protected $editPolicy;
|
||||||
|
protected $isDefaultNamespace;
|
||||||
|
|
||||||
|
public static function initializeNewNamespace(PhabricatorUser $actor) {
|
||||||
|
$app = id(new PhabricatorApplicationQuery())
|
||||||
|
->setViewer($actor)
|
||||||
|
->withClasses(array('PhabricatorApplicationSpaces'))
|
||||||
|
->executeOne();
|
||||||
|
|
||||||
|
$view_policy = $app->getPolicy(
|
||||||
|
PhabricatorSpacesCapabilityDefaultView::CAPABILITY);
|
||||||
|
$edit_policy = $app->getPolicy(
|
||||||
|
PhabricatorSpacesCapabilityDefaultEdit::CAPABILITY);
|
||||||
|
|
||||||
|
return id(new PhabricatorSpacesNamespace())
|
||||||
|
->setIsDefaultNamespace(null)
|
||||||
|
->setViewPolicy($view_policy)
|
||||||
|
->setEditPolicy($edit_policy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getConfiguration() {
|
||||||
|
return array(
|
||||||
|
self::CONFIG_AUX_PHID => true,
|
||||||
|
self::CONFIG_COLUMN_SCHEMA => array(
|
||||||
|
'namespaceName' => 'text255',
|
||||||
|
'isDefaultNamespace' => 'bool?',
|
||||||
|
),
|
||||||
|
self::CONFIG_KEY_SCHEMA => array(
|
||||||
|
'key_default' => array(
|
||||||
|
'columns' => array('isDefaultNamespace'),
|
||||||
|
'unique' => true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
) + parent::getConfiguration();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function generatePHID() {
|
||||||
|
return PhabricatorPHID::generateNewPHID(
|
||||||
|
PhabricatorSpacesNamespacePHIDType::TYPECONST);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMonogram() {
|
||||||
|
return 'S'.$this->getID();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -( 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 null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
public function getApplicationTransactionEditor() {
|
||||||
|
return new PhabricatorSpacesNamespaceEditor();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getApplicationTransactionObject() {
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getApplicationTransactionTemplate() {
|
||||||
|
return new PhabricatorSpacesNamespaceTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function willRenderTimeline(
|
||||||
|
PhabricatorApplicationTransactionView $timeline,
|
||||||
|
AphrontRequest $request) {
|
||||||
|
return $timeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorSpacesNamespaceTransaction
|
||||||
|
extends PhabricatorApplicationTransaction {
|
||||||
|
|
||||||
|
const TYPE_NAME = 'spaces:name';
|
||||||
|
const TYPE_DEFAULT = 'spaces:default';
|
||||||
|
|
||||||
|
public function getApplicationName() {
|
||||||
|
return 'spaces';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getApplicationTransactionType() {
|
||||||
|
return PhabricatorSpacesNamespacePHIDType::TYPECONST;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getApplicationTransactionCommentObject() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTitle() {
|
||||||
|
$old = $this->getOldValue();
|
||||||
|
$new = $this->getNewValue();
|
||||||
|
|
||||||
|
$author_phid = $this->getAuthorPHID();
|
||||||
|
|
||||||
|
switch ($this->getTransactionType()) {
|
||||||
|
case self::TYPE_NAME:
|
||||||
|
if ($old === null) {
|
||||||
|
return pht(
|
||||||
|
'%s created this space.',
|
||||||
|
$this->renderHandleLink($author_phid));
|
||||||
|
} else {
|
||||||
|
return pht(
|
||||||
|
'%s renamed this space from "%s" to "%s".',
|
||||||
|
$this->renderHandleLink($author_phid),
|
||||||
|
$old,
|
||||||
|
$new);
|
||||||
|
}
|
||||||
|
case self::TYPE_DEFAULT:
|
||||||
|
return pht(
|
||||||
|
'%s made this the default space.',
|
||||||
|
$this->renderHandleLink($author_phid));
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::getTitle();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -105,6 +105,7 @@ final class PhabricatorBuiltinPatchList extends PhabricatorSQLPatchList {
|
||||||
'db.fund' => array(),
|
'db.fund' => array(),
|
||||||
'db.almanac' => array(),
|
'db.almanac' => array(),
|
||||||
'db.multimeter' => array(),
|
'db.multimeter' => array(),
|
||||||
|
'db.spaces' => array(),
|
||||||
'0000.legacy.sql' => array(
|
'0000.legacy.sql' => array(
|
||||||
'legacy' => 0,
|
'legacy' => 0,
|
||||||
),
|
),
|
||||||
|
|
Loading…
Reference in a new issue