mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-30 17:30:59 +01:00
Build AlmanacDevice UI
Summary: Ref T5833. The "uninteresting" part of this object is virtually identical to AlmanacService. Test Plan: See screenshots. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T5833 Differential Revision: https://secure.phabricator.com/D10714
This commit is contained in:
parent
796921021b
commit
247cb94d5a
20 changed files with 798 additions and 59 deletions
22
resources/sql/autopatches/20141016.almanac.device.sql
Normal file
22
resources/sql/autopatches/20141016.almanac.device.sql
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
TRUNCATE TABLE {$NAMESPACE}_almanac.almanac_device;
|
||||||
|
|
||||||
|
ALTER TABLE {$NAMESPACE}_almanac.almanac_device
|
||||||
|
CHANGE name name VARCHAR(128) NOT NULL COLLATE utf8_bin;
|
||||||
|
|
||||||
|
ALTER TABLE {$NAMESPACE}_almanac.almanac_device
|
||||||
|
ADD nameIndex BINARY(12) NOT NULL;
|
||||||
|
|
||||||
|
ALTER TABLE {$NAMESPACE}_almanac.almanac_device
|
||||||
|
ADD mailKey BINARY(20) NOT NULL;
|
||||||
|
|
||||||
|
ALTER TABLE {$NAMESPACE}_almanac.almanac_device
|
||||||
|
ADD UNIQUE KEY `key_name` (nameIndex);
|
||||||
|
|
||||||
|
ALTER TABLE {$NAMESPACE}_almanac.almanac_device
|
||||||
|
ADD KEY `key_nametext` (name);
|
||||||
|
|
||||||
|
ALTER TABLE {$NAMESPACE}_almanac.almanac_device
|
||||||
|
ADD viewPolicy VARBINARY(64) NOT NULL;
|
||||||
|
|
||||||
|
ALTER TABLE {$NAMESPACE}_almanac.almanac_device
|
||||||
|
ADD editPolicy VARBINARY(64) NOT NULL;
|
19
resources/sql/autopatches/20141016.almanac.dxaction.sql
Normal file
19
resources/sql/autopatches/20141016.almanac.dxaction.sql
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
CREATE TABLE {$NAMESPACE}_almanac.almanac_devicetransaction (
|
||||||
|
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
phid VARCHAR(64) COLLATE utf8_bin NOT NULL,
|
||||||
|
authorPHID VARCHAR(64) COLLATE utf8_bin NOT NULL,
|
||||||
|
objectPHID VARCHAR(64) COLLATE utf8_bin NOT NULL,
|
||||||
|
viewPolicy VARCHAR(64) COLLATE utf8_bin NOT NULL,
|
||||||
|
editPolicy VARCHAR(64) COLLATE utf8_bin NOT NULL,
|
||||||
|
commentPHID VARCHAR(64) COLLATE utf8_bin DEFAULT NULL,
|
||||||
|
commentVersion INT UNSIGNED NOT NULL,
|
||||||
|
transactionType VARCHAR(32) COLLATE utf8_bin NOT NULL,
|
||||||
|
oldValue LONGTEXT COLLATE utf8_bin NOT NULL,
|
||||||
|
newValue LONGTEXT COLLATE utf8_bin NOT NULL,
|
||||||
|
contentSource LONGTEXT COLLATE utf8_bin NOT NULL,
|
||||||
|
metadata LONGTEXT COLLATE utf8_bin NOT NULL,
|
||||||
|
dateCreated INT UNSIGNED NOT NULL,
|
||||||
|
dateModified INT UNSIGNED NOT NULL,
|
||||||
|
UNIQUE KEY `key_phid` (`phid`),
|
||||||
|
KEY `key_object` (`objectPHID`)
|
||||||
|
) ENGINE=InnoDB, COLLATE utf8_general_ci;
|
|
@ -12,14 +12,25 @@ phutil_register_library_map(array(
|
||||||
'AlmanacConduitUtil' => 'applications/almanac/util/AlmanacConduitUtil.php',
|
'AlmanacConduitUtil' => 'applications/almanac/util/AlmanacConduitUtil.php',
|
||||||
'AlmanacConsoleController' => 'applications/almanac/controller/AlmanacConsoleController.php',
|
'AlmanacConsoleController' => 'applications/almanac/controller/AlmanacConsoleController.php',
|
||||||
'AlmanacController' => 'applications/almanac/controller/AlmanacController.php',
|
'AlmanacController' => 'applications/almanac/controller/AlmanacController.php',
|
||||||
|
'AlmanacCreateDevicesCapability' => 'applications/almanac/capability/AlmanacCreateDevicesCapability.php',
|
||||||
'AlmanacCreateServicesCapability' => 'applications/almanac/capability/AlmanacCreateServicesCapability.php',
|
'AlmanacCreateServicesCapability' => 'applications/almanac/capability/AlmanacCreateServicesCapability.php',
|
||||||
'AlmanacDAO' => 'applications/almanac/storage/AlmanacDAO.php',
|
'AlmanacDAO' => 'applications/almanac/storage/AlmanacDAO.php',
|
||||||
'AlmanacDevice' => 'applications/almanac/storage/AlmanacDevice.php',
|
'AlmanacDevice' => 'applications/almanac/storage/AlmanacDevice.php',
|
||||||
|
'AlmanacDeviceController' => 'applications/almanac/controller/AlmanacDeviceController.php',
|
||||||
|
'AlmanacDeviceEditController' => 'applications/almanac/controller/AlmanacDeviceEditController.php',
|
||||||
|
'AlmanacDeviceEditor' => 'applications/almanac/editor/AlmanacDeviceEditor.php',
|
||||||
|
'AlmanacDeviceListController' => 'applications/almanac/controller/AlmanacDeviceListController.php',
|
||||||
'AlmanacDevicePHIDType' => 'applications/almanac/phid/AlmanacDevicePHIDType.php',
|
'AlmanacDevicePHIDType' => 'applications/almanac/phid/AlmanacDevicePHIDType.php',
|
||||||
'AlmanacDeviceProperty' => 'applications/almanac/storage/AlmanacDeviceProperty.php',
|
'AlmanacDeviceProperty' => 'applications/almanac/storage/AlmanacDeviceProperty.php',
|
||||||
'AlmanacDeviceQuery' => 'applications/almanac/query/AlmanacDeviceQuery.php',
|
'AlmanacDeviceQuery' => 'applications/almanac/query/AlmanacDeviceQuery.php',
|
||||||
|
'AlmanacDeviceSearchEngine' => 'applications/almanac/query/AlmanacDeviceSearchEngine.php',
|
||||||
|
'AlmanacDeviceTransaction' => 'applications/almanac/storage/AlmanacDeviceTransaction.php',
|
||||||
|
'AlmanacDeviceTransactionQuery' => 'applications/almanac/query/AlmanacDeviceTransactionQuery.php',
|
||||||
|
'AlmanacDeviceViewController' => 'applications/almanac/controller/AlmanacDeviceViewController.php',
|
||||||
'AlmanacManagementRegisterWorkflow' => 'applications/almanac/management/AlmanacManagementRegisterWorkflow.php',
|
'AlmanacManagementRegisterWorkflow' => 'applications/almanac/management/AlmanacManagementRegisterWorkflow.php',
|
||||||
'AlmanacManagementWorkflow' => 'applications/almanac/management/AlmanacManagementWorkflow.php',
|
'AlmanacManagementWorkflow' => 'applications/almanac/management/AlmanacManagementWorkflow.php',
|
||||||
|
'AlmanacNames' => 'applications/almanac/util/AlmanacNames.php',
|
||||||
|
'AlmanacNamesTestCase' => 'applications/almanac/util/__tests__/AlmanacNamesTestCase.php',
|
||||||
'AlmanacService' => 'applications/almanac/storage/AlmanacService.php',
|
'AlmanacService' => 'applications/almanac/storage/AlmanacService.php',
|
||||||
'AlmanacServiceController' => 'applications/almanac/controller/AlmanacServiceController.php',
|
'AlmanacServiceController' => 'applications/almanac/controller/AlmanacServiceController.php',
|
||||||
'AlmanacServiceEditController' => 'applications/almanac/controller/AlmanacServiceEditController.php',
|
'AlmanacServiceEditController' => 'applications/almanac/controller/AlmanacServiceEditController.php',
|
||||||
|
@ -28,7 +39,6 @@ phutil_register_library_map(array(
|
||||||
'AlmanacServicePHIDType' => 'applications/almanac/phid/AlmanacServicePHIDType.php',
|
'AlmanacServicePHIDType' => 'applications/almanac/phid/AlmanacServicePHIDType.php',
|
||||||
'AlmanacServiceQuery' => 'applications/almanac/query/AlmanacServiceQuery.php',
|
'AlmanacServiceQuery' => 'applications/almanac/query/AlmanacServiceQuery.php',
|
||||||
'AlmanacServiceSearchEngine' => 'applications/almanac/query/AlmanacServiceSearchEngine.php',
|
'AlmanacServiceSearchEngine' => 'applications/almanac/query/AlmanacServiceSearchEngine.php',
|
||||||
'AlmanacServiceTestCase' => 'applications/almanac/storage/__tests__/AlmanacServiceTestCase.php',
|
|
||||||
'AlmanacServiceTransaction' => 'applications/almanac/storage/AlmanacServiceTransaction.php',
|
'AlmanacServiceTransaction' => 'applications/almanac/storage/AlmanacServiceTransaction.php',
|
||||||
'AlmanacServiceTransactionQuery' => 'applications/almanac/query/AlmanacServiceTransactionQuery.php',
|
'AlmanacServiceTransactionQuery' => 'applications/almanac/query/AlmanacServiceTransactionQuery.php',
|
||||||
'AlmanacServiceViewController' => 'applications/almanac/controller/AlmanacServiceViewController.php',
|
'AlmanacServiceViewController' => 'applications/almanac/controller/AlmanacServiceViewController.php',
|
||||||
|
@ -2921,17 +2931,28 @@ phutil_register_library_map(array(
|
||||||
'AlmanacConduitUtil' => 'Phobject',
|
'AlmanacConduitUtil' => 'Phobject',
|
||||||
'AlmanacConsoleController' => 'AlmanacController',
|
'AlmanacConsoleController' => 'AlmanacController',
|
||||||
'AlmanacController' => 'PhabricatorController',
|
'AlmanacController' => 'PhabricatorController',
|
||||||
|
'AlmanacCreateDevicesCapability' => 'PhabricatorPolicyCapability',
|
||||||
'AlmanacCreateServicesCapability' => 'PhabricatorPolicyCapability',
|
'AlmanacCreateServicesCapability' => 'PhabricatorPolicyCapability',
|
||||||
'AlmanacDAO' => 'PhabricatorLiskDAO',
|
'AlmanacDAO' => 'PhabricatorLiskDAO',
|
||||||
'AlmanacDevice' => array(
|
'AlmanacDevice' => array(
|
||||||
'AlmanacDAO',
|
'AlmanacDAO',
|
||||||
'PhabricatorPolicyInterface',
|
'PhabricatorPolicyInterface',
|
||||||
),
|
),
|
||||||
|
'AlmanacDeviceController' => 'AlmanacController',
|
||||||
|
'AlmanacDeviceEditController' => 'AlmanacDeviceController',
|
||||||
|
'AlmanacDeviceEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||||
|
'AlmanacDeviceListController' => 'AlmanacDeviceController',
|
||||||
'AlmanacDevicePHIDType' => 'PhabricatorPHIDType',
|
'AlmanacDevicePHIDType' => 'PhabricatorPHIDType',
|
||||||
'AlmanacDeviceProperty' => 'AlmanacDAO',
|
'AlmanacDeviceProperty' => 'AlmanacDAO',
|
||||||
'AlmanacDeviceQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
'AlmanacDeviceQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||||
|
'AlmanacDeviceSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||||
|
'AlmanacDeviceTransaction' => 'PhabricatorApplicationTransaction',
|
||||||
|
'AlmanacDeviceTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||||
|
'AlmanacDeviceViewController' => 'AlmanacDeviceController',
|
||||||
'AlmanacManagementRegisterWorkflow' => 'AlmanacManagementWorkflow',
|
'AlmanacManagementRegisterWorkflow' => 'AlmanacManagementWorkflow',
|
||||||
'AlmanacManagementWorkflow' => 'PhabricatorManagementWorkflow',
|
'AlmanacManagementWorkflow' => 'PhabricatorManagementWorkflow',
|
||||||
|
'AlmanacNames' => 'Phobject',
|
||||||
|
'AlmanacNamesTestCase' => 'PhabricatorTestCase',
|
||||||
'AlmanacService' => array(
|
'AlmanacService' => array(
|
||||||
'AlmanacDAO',
|
'AlmanacDAO',
|
||||||
'PhabricatorPolicyInterface',
|
'PhabricatorPolicyInterface',
|
||||||
|
@ -2943,7 +2964,6 @@ phutil_register_library_map(array(
|
||||||
'AlmanacServicePHIDType' => 'PhabricatorPHIDType',
|
'AlmanacServicePHIDType' => 'PhabricatorPHIDType',
|
||||||
'AlmanacServiceQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
'AlmanacServiceQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||||
'AlmanacServiceSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
'AlmanacServiceSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||||
'AlmanacServiceTestCase' => 'PhabricatorTestCase',
|
|
||||||
'AlmanacServiceTransaction' => 'PhabricatorApplicationTransaction',
|
'AlmanacServiceTransaction' => 'PhabricatorApplicationTransaction',
|
||||||
'AlmanacServiceTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
'AlmanacServiceTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||||
'AlmanacServiceViewController' => 'AlmanacServiceController',
|
'AlmanacServiceViewController' => 'AlmanacServiceController',
|
||||||
|
|
|
@ -39,6 +39,11 @@ final class PhabricatorAlmanacApplication extends PhabricatorApplication {
|
||||||
'edit/(?:(?P<id>\d+)/)?' => 'AlmanacServiceEditController',
|
'edit/(?:(?P<id>\d+)/)?' => 'AlmanacServiceEditController',
|
||||||
'view/(?P<name>[^/]+)/' => 'AlmanacServiceViewController',
|
'view/(?P<name>[^/]+)/' => 'AlmanacServiceViewController',
|
||||||
),
|
),
|
||||||
|
'device/' => array(
|
||||||
|
'(?:query/(?P<queryKey>[^/]+)/)?' => 'AlmanacDeviceListController',
|
||||||
|
'edit/(?:(?P<id>\d+)/)?' => 'AlmanacDeviceEditController',
|
||||||
|
'view/(?P<name>[^/]+)/' => 'AlmanacDeviceViewController',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -48,6 +53,9 @@ final class PhabricatorAlmanacApplication extends PhabricatorApplication {
|
||||||
AlmanacCreateServicesCapability::CAPABILITY => array(
|
AlmanacCreateServicesCapability::CAPABILITY => array(
|
||||||
'default' => PhabricatorPolicies::POLICY_ADMIN,
|
'default' => PhabricatorPolicies::POLICY_ADMIN,
|
||||||
),
|
),
|
||||||
|
AlmanacCreateDevicesCapability::CAPABILITY => array(
|
||||||
|
'default' => PhabricatorPolicies::POLICY_ADMIN,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class AlmanacCreateDevicesCapability
|
||||||
|
extends PhabricatorPolicyCapability {
|
||||||
|
|
||||||
|
const CAPABILITY = 'almanac.devices';
|
||||||
|
|
||||||
|
public function getCapabilityName() {
|
||||||
|
return pht('Can Create Devices');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function describeCapabilityRejection() {
|
||||||
|
return pht('You do not have permission to create Almanac devices.');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -20,6 +20,14 @@ final class AlmanacConsoleController extends AlmanacController {
|
||||||
pht(
|
pht(
|
||||||
'Manage Almanac services.')));
|
'Manage Almanac services.')));
|
||||||
|
|
||||||
|
$menu->addItem(
|
||||||
|
id(new PHUIObjectItemView())
|
||||||
|
->setHeader(pht('Devices'))
|
||||||
|
->setHref($this->getApplicationURI('device/'))
|
||||||
|
->addAttribute(
|
||||||
|
pht(
|
||||||
|
'Manage Almanac devices.')));
|
||||||
|
|
||||||
$crumbs = $this->buildApplicationCrumbs();
|
$crumbs = $this->buildApplicationCrumbs();
|
||||||
$crumbs->addTextCrumb(pht('Console'));
|
$crumbs->addTextCrumb(pht('Console'));
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
abstract class AlmanacDeviceController extends AlmanacController {
|
||||||
|
|
||||||
|
public function buildApplicationCrumbs() {
|
||||||
|
$crumbs = parent::buildApplicationCrumbs();
|
||||||
|
|
||||||
|
$list_uri = $this->getApplicationURI('device/');
|
||||||
|
$crumbs->addTextCrumb(pht('Devices'), $list_uri);
|
||||||
|
|
||||||
|
return $crumbs;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,142 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class AlmanacDeviceEditController
|
||||||
|
extends AlmanacDeviceController {
|
||||||
|
|
||||||
|
public function handleRequest(AphrontRequest $request) {
|
||||||
|
$viewer = $request->getViewer();
|
||||||
|
|
||||||
|
$list_uri = $this->getApplicationURI('device/');
|
||||||
|
|
||||||
|
$id = $request->getURIData('id');
|
||||||
|
if ($id) {
|
||||||
|
$device = id(new AlmanacDeviceQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withIDs(array($id))
|
||||||
|
->requireCapabilities(
|
||||||
|
array(
|
||||||
|
PhabricatorPolicyCapability::CAN_VIEW,
|
||||||
|
PhabricatorPolicyCapability::CAN_EDIT,
|
||||||
|
))
|
||||||
|
->executeOne();
|
||||||
|
if (!$device) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
$is_new = false;
|
||||||
|
$device_uri = $device->getURI();
|
||||||
|
$cancel_uri = $device_uri;
|
||||||
|
$title = pht('Edit Device');
|
||||||
|
$save_button = pht('Save Changes');
|
||||||
|
} else {
|
||||||
|
$this->requireApplicationCapability(
|
||||||
|
AlmanacCreateDevicesCapability::CAPABILITY);
|
||||||
|
|
||||||
|
$device = AlmanacDevice::initializeNewDevice();
|
||||||
|
$is_new = true;
|
||||||
|
|
||||||
|
$cancel_uri = $list_uri;
|
||||||
|
$title = pht('Create Device');
|
||||||
|
$save_button = pht('Create Device');
|
||||||
|
}
|
||||||
|
|
||||||
|
$v_name = $device->getName();
|
||||||
|
$e_name = true;
|
||||||
|
$validation_exception = null;
|
||||||
|
|
||||||
|
if ($request->isFormPost()) {
|
||||||
|
$v_name = $request->getStr('name');
|
||||||
|
$v_view = $request->getStr('viewPolicy');
|
||||||
|
$v_edit = $request->getStr('editPolicy');
|
||||||
|
|
||||||
|
$type_name = AlmanacDeviceTransaction::TYPE_NAME;
|
||||||
|
$type_view = PhabricatorTransactions::TYPE_VIEW_POLICY;
|
||||||
|
$type_edit = PhabricatorTransactions::TYPE_EDIT_POLICY;
|
||||||
|
|
||||||
|
$xactions = array();
|
||||||
|
|
||||||
|
$xactions[] = id(new AlmanacDeviceTransaction())
|
||||||
|
->setTransactionType($type_name)
|
||||||
|
->setNewValue($v_name);
|
||||||
|
|
||||||
|
$xactions[] = id(new AlmanacDeviceTransaction())
|
||||||
|
->setTransactionType($type_view)
|
||||||
|
->setNewValue($v_view);
|
||||||
|
|
||||||
|
$xactions[] = id(new AlmanacDeviceTransaction())
|
||||||
|
->setTransactionType($type_edit)
|
||||||
|
->setNewValue($v_edit);
|
||||||
|
|
||||||
|
$editor = id(new AlmanacDeviceEditor())
|
||||||
|
->setActor($viewer)
|
||||||
|
->setContentSourceFromRequest($request)
|
||||||
|
->setContinueOnNoEffect(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$editor->applyTransactions($device, $xactions);
|
||||||
|
|
||||||
|
$device_uri = $device->getURI();
|
||||||
|
return id(new AphrontRedirectResponse())->setURI($device_uri);
|
||||||
|
} catch (PhabricatorApplicationTransactionValidationException $ex) {
|
||||||
|
$validation_exception = $ex;
|
||||||
|
$e_name = $ex->getShortMessage($type_name);
|
||||||
|
|
||||||
|
$device->setViewPolicy($v_view);
|
||||||
|
$device->setEditPolicy($v_edit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$policies = id(new PhabricatorPolicyQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->setObject($device)
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$form = id(new AphrontFormView())
|
||||||
|
->setUser($viewer)
|
||||||
|
->appendChild(
|
||||||
|
id(new AphrontFormTextControl())
|
||||||
|
->setLabel(pht('Name'))
|
||||||
|
->setName('name')
|
||||||
|
->setValue($v_name)
|
||||||
|
->setError($e_name))
|
||||||
|
->appendChild(
|
||||||
|
id(new AphrontFormPolicyControl())
|
||||||
|
->setName('viewPolicy')
|
||||||
|
->setPolicyObject($device)
|
||||||
|
->setCapability(PhabricatorPolicyCapability::CAN_VIEW)
|
||||||
|
->setPolicies($policies))
|
||||||
|
->appendChild(
|
||||||
|
id(new AphrontFormPolicyControl())
|
||||||
|
->setName('editPolicy')
|
||||||
|
->setPolicyObject($device)
|
||||||
|
->setCapability(PhabricatorPolicyCapability::CAN_EDIT)
|
||||||
|
->setPolicies($policies))
|
||||||
|
->appendChild(
|
||||||
|
id(new AphrontFormSubmitControl())
|
||||||
|
->addCancelButton($cancel_uri)
|
||||||
|
->setValue($save_button));
|
||||||
|
|
||||||
|
$box = id(new PHUIObjectBoxView())
|
||||||
|
->setValidationException($validation_exception)
|
||||||
|
->setHeaderText($title)
|
||||||
|
->appendChild($form);
|
||||||
|
|
||||||
|
$crumbs = $this->buildApplicationCrumbs();
|
||||||
|
if ($is_new) {
|
||||||
|
$crumbs->addTextCrumb(pht('Create Device'));
|
||||||
|
} else {
|
||||||
|
$crumbs->addTextCrumb($device->getName(), $device_uri);
|
||||||
|
$crumbs->addTextCrumb(pht('Edit'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->buildApplicationPage(
|
||||||
|
array(
|
||||||
|
$crumbs,
|
||||||
|
$box,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'title' => $title,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class AlmanacDeviceListController
|
||||||
|
extends AlmanacDeviceController {
|
||||||
|
|
||||||
|
public function shouldAllowPublic() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleRequest(AphrontRequest $request) {
|
||||||
|
$controller = id(new PhabricatorApplicationSearchController())
|
||||||
|
->setQueryKey($request->getURIData('queryKey'))
|
||||||
|
->setSearchEngine(new AlmanacDeviceSearchEngine())
|
||||||
|
->setNavigation($this->buildSideNavView());
|
||||||
|
|
||||||
|
return $this->delegateToController($controller);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildApplicationCrumbs() {
|
||||||
|
$crumbs = parent::buildApplicationCrumbs();
|
||||||
|
|
||||||
|
$can_create = $this->hasApplicationCapability(
|
||||||
|
AlmanacCreateDevicesCapability::CAPABILITY);
|
||||||
|
|
||||||
|
$crumbs->addAction(
|
||||||
|
id(new PHUIListItemView())
|
||||||
|
->setName(pht('Create Device'))
|
||||||
|
->setHref($this->getApplicationURI('device/edit/'))
|
||||||
|
->setIcon('fa-plus-square')
|
||||||
|
->setDisabled(!$can_create)
|
||||||
|
->setWorkflow(!$can_create));
|
||||||
|
|
||||||
|
return $crumbs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildSideNavView() {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
|
$nav = new AphrontSideNavFilterView();
|
||||||
|
$nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
|
||||||
|
|
||||||
|
id(new AlmanacDeviceSearchEngine())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->addNavigationItems($nav->getMenu());
|
||||||
|
|
||||||
|
$nav->selectFilter(null);
|
||||||
|
|
||||||
|
return $nav;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class AlmanacDeviceViewController
|
||||||
|
extends AlmanacDeviceController {
|
||||||
|
|
||||||
|
public function shouldAllowPublic() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleRequest(AphrontRequest $request) {
|
||||||
|
$viewer = $request->getViewer();
|
||||||
|
|
||||||
|
$name = $request->getURIData('name');
|
||||||
|
|
||||||
|
$device = id(new AlmanacDeviceQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withNames(array($name))
|
||||||
|
->executeOne();
|
||||||
|
if (!$device) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
$title = pht('Device %s', $device->getName());
|
||||||
|
|
||||||
|
$property_list = $this->buildPropertyList($device);
|
||||||
|
$action_list = $this->buildActionList($device);
|
||||||
|
$property_list->setActionList($action_list);
|
||||||
|
|
||||||
|
$header = id(new PHUIHeaderView())
|
||||||
|
->setUser($viewer)
|
||||||
|
->setHeader($device->getName())
|
||||||
|
->setPolicyObject($device);
|
||||||
|
|
||||||
|
$box = id(new PHUIObjectBoxView())
|
||||||
|
->setHeader($header)
|
||||||
|
->addPropertyList($property_list);
|
||||||
|
|
||||||
|
$crumbs = $this->buildApplicationCrumbs();
|
||||||
|
$crumbs->addTextCrumb($device->getName());
|
||||||
|
|
||||||
|
$xactions = id(new AlmanacDeviceTransactionQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withObjectPHIDs(array($device->getPHID()))
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$xaction_view = id(new PhabricatorApplicationTransactionView())
|
||||||
|
->setUser($viewer)
|
||||||
|
->setObjectPHID($device->getPHID())
|
||||||
|
->setTransactions($xactions)
|
||||||
|
->setShouldTerminate(true);
|
||||||
|
|
||||||
|
return $this->buildApplicationPage(
|
||||||
|
array(
|
||||||
|
$crumbs,
|
||||||
|
$box,
|
||||||
|
$xaction_view,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'title' => $title,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildPropertyList(AlmanacDevice $device) {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
|
$properties = id(new PHUIPropertyListView())
|
||||||
|
->setUser($viewer);
|
||||||
|
|
||||||
|
return $properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildActionList(AlmanacDevice $device) {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
$id = $device->getID();
|
||||||
|
|
||||||
|
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
||||||
|
$viewer,
|
||||||
|
$device,
|
||||||
|
PhabricatorPolicyCapability::CAN_EDIT);
|
||||||
|
|
||||||
|
$actions = id(new PhabricatorActionListView())
|
||||||
|
->setUser($viewer);
|
||||||
|
|
||||||
|
$actions->addAction(
|
||||||
|
id(new PhabricatorActionView())
|
||||||
|
->setIcon('fa-pencil')
|
||||||
|
->setName(pht('Edit Device'))
|
||||||
|
->setHref($this->getApplicationURI("device/edit/{$id}/"))
|
||||||
|
->setWorkflow(!$can_edit)
|
||||||
|
->setDisabled(!$can_edit));
|
||||||
|
|
||||||
|
return $actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
144
src/applications/almanac/editor/AlmanacDeviceEditor.php
Normal file
144
src/applications/almanac/editor/AlmanacDeviceEditor.php
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class AlmanacDeviceEditor
|
||||||
|
extends PhabricatorApplicationTransactionEditor {
|
||||||
|
|
||||||
|
public function getEditorApplicationClass() {
|
||||||
|
return 'PhabricatorAlmanacApplication';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEditorObjectsDescription() {
|
||||||
|
return pht('Almanac Device');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTransactionTypes() {
|
||||||
|
$types = parent::getTransactionTypes();
|
||||||
|
|
||||||
|
$types[] = AlmanacDeviceTransaction::TYPE_NAME;
|
||||||
|
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
|
||||||
|
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
|
||||||
|
|
||||||
|
return $types;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getCustomTransactionOldValue(
|
||||||
|
PhabricatorLiskDAO $object,
|
||||||
|
PhabricatorApplicationTransaction $xaction) {
|
||||||
|
switch ($xaction->getTransactionType()) {
|
||||||
|
case AlmanacDeviceTransaction::TYPE_NAME:
|
||||||
|
return $object->getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::getCustomTransactionOldValue($object, $xaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getCustomTransactionNewValue(
|
||||||
|
PhabricatorLiskDAO $object,
|
||||||
|
PhabricatorApplicationTransaction $xaction) {
|
||||||
|
|
||||||
|
switch ($xaction->getTransactionType()) {
|
||||||
|
case AlmanacDeviceTransaction::TYPE_NAME:
|
||||||
|
return $xaction->getNewValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::getCustomTransactionNewValue($object, $xaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function applyCustomInternalTransaction(
|
||||||
|
PhabricatorLiskDAO $object,
|
||||||
|
PhabricatorApplicationTransaction $xaction) {
|
||||||
|
|
||||||
|
switch ($xaction->getTransactionType()) {
|
||||||
|
case AlmanacDeviceTransaction::TYPE_NAME:
|
||||||
|
$object->setName($xaction->getNewValue());
|
||||||
|
return;
|
||||||
|
case PhabricatorTransactions::TYPE_VIEW_POLICY:
|
||||||
|
case PhabricatorTransactions::TYPE_EDIT_POLICY:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::applyCustomInternalTransaction($object, $xaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function applyCustomExternalTransaction(
|
||||||
|
PhabricatorLiskDAO $object,
|
||||||
|
PhabricatorApplicationTransaction $xaction) {
|
||||||
|
|
||||||
|
switch ($xaction->getTransactionType()) {
|
||||||
|
case AlmanacDeviceTransaction::TYPE_NAME:
|
||||||
|
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 AlmanacDeviceTransaction::TYPE_NAME:
|
||||||
|
$missing = $this->validateIsEmptyTextField(
|
||||||
|
$object->getName(),
|
||||||
|
$xactions);
|
||||||
|
|
||||||
|
if ($missing) {
|
||||||
|
$error = new PhabricatorApplicationTransactionValidationError(
|
||||||
|
$type,
|
||||||
|
pht('Required'),
|
||||||
|
pht('Device name is required.'),
|
||||||
|
nonempty(last($xactions), null));
|
||||||
|
|
||||||
|
$error->setIsMissingFieldError(true);
|
||||||
|
$errors[] = $error;
|
||||||
|
} else {
|
||||||
|
foreach ($xactions as $xaction) {
|
||||||
|
$message = null;
|
||||||
|
$name = $xaction->getNewValue();
|
||||||
|
|
||||||
|
try {
|
||||||
|
AlmanacNames::validateServiceOrDeviceName($name);
|
||||||
|
} catch (Exception $ex) {
|
||||||
|
$message = $ex->getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($message !== null) {
|
||||||
|
$error = new PhabricatorApplicationTransactionValidationError(
|
||||||
|
$type,
|
||||||
|
pht('Invalid'),
|
||||||
|
$message,
|
||||||
|
$xaction);
|
||||||
|
$errors[] = $error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($xactions) {
|
||||||
|
$duplicate = id(new AlmanacDeviceQuery())
|
||||||
|
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||||
|
->withNames(array(last($xactions)->getNewValue()))
|
||||||
|
->executeOne();
|
||||||
|
if ($duplicate && ($duplicate->getID() != $object->getID())) {
|
||||||
|
$error = new PhabricatorApplicationTransactionValidationError(
|
||||||
|
$type,
|
||||||
|
pht('Not Unique'),
|
||||||
|
pht('Almanac devices must have unique names.'),
|
||||||
|
last($xactions));
|
||||||
|
$errors[] = $error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -100,8 +100,10 @@ final class AlmanacServiceEditor
|
||||||
foreach ($xactions as $xaction) {
|
foreach ($xactions as $xaction) {
|
||||||
$message = null;
|
$message = null;
|
||||||
|
|
||||||
|
$name = $xaction->getNewValue();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
AlmanacService::validateServiceName($xaction->getNewValue());
|
AlmanacNames::validateServiceOrDeviceName($name);
|
||||||
} catch (Exception $ex) {
|
} catch (Exception $ex) {
|
||||||
$message = $ex->getMessage();
|
$message = $ex->getMessage();
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ final class AlmanacDeviceQuery
|
||||||
|
|
||||||
private $ids;
|
private $ids;
|
||||||
private $phids;
|
private $phids;
|
||||||
|
private $names;
|
||||||
|
|
||||||
public function withIDs(array $ids) {
|
public function withIDs(array $ids) {
|
||||||
$this->ids = $ids;
|
$this->ids = $ids;
|
||||||
|
@ -16,6 +17,11 @@ final class AlmanacDeviceQuery
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function withNames(array $names) {
|
||||||
|
$this->names = $names;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
protected function loadPage() {
|
protected function loadPage() {
|
||||||
$table = new AlmanacDevice();
|
$table = new AlmanacDevice();
|
||||||
$conn_r = $table->establishConnection('r');
|
$conn_r = $table->establishConnection('r');
|
||||||
|
@ -48,6 +54,17 @@ final class AlmanacDeviceQuery
|
||||||
$this->phids);
|
$this->phids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->names !== null) {
|
||||||
|
$hashes = array();
|
||||||
|
foreach ($this->names as $name) {
|
||||||
|
$hashes[] = PhabricatorHash::digestForIndex($name);
|
||||||
|
}
|
||||||
|
$where[] = qsprintf(
|
||||||
|
$conn_r,
|
||||||
|
'nameIndex IN (%Ls)',
|
||||||
|
$hashes);
|
||||||
|
}
|
||||||
|
|
||||||
$where[] = $this->buildPagingClause($conn_r);
|
$where[] = $this->buildPagingClause($conn_r);
|
||||||
|
|
||||||
return $this->formatWhereClause($where);
|
return $this->formatWhereClause($where);
|
||||||
|
|
79
src/applications/almanac/query/AlmanacDeviceSearchEngine.php
Normal file
79
src/applications/almanac/query/AlmanacDeviceSearchEngine.php
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class AlmanacDeviceSearchEngine
|
||||||
|
extends PhabricatorApplicationSearchEngine {
|
||||||
|
|
||||||
|
public function getResultTypeDescription() {
|
||||||
|
return pht('Almanac Devices');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildSavedQueryFromRequest(AphrontRequest $request) {
|
||||||
|
$saved = new PhabricatorSavedQuery();
|
||||||
|
|
||||||
|
return $saved;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
|
||||||
|
$query = id(new AlmanacDeviceQuery());
|
||||||
|
|
||||||
|
return $query;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildSearchForm(
|
||||||
|
AphrontFormView $form,
|
||||||
|
PhabricatorSavedQuery $saved_query) {}
|
||||||
|
|
||||||
|
protected function getURI($path) {
|
||||||
|
return '/almanac/device/'.$path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBuiltinQueryNames() {
|
||||||
|
$names = array(
|
||||||
|
'all' => pht('All Devices'),
|
||||||
|
);
|
||||||
|
|
||||||
|
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 getRequiredHandlePHIDsForResultList(
|
||||||
|
array $devices,
|
||||||
|
PhabricatorSavedQuery $query) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function renderResultList(
|
||||||
|
array $devices,
|
||||||
|
PhabricatorSavedQuery $query,
|
||||||
|
array $handles) {
|
||||||
|
assert_instances_of($devices, 'AlmanacDevice');
|
||||||
|
|
||||||
|
$viewer = $this->requireViewer();
|
||||||
|
|
||||||
|
$list = new PHUIObjectItemListView();
|
||||||
|
$list->setUser($viewer);
|
||||||
|
foreach ($devices as $device) {
|
||||||
|
$item = id(new PHUIObjectItemView())
|
||||||
|
->setObjectName(pht('Device %d', $device->getID()))
|
||||||
|
->setHeader($device->getName())
|
||||||
|
->setHref($device->getURI())
|
||||||
|
->setObject($device);
|
||||||
|
|
||||||
|
$list->addItem($item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class AlmanacDeviceTransactionQuery
|
||||||
|
extends PhabricatorApplicationTransactionQuery {
|
||||||
|
|
||||||
|
public function getTemplateApplicationTransaction() {
|
||||||
|
return new AlmanacDeviceTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -5,12 +5,32 @@ final class AlmanacDevice
|
||||||
implements PhabricatorPolicyInterface {
|
implements PhabricatorPolicyInterface {
|
||||||
|
|
||||||
protected $name;
|
protected $name;
|
||||||
|
protected $nameIndex;
|
||||||
|
protected $mailKey;
|
||||||
|
protected $viewPolicy;
|
||||||
|
protected $editPolicy;
|
||||||
|
|
||||||
|
public static function initializeNewDevice() {
|
||||||
|
return id(new AlmanacDevice())
|
||||||
|
->setViewPolicy(PhabricatorPolicies::POLICY_USER)
|
||||||
|
->setEditPolicy(PhabricatorPolicies::POLICY_ADMIN);
|
||||||
|
}
|
||||||
|
|
||||||
public function getConfiguration() {
|
public function getConfiguration() {
|
||||||
return array(
|
return array(
|
||||||
self::CONFIG_AUX_PHID => true,
|
self::CONFIG_AUX_PHID => true,
|
||||||
self::CONFIG_COLUMN_SCHEMA => array(
|
self::CONFIG_COLUMN_SCHEMA => array(
|
||||||
'name' => 'text255',
|
'name' => 'text128',
|
||||||
|
'nameIndex' => 'bytes12',
|
||||||
|
),
|
||||||
|
self::CONFIG_KEY_SCHEMA => array(
|
||||||
|
'key_name' => array(
|
||||||
|
'columns' => array('nameIndex'),
|
||||||
|
'unique' => true,
|
||||||
|
),
|
||||||
|
'key_nametext' => array(
|
||||||
|
'columns' => array('name'),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
) + parent::getConfiguration();
|
) + parent::getConfiguration();
|
||||||
}
|
}
|
||||||
|
@ -19,6 +39,22 @@ final class AlmanacDevice
|
||||||
return PhabricatorPHID::generateNewPHID(AlmanacDevicePHIDType::TYPECONST);
|
return PhabricatorPHID::generateNewPHID(AlmanacDevicePHIDType::TYPECONST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function save() {
|
||||||
|
AlmanacNames::validateServiceOrDeviceName($this->getName());
|
||||||
|
|
||||||
|
$this->nameIndex = PhabricatorHash::digestForIndex($this->getName());
|
||||||
|
|
||||||
|
if (!$this->mailKey) {
|
||||||
|
$this->mailKey = Filesystem::readRandomCharacters(20);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getURI() {
|
||||||
|
return '/almanac/device/view/'.$this->getName().'/';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||||
|
|
||||||
|
@ -26,16 +62,16 @@ final class AlmanacDevice
|
||||||
public function getCapabilities() {
|
public function getCapabilities() {
|
||||||
return array(
|
return array(
|
||||||
PhabricatorPolicyCapability::CAN_VIEW,
|
PhabricatorPolicyCapability::CAN_VIEW,
|
||||||
|
PhabricatorPolicyCapability::CAN_EDIT,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPolicy($capability) {
|
public function getPolicy($capability) {
|
||||||
switch ($capability) {
|
switch ($capability) {
|
||||||
case PhabricatorPolicyCapability::CAN_VIEW:
|
case PhabricatorPolicyCapability::CAN_VIEW:
|
||||||
// Until we get a clearer idea on what's going to be stored in this
|
return $this->getViewPolicy();
|
||||||
// table, don't allow anyone (other than the omnipotent user) to find
|
case PhabricatorPolicyCapability::CAN_EDIT:
|
||||||
// these objects.
|
return $this->getEditPolicy();
|
||||||
return PhabricatorPolicies::POLICY_NOONE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class AlmanacDeviceTransaction
|
||||||
|
extends PhabricatorApplicationTransaction {
|
||||||
|
|
||||||
|
const TYPE_NAME = 'almanac:device:name';
|
||||||
|
|
||||||
|
public function getApplicationName() {
|
||||||
|
return 'almanac';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getApplicationTransactionType() {
|
||||||
|
return AlmanacDevicePHIDType::TYPECONST;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getApplicationTransactionCommentObject() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTitle() {
|
||||||
|
$author_phid = $this->getAuthorPHID();
|
||||||
|
|
||||||
|
$old = $this->getOldValue();
|
||||||
|
$new = $this->getNewValue();
|
||||||
|
|
||||||
|
switch ($this->getTransactionType()) {
|
||||||
|
case self::TYPE_NAME:
|
||||||
|
if ($old === null) {
|
||||||
|
return pht(
|
||||||
|
'%s created this device.',
|
||||||
|
$this->renderHandleLink($author_phid));
|
||||||
|
} else {
|
||||||
|
return pht(
|
||||||
|
'%s renamed this device from "%s" to "%s".',
|
||||||
|
$this->renderHandleLink($author_phid),
|
||||||
|
$old,
|
||||||
|
$new);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::getTitle();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -41,7 +41,8 @@ final class AlmanacService
|
||||||
}
|
}
|
||||||
|
|
||||||
public function save() {
|
public function save() {
|
||||||
self::validateServiceName($this->getName());
|
AlmanacNames::validateServiceOrDeviceName($this->getName());
|
||||||
|
|
||||||
$this->nameIndex = PhabricatorHash::digestForIndex($this->getName());
|
$this->nameIndex = PhabricatorHash::digestForIndex($this->getName());
|
||||||
|
|
||||||
if (!$this->mailKey) {
|
if (!$this->mailKey) {
|
||||||
|
@ -55,53 +56,6 @@ final class AlmanacService
|
||||||
return '/almanac/service/view/'.$this->getName().'/';
|
return '/almanac/service/view/'.$this->getName().'/';
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function validateServiceName($name) {
|
|
||||||
if (strlen($name) < 3) {
|
|
||||||
throw new Exception(
|
|
||||||
pht('Almanac service names must be at least 3 characters long.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!preg_match('/^[a-z0-9.-]+\z/', $name)) {
|
|
||||||
throw new Exception(
|
|
||||||
pht(
|
|
||||||
'Almanac service names may only contain lowercase letters, numbers, '.
|
|
||||||
'hyphens, and periods.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (preg_match('/(^|\\.)\d+(\z|\\.)/', $name)) {
|
|
||||||
throw new Exception(
|
|
||||||
pht(
|
|
||||||
'Almanac service names may not have any segments containing only '.
|
|
||||||
'digits.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (preg_match('/\.\./', $name)) {
|
|
||||||
throw new Exception(
|
|
||||||
pht(
|
|
||||||
'Almanac service names may not contain multiple consecutive '.
|
|
||||||
'periods.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (preg_match('/\\.-|-\\./', $name)) {
|
|
||||||
throw new Exception(
|
|
||||||
pht(
|
|
||||||
'Amanac service names may not contain hyphens adjacent to periods.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (preg_match('/--/', $name)) {
|
|
||||||
throw new Exception(
|
|
||||||
pht(
|
|
||||||
'Almanac service names may not contain multiple consecutive '.
|
|
||||||
'hyphens.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!preg_match('/^[a-z0-9].*[a-z0-9]\z/', $name)) {
|
|
||||||
throw new Exception(
|
|
||||||
pht(
|
|
||||||
'Almanac service names must begin and end with a letter or number.'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
|
56
src/applications/almanac/util/AlmanacNames.php
Normal file
56
src/applications/almanac/util/AlmanacNames.php
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class AlmanacNames extends Phobject {
|
||||||
|
|
||||||
|
public static function validateServiceOrDeviceName($name) {
|
||||||
|
if (strlen($name) < 3) {
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'Almanac service and device names must be at least 3 '.
|
||||||
|
'characters long.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!preg_match('/^[a-z0-9.-]+\z/', $name)) {
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'Almanac service and device names may only contain lowercase '.
|
||||||
|
'letters, numbers, hyphens, and periods.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (preg_match('/(^|\\.)\d+(\z|\\.)/', $name)) {
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'Almanac service and device names may not have any segments '.
|
||||||
|
'containing only digits.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (preg_match('/\.\./', $name)) {
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'Almanac service and device names may not contain multiple '.
|
||||||
|
'consecutive periods.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (preg_match('/\\.-|-\\./', $name)) {
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'Amanac service and device names may not contain hyphens adjacent '.
|
||||||
|
'to periods.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (preg_match('/--/', $name)) {
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'Almanac service and device names may not contain multiple '.
|
||||||
|
'consecutive hyphens.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!preg_match('/^[a-z0-9].*[a-z0-9]\z/', $name)) {
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'Almanac service and device names must begin and end with a letter '.
|
||||||
|
'or number.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
final class AlmanacServiceTestCase extends PhabricatorTestCase {
|
final class AlmanacNamesTestCase extends PhabricatorTestCase {
|
||||||
|
|
||||||
public function testServiceNames() {
|
public function testServiceOrDeviceNames() {
|
||||||
$map = array(
|
$map = array(
|
||||||
'' => false,
|
'' => false,
|
||||||
'a' => false,
|
'a' => false,
|
||||||
|
@ -38,7 +38,7 @@ final class AlmanacServiceTestCase extends PhabricatorTestCase {
|
||||||
foreach ($map as $input => $expect) {
|
foreach ($map as $input => $expect) {
|
||||||
$caught = null;
|
$caught = null;
|
||||||
try {
|
try {
|
||||||
AlmanacService::validateServiceName($input);
|
AlmanacNames::validateServiceOrDeviceName($input);
|
||||||
} catch (Exception $ex) {
|
} catch (Exception $ex) {
|
||||||
$caught = $ex;
|
$caught = $ex;
|
||||||
}
|
}
|
Loading…
Reference in a new issue