1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-18 04:42:40 +01:00

Store Almanac "service types" instead of "service classes"

Summary:
Ref T10449. Currently, we store classes (like "AlmanacClusterRepositoryServiceType") in the database.

Instead, store types (like "cluster.repository").

This is a small change, but types are a little more flexible (they let us freely reanme classes), a little cleaner (fewer magic strings in the codebase), and a little better for API usage (they're more human readable).

Make this minor usability change now, before we unprototype.

Also make services searchable by type.

Also remove old Almanac API endpoints.

Test Plan:
  - Ran migration, verified all data migrated properly.
  - Created, edited, rebound, and changed properties of services.
  - Searched for services by service type.
  - Reviewed available Conduit methods.

Reviewers: chad

Reviewed By: chad

Subscribers: yelirekim

Maniphest Tasks: T10449

Differential Revision: https://secure.phabricator.com/D15346
This commit is contained in:
epriestley 2016-02-25 05:05:36 -08:00
parent 4c97d88aa4
commit 7d4b323da2
23 changed files with 226 additions and 282 deletions

View file

@ -0,0 +1,2 @@
ALTER TABLE {$NAMESPACE}_almanac.almanac_service
CHANGE serviceClass serviceType VARCHAR(64) NOT NULL COLLATE {$COLLATE_TEXT};

View file

@ -0,0 +1,30 @@
<?php
// Previously, Almanac services stored a "serviceClass". Migrate these to
// new "serviceType" values.
$table = new AlmanacService();
$conn_w = $table->establishConnection('w');
foreach (new LiskMigrationIterator($table) as $service) {
$new_type = null;
try {
$old_type = $service->getServiceType();
$object = newv($old_type, array());
$new_type = $object->getServiceTypeConstant();
} catch (Exception $ex) {
continue;
}
if (!$new_type) {
continue;
}
queryfx(
$conn_w,
'UPDATE %T SET serviceType = %s WHERE id = %d',
$table->getTableName(),
$new_type,
$service->getID());
}

View file

@ -25,7 +25,6 @@ phutil_register_library_map(array(
'AlmanacClusterDatabaseServiceType' => 'applications/almanac/servicetype/AlmanacClusterDatabaseServiceType.php', 'AlmanacClusterDatabaseServiceType' => 'applications/almanac/servicetype/AlmanacClusterDatabaseServiceType.php',
'AlmanacClusterRepositoryServiceType' => 'applications/almanac/servicetype/AlmanacClusterRepositoryServiceType.php', 'AlmanacClusterRepositoryServiceType' => 'applications/almanac/servicetype/AlmanacClusterRepositoryServiceType.php',
'AlmanacClusterServiceType' => 'applications/almanac/servicetype/AlmanacClusterServiceType.php', 'AlmanacClusterServiceType' => 'applications/almanac/servicetype/AlmanacClusterServiceType.php',
'AlmanacConduitAPIMethod' => 'applications/almanac/conduit/AlmanacConduitAPIMethod.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', 'AlmanacCreateDevicesCapability' => 'applications/almanac/capability/AlmanacCreateDevicesCapability.php',
@ -101,8 +100,6 @@ phutil_register_library_map(array(
'AlmanacPropertyInterface' => 'applications/almanac/property/AlmanacPropertyInterface.php', 'AlmanacPropertyInterface' => 'applications/almanac/property/AlmanacPropertyInterface.php',
'AlmanacPropertyQuery' => 'applications/almanac/query/AlmanacPropertyQuery.php', 'AlmanacPropertyQuery' => 'applications/almanac/query/AlmanacPropertyQuery.php',
'AlmanacQuery' => 'applications/almanac/query/AlmanacQuery.php', 'AlmanacQuery' => 'applications/almanac/query/AlmanacQuery.php',
'AlmanacQueryDevicesConduitAPIMethod' => 'applications/almanac/conduit/AlmanacQueryDevicesConduitAPIMethod.php',
'AlmanacQueryServicesConduitAPIMethod' => 'applications/almanac/conduit/AlmanacQueryServicesConduitAPIMethod.php',
'AlmanacSchemaSpec' => 'applications/almanac/storage/AlmanacSchemaSpec.php', 'AlmanacSchemaSpec' => 'applications/almanac/storage/AlmanacSchemaSpec.php',
'AlmanacSearchEngineAttachment' => 'applications/almanac/engineextension/AlmanacSearchEngineAttachment.php', 'AlmanacSearchEngineAttachment' => 'applications/almanac/engineextension/AlmanacSearchEngineAttachment.php',
'AlmanacService' => 'applications/almanac/storage/AlmanacService.php', 'AlmanacService' => 'applications/almanac/storage/AlmanacService.php',
@ -120,6 +117,7 @@ phutil_register_library_map(array(
'AlmanacServiceTransaction' => 'applications/almanac/storage/AlmanacServiceTransaction.php', 'AlmanacServiceTransaction' => 'applications/almanac/storage/AlmanacServiceTransaction.php',
'AlmanacServiceTransactionQuery' => 'applications/almanac/query/AlmanacServiceTransactionQuery.php', 'AlmanacServiceTransactionQuery' => 'applications/almanac/query/AlmanacServiceTransactionQuery.php',
'AlmanacServiceType' => 'applications/almanac/servicetype/AlmanacServiceType.php', 'AlmanacServiceType' => 'applications/almanac/servicetype/AlmanacServiceType.php',
'AlmanacServiceTypeDatasource' => 'applications/almanac/typeahead/AlmanacServiceTypeDatasource.php',
'AlmanacServiceTypeTestCase' => 'applications/almanac/servicetype/__tests__/AlmanacServiceTypeTestCase.php', 'AlmanacServiceTypeTestCase' => 'applications/almanac/servicetype/__tests__/AlmanacServiceTypeTestCase.php',
'AlmanacServiceViewController' => 'applications/almanac/controller/AlmanacServiceViewController.php', 'AlmanacServiceViewController' => 'applications/almanac/controller/AlmanacServiceViewController.php',
'AlmanacTransaction' => 'applications/almanac/storage/AlmanacTransaction.php', 'AlmanacTransaction' => 'applications/almanac/storage/AlmanacTransaction.php',
@ -4012,7 +4010,6 @@ phutil_register_library_map(array(
'AlmanacClusterDatabaseServiceType' => 'AlmanacClusterServiceType', 'AlmanacClusterDatabaseServiceType' => 'AlmanacClusterServiceType',
'AlmanacClusterRepositoryServiceType' => 'AlmanacClusterServiceType', 'AlmanacClusterRepositoryServiceType' => 'AlmanacClusterServiceType',
'AlmanacClusterServiceType' => 'AlmanacServiceType', 'AlmanacClusterServiceType' => 'AlmanacServiceType',
'AlmanacConduitAPIMethod' => 'ConduitAPIMethod',
'AlmanacConsoleController' => 'AlmanacController', 'AlmanacConsoleController' => 'AlmanacController',
'AlmanacController' => 'PhabricatorController', 'AlmanacController' => 'PhabricatorController',
'AlmanacCreateDevicesCapability' => 'PhabricatorPolicyCapability', 'AlmanacCreateDevicesCapability' => 'PhabricatorPolicyCapability',
@ -4120,8 +4117,6 @@ phutil_register_library_map(array(
'AlmanacPropertyEditEngine' => 'PhabricatorEditEngine', 'AlmanacPropertyEditEngine' => 'PhabricatorEditEngine',
'AlmanacPropertyQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'AlmanacPropertyQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'AlmanacQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'AlmanacQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'AlmanacQueryDevicesConduitAPIMethod' => 'AlmanacConduitAPIMethod',
'AlmanacQueryServicesConduitAPIMethod' => 'AlmanacConduitAPIMethod',
'AlmanacSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'AlmanacSchemaSpec' => 'PhabricatorConfigSchemaSpec',
'AlmanacSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment', 'AlmanacSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment',
'AlmanacService' => array( 'AlmanacService' => array(
@ -4149,6 +4144,7 @@ phutil_register_library_map(array(
'AlmanacServiceTransaction' => 'AlmanacTransaction', 'AlmanacServiceTransaction' => 'AlmanacTransaction',
'AlmanacServiceTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'AlmanacServiceTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'AlmanacServiceType' => 'Phobject', 'AlmanacServiceType' => 'Phobject',
'AlmanacServiceTypeDatasource' => 'PhabricatorTypeaheadDatasource',
'AlmanacServiceTypeTestCase' => 'PhabricatorTestCase', 'AlmanacServiceTypeTestCase' => 'PhabricatorTestCase',
'AlmanacServiceViewController' => 'AlmanacServiceController', 'AlmanacServiceViewController' => 'AlmanacServiceController',
'AlmanacTransaction' => 'PhabricatorApplicationTransaction', 'AlmanacTransaction' => 'PhabricatorApplicationTransaction',

View file

@ -1,73 +0,0 @@
<?php
abstract class AlmanacConduitAPIMethod extends ConduitAPIMethod {
final public function getApplication() {
return PhabricatorApplication::getByClass(
'PhabricatorAlmanacApplication');
}
public function getMethodStatus() {
return self::METHOD_STATUS_DEPRECATED;
}
public function getMethodStatusDescription() {
return pht(
'Almanac is a prototype application and its APIs are '.
'subject to change.');
}
protected function getServiceDictionary(AlmanacService $service) {
return array(
'id' => (int)$service->getID(),
'phid' => $service->getPHID(),
'name' => $service->getName(),
'uri' => PhabricatorEnv::getProductionURI($service->getURI()),
'serviceClass' => $service->getServiceClass(),
'properties' => $this->getPropertiesDictionary($service),
);
}
protected function getBindingDictionary(AlmanacBinding $binding) {
return array(
'id' => (int)$binding->getID(),
'phid' => $binding->getPHID(),
'properties' => $this->getPropertiesDictionary($binding),
'interface' => $this->getInterfaceDictionary($binding->getInterface()),
);
}
protected function getPropertiesDictionary(AlmanacPropertyInterface $obj) {
$properties = $obj->getAlmanacProperties();
return (object)mpull($properties, 'getFieldValue', 'getFieldName');
}
protected function getInterfaceDictionary(AlmanacInterface $interface) {
return array(
'id' => (int)$interface->getID(),
'phid' => $interface->getPHID(),
'address' => $interface->getAddress(),
'port' => (int)$interface->getPort(),
'device' => $this->getDeviceDictionary($interface->getDevice()),
'network' => $this->getNetworkDictionary($interface->getNetwork()),
);
}
protected function getDeviceDictionary(AlmanacDevice $device) {
return array(
'id' => (int)$device->getID(),
'phid' => $device->getPHID(),
'name' => $device->getName(),
'properties' => $this->getPropertiesDictionary($device),
);
}
protected function getNetworkDictionary(AlmanacNetwork $network) {
return array(
'id' => (int)$network->getID(),
'phid' => $network->getPHID(),
'name' => $network->getName(),
);
}
}

View file

@ -1,63 +0,0 @@
<?php
final class AlmanacQueryDevicesConduitAPIMethod
extends AlmanacConduitAPIMethod {
public function getAPIMethodName() {
return 'almanac.querydevices';
}
public function getMethodDescription() {
return pht('Query Almanac devices.');
}
protected function defineParamTypes() {
return array(
'ids' => 'optional list<id>',
'phids' => 'optional list<phid>',
'names' => 'optional list<phid>',
) + self::getPagerParamTypes();
}
protected function defineReturnType() {
return 'list<wild>';
}
protected function execute(ConduitAPIRequest $request) {
$viewer = $request->getUser();
$query = id(new AlmanacDeviceQuery())
->setViewer($viewer);
$ids = $request->getValue('ids');
if ($ids !== null) {
$query->withIDs($ids);
}
$phids = $request->getValue('phids');
if ($phids !== null) {
$query->withPHIDs($phids);
}
$names = $request->getValue('names');
if ($names !== null) {
$query->withNames($names);
}
$pager = $this->newPager($request);
$devices = $query->executeWithCursorPager($pager);
$data = array();
foreach ($devices as $device) {
$data[] = $this->getDeviceDictionary($device);
}
$results = array(
'data' => $data,
);
return $this->addPagerResults($results, $pager);
}
}

View file

@ -1,86 +0,0 @@
<?php
final class AlmanacQueryServicesConduitAPIMethod
extends AlmanacConduitAPIMethod {
public function getAPIMethodName() {
return 'almanac.queryservices';
}
public function getMethodDescription() {
return pht('Query Almanac services.');
}
protected function defineParamTypes() {
return array(
'ids' => 'optional list<id>',
'phids' => 'optional list<phid>',
'names' => 'optional list<phid>',
'devicePHIDs' => 'optional list<phid>',
'serviceClasses' => 'optional list<string>',
) + self::getPagerParamTypes();
}
protected function defineReturnType() {
return 'list<wild>';
}
protected function execute(ConduitAPIRequest $request) {
$viewer = $request->getUser();
$query = id(new AlmanacServiceQuery())
->setViewer($viewer)
->needBindings(true);
$ids = $request->getValue('ids');
if ($ids !== null) {
$query->withIDs($ids);
}
$phids = $request->getValue('phids');
if ($phids !== null) {
$query->withPHIDs($phids);
}
$names = $request->getValue('names');
if ($names !== null) {
$query->withNames($names);
}
$classes = $request->getValue('serviceClasses');
if ($classes !== null) {
$query->withServiceClasses($classes);
}
$device_phids = $request->getValue('devicePHIDs');
if ($device_phids !== null) {
$query->withDevicePHIDs($device_phids);
}
$pager = $this->newPager($request);
$services = $query->executeWithCursorPager($pager);
$data = array();
foreach ($services as $service) {
$phid = $service->getPHID();
$service_bindings = $service->getBindings();
$service_bindings = array_values($service_bindings);
foreach ($service_bindings as $key => $service_binding) {
$service_bindings[$key] = $this->getBindingDictionary($service_binding);
}
$data[] = $this->getServiceDictionary($service) + array(
'bindings' => $service_bindings,
);
}
$results = array(
'data' => $data,
);
return $this->addPagerResults($results, $pager);
}
}

View file

@ -34,21 +34,19 @@ final class AlmanacServiceEditController
$this->requireApplicationCapability( $this->requireApplicationCapability(
AlmanacCreateServicesCapability::CAPABILITY); AlmanacCreateServicesCapability::CAPABILITY);
$service_class = $request->getStr('serviceClass'); $service_type = $request->getStr('serviceType');
$service_types = AlmanacServiceType::getAllServiceTypes();
if (empty($service_types[$service_class])) { try {
return $this->buildServiceTypeResponse($service_types, $cancel_uri); $service = AlmanacService::initializeNewService($service_type);
} catch (Exception $ex) {
return $this->buildServiceTypeResponse($cancel_uri);
} }
$service_type = $service_types[$service_class]; if ($service->isClusterService()) {
if ($service_type->isClusterServiceType()) {
$this->requireApplicationCapability( $this->requireApplicationCapability(
AlmanacManageClusterServicesCapability::CAPABILITY); AlmanacManageClusterServicesCapability::CAPABILITY);
} }
$service = AlmanacService::initializeNewService();
$service->setServiceClass($service_class);
$service->attachServiceType($service_type);
$is_new = true; $is_new = true;
$title = pht('Create Service'); $title = pht('Create Service');
@ -125,7 +123,7 @@ final class AlmanacServiceEditController
$form = id(new AphrontFormView()) $form = id(new AphrontFormView())
->setUser($viewer) ->setUser($viewer)
->addHiddenInput('edit', true) ->addHiddenInput('edit', true)
->addHiddenInput('serviceClass', $service->getServiceClass()) ->addHiddenInput('serviceType', $service->getServiceType())
->appendChild( ->appendChild(
id(new AphrontFormTextControl()) id(new AphrontFormTextControl())
->setLabel(pht('Name')) ->setLabel(pht('Name'))
@ -177,7 +175,9 @@ final class AlmanacServiceEditController
)); ));
} }
private function buildServiceTypeResponse(array $service_types, $cancel_uri) { private function buildServiceTypeResponse($cancel_uri) {
$service_types = AlmanacServiceType::getAllServiceTypes();
$request = $this->getRequest(); $request = $this->getRequest();
$viewer = $this->getViewer(); $viewer = $this->getViewer();
@ -197,7 +197,7 @@ final class AlmanacServiceEditController
$type_control = id(new AphrontFormRadioButtonControl()) $type_control = id(new AphrontFormRadioButtonControl())
->setLabel(pht('Service Type')) ->setLabel(pht('Service Type'))
->setName('serviceClass') ->setName('serviceType')
->setError($e_service); ->setError($e_service);
foreach ($service_types as $service_type) { foreach ($service_types as $service_type) {
@ -211,7 +211,7 @@ final class AlmanacServiceEditController
} }
$type_control->addButton( $type_control->addButton(
get_class($service_type), $service_type->getServiceTypeConstant(),
$service_type->getServiceTypeName(), $service_type->getServiceTypeName(),
array( array(
$service_type->getServiceTypeDescription(), $service_type->getServiceTypeDescription(),

View file

@ -76,7 +76,7 @@ final class AlmanacServiceViewController
$properties->addProperty( $properties->addProperty(
pht('Service Type'), pht('Service Type'),
$service->getServiceType()->getServiceTypeShortName()); $service->getServiceImplementation()->getServiceTypeShortName());
return $properties; return $properties;
} }

View file

@ -6,7 +6,7 @@ final class AlmanacServiceQuery
private $ids; private $ids;
private $phids; private $phids;
private $names; private $names;
private $serviceClasses; private $serviceTypes;
private $devicePHIDs; private $devicePHIDs;
private $namePrefix; private $namePrefix;
private $nameSuffix; private $nameSuffix;
@ -28,8 +28,8 @@ final class AlmanacServiceQuery
return $this; return $this;
} }
public function withServiceClasses(array $classes) { public function withServiceTypes(array $types) {
$this->serviceClasses = $classes; $this->serviceTypes = $types;
return $this; return $this;
} }
@ -109,11 +109,11 @@ final class AlmanacServiceQuery
$hashes); $hashes);
} }
if ($this->serviceClasses !== null) { if ($this->serviceTypes !== null) {
$where[] = qsprintf( $where[] = qsprintf(
$conn, $conn,
'service.serviceClass IN (%Ls)', 'service.serviceType IN (%Ls)',
$this->serviceClasses); $this->serviceTypes);
} }
if ($this->devicePHIDs !== null) { if ($this->devicePHIDs !== null) {
@ -141,17 +141,19 @@ final class AlmanacServiceQuery
} }
protected function willFilterPage(array $services) { protected function willFilterPage(array $services) {
$service_types = AlmanacServiceType::getAllServiceTypes(); $service_map = AlmanacServiceType::getAllServiceTypes();
foreach ($services as $key => $service) { foreach ($services as $key => $service) {
$service_class = $service->getServiceClass(); $implementation = idx($service_map, $service->getServiceType());
$service_type = idx($service_types, $service_class);
if (!$service_type) { if (!$implementation) {
$this->didRejectResult($service); $this->didRejectResult($service);
unset($services[$key]); unset($services[$key]);
continue; continue;
} }
$service->attachServiceType($service_type);
$implementation = clone $implementation;
$service->attachServiceImplementation($implementation);
} }
return $services; return $services;

View file

@ -16,7 +16,7 @@ final class AlmanacServiceSearchEngine
} }
public function newResultObject() { public function newResultObject() {
return AlmanacService::initializeNewService(); return new AlmanacService();
} }
protected function buildQueryFromParameters(array $map) { protected function buildQueryFromParameters(array $map) {
@ -34,6 +34,10 @@ final class AlmanacServiceSearchEngine
$query->withDevicePHIDs($map['devicePHIDs']); $query->withDevicePHIDs($map['devicePHIDs']);
} }
if ($map['serviceTypes']) {
$query->withServiceTypes($map['serviceTypes']);
}
return $query; return $query;
} }
@ -48,6 +52,11 @@ final class AlmanacServiceSearchEngine
->setLabel(pht('Exact Names')) ->setLabel(pht('Exact Names'))
->setKey('names') ->setKey('names')
->setDescription(pht('Search for services with specific names.')), ->setDescription(pht('Search for services with specific names.')),
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Service Types'))
->setKey('serviceTypes')
->setDescription(pht('Find services by type.'))
->setDatasource(id(new AlmanacServiceTypeDatasource())),
id(new PhabricatorPHIDsSearchField()) id(new PhabricatorPHIDsSearchField())
->setLabel(pht('Devices')) ->setLabel(pht('Devices'))
->setKey('devicePHIDs') ->setKey('devicePHIDs')
@ -98,8 +107,8 @@ final class AlmanacServiceSearchEngine
->setHref($service->getURI()) ->setHref($service->getURI())
->setObject($service) ->setObject($service)
->addIcon( ->addIcon(
$service->getServiceType()->getServiceTypeIcon(), $service->getServiceImplementation()->getServiceTypeIcon(),
$service->getServiceType()->getServiceTypeShortName()); $service->getServiceImplementation()->getServiceTypeShortName());
$list->addItem($item); $list->addItem($item);
} }

View file

@ -3,6 +3,8 @@
final class AlmanacClusterDatabaseServiceType final class AlmanacClusterDatabaseServiceType
extends AlmanacClusterServiceType { extends AlmanacClusterServiceType {
const SERVICETYPE = 'cluster.database';
public function getServiceTypeShortName() { public function getServiceTypeShortName() {
return pht('Cluster Database'); return pht('Cluster Database');
} }

View file

@ -3,6 +3,8 @@
final class AlmanacClusterRepositoryServiceType final class AlmanacClusterRepositoryServiceType
extends AlmanacClusterServiceType { extends AlmanacClusterServiceType {
const SERVICETYPE = 'cluster.repository';
public function getServiceTypeShortName() { public function getServiceTypeShortName() {
return pht('Cluster Repository'); return pht('Cluster Repository');
} }

View file

@ -2,6 +2,8 @@
final class AlmanacCustomServiceType extends AlmanacServiceType { final class AlmanacCustomServiceType extends AlmanacServiceType {
const SERVICETYPE = 'almanac.custom';
public function getServiceTypeShortName() { public function getServiceTypeShortName() {
return pht('Custom'); return pht('Custom');
} }

View file

@ -2,6 +2,8 @@
final class AlmanacDrydockPoolServiceType extends AlmanacServiceType { final class AlmanacDrydockPoolServiceType extends AlmanacServiceType {
const SERVICETYPE = 'drydock.pool';
public function getServiceTypeShortName() { public function getServiceTypeShortName() {
return pht('Drydock Pool'); return pht('Drydock Pool');
} }

View file

@ -30,6 +30,11 @@ abstract class AlmanacServiceType extends Phobject {
abstract public function getServiceTypeDescription(); abstract public function getServiceTypeDescription();
final public function getServiceTypeConstant() {
return $this->getPhobjectClassConstant('SERVICETYPE', 64);
}
public function getServiceTypeIcon() { public function getServiceTypeIcon() {
return 'fa-cog'; return 'fa-cog';
} }
@ -38,7 +43,7 @@ abstract class AlmanacServiceType extends Phobject {
* Return `true` if this service type is a Phabricator cluster service type. * Return `true` if this service type is a Phabricator cluster service type.
* *
* These special services change the behavior of Phabricator, and require * These special services change the behavior of Phabricator, and require
* elevated permission to create. * elevated permission to create and edit.
* *
* @return bool True if this is a Phabricator cluster service type. * @return bool True if this is a Phabricator cluster service type.
*/ */
@ -63,6 +68,7 @@ abstract class AlmanacServiceType extends Phobject {
public static function getAllServiceTypes() { public static function getAllServiceTypes() {
return id(new PhutilClassMapQuery()) return id(new PhutilClassMapQuery())
->setAncestorClass(__CLASS__) ->setAncestorClass(__CLASS__)
->setUniqueMethod('getServiceTypeConstant')
->setSortMethod('getServiceTypeName') ->setSortMethod('getServiceTypeName')
->execute(); ->execute();
} }

View file

@ -39,6 +39,46 @@ final class AlmanacProperty
return $this; return $this;
} }
public static function newPropertyUpdateTransactions(
AlmanacPropertyInterface $object,
array $properties,
$only_builtins = false) {
$template = $object->getApplicationTransactionTemplate();
$builtins = $object->getAlmanacPropertyFieldSpecifications();
$xactions = array();
foreach ($properties as $name => $property) {
if ($only_builtins && empty($builtins[$name])) {
continue;
}
$xactions[] = id(clone $template)
->setTransactionType(AlmanacTransaction::TYPE_PROPERTY_UPDATE)
->setMetadataValue('almanac.property', $name)
->setNewValue($property);
}
return $xactions;
}
public static function newPropertyRemoveTransactions(
AlmanacPropertyInterface $object,
array $properties) {
$template = $object->getApplicationTransactionTemplate();
$xactions = array();
foreach ($properties as $property) {
$xactions[] = id(clone $template)
->setTransactionType(AlmanacTransaction::TYPE_PROPERTY_REMOVE)
->setMetadataValue('almanac.property', $property)
->setNewValue(null);
}
return $xactions;
}
public function save() { public function save() {
$hash = PhabricatorHash::digestForIndex($this->getFieldName()); $hash = PhabricatorHash::digestForIndex($this->getFieldName());
$this->setFieldIndex($hash); $this->setFieldIndex($hash);

View file

@ -17,17 +17,29 @@ final class AlmanacService
protected $mailKey; protected $mailKey;
protected $viewPolicy; protected $viewPolicy;
protected $editPolicy; protected $editPolicy;
protected $serviceClass; protected $serviceType;
private $almanacProperties = self::ATTACHABLE; private $almanacProperties = self::ATTACHABLE;
private $bindings = self::ATTACHABLE; private $bindings = self::ATTACHABLE;
private $serviceType = self::ATTACHABLE; private $serviceImplementation = self::ATTACHABLE;
public static function initializeNewService($type) {
$type_map = AlmanacServiceType::getAllServiceTypes();
$implementation = idx($type_map, $type);
if (!$implementation) {
throw new Exception(
pht(
'No Almanac service type "%s" exists!',
$type));
}
public static function initializeNewService() {
return id(new AlmanacService()) return id(new AlmanacService())
->setViewPolicy(PhabricatorPolicies::POLICY_USER) ->setViewPolicy(PhabricatorPolicies::POLICY_USER)
->setEditPolicy(PhabricatorPolicies::POLICY_ADMIN) ->setEditPolicy(PhabricatorPolicies::POLICY_ADMIN)
->attachAlmanacProperties(array()); ->attachAlmanacProperties(array())
->setServiceType($type)
->attachServiceImplementation($implementation);
} }
protected function getConfiguration() { protected function getConfiguration() {
@ -37,7 +49,7 @@ final class AlmanacService
'name' => 'text128', 'name' => 'text128',
'nameIndex' => 'bytes12', 'nameIndex' => 'bytes12',
'mailKey' => 'bytes20', 'mailKey' => 'bytes20',
'serviceClass' => 'text64', 'serviceType' => 'text64',
), ),
self::CONFIG_KEY_SCHEMA => array( self::CONFIG_KEY_SCHEMA => array(
'key_name' => array( 'key_name' => array(
@ -47,8 +59,8 @@ final class AlmanacService
'key_nametext' => array( 'key_nametext' => array(
'columns' => array('name'), 'columns' => array('name'),
), ),
'key_class' => array( 'key_servicetype' => array(
'columns' => array('serviceClass'), 'columns' => array('serviceType'),
), ),
), ),
) + parent::getConfiguration(); ) + parent::getConfiguration();
@ -78,22 +90,35 @@ final class AlmanacService
return $this->assertAttached($this->bindings); return $this->assertAttached($this->bindings);
} }
public function getActiveBindings() {
$bindings = $this->getBindings();
// Filter out disabled bindings.
foreach ($bindings as $key => $binding) {
if ($binding->getIsDisabled()) {
unset($bindings[$key]);
}
}
return $bindings;
}
public function attachBindings(array $bindings) { public function attachBindings(array $bindings) {
$this->bindings = $bindings; $this->bindings = $bindings;
return $this; return $this;
} }
public function getServiceType() { public function getServiceImplementation() {
return $this->assertAttached($this->serviceType); return $this->assertAttached($this->serviceImplementation);
} }
public function attachServiceType(AlmanacServiceType $type) { public function attachServiceImplementation(AlmanacServiceType $type) {
$this->serviceType = $type; $this->serviceImplementation = $type;
return $this; return $this;
} }
public function isClusterService() { public function isClusterService() {
return $this->getServiceType()->isClusterServiceType(); return $this->getServiceImplementation()->isClusterServiceType();
} }
@ -128,7 +153,7 @@ final class AlmanacService
} }
public function getAlmanacPropertyFieldSpecifications() { public function getAlmanacPropertyFieldSpecifications() {
return $this->getServiceType()->getFieldSpecifications(); return $this->getServiceImplementation()->getFieldSpecifications();
} }
public function newAlmanacPropertyEditEngine() { public function newAlmanacPropertyEditEngine() {
@ -246,12 +271,17 @@ final class AlmanacService
->setKey('name') ->setKey('name')
->setType('string') ->setType('string')
->setDescription(pht('The name of the service.')), ->setDescription(pht('The name of the service.')),
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('serviceType')
->setType('string')
->setDescription(pht('The service type constant.')),
); );
} }
public function getFieldValuesForConduit() { public function getFieldValuesForConduit() {
return array( return array(
'name' => $this->getName(), 'name' => $this->getName(),
'serviceType' => $this->getServiceType(),
); );
} }

View file

@ -28,9 +28,9 @@ final class AlmanacServiceDatasource
// selected, or show all services but mark the invalid ones disabled and // selected, or show all services but mark the invalid ones disabled and
// prevent their selection. // prevent their selection.
$service_classes = $this->getParameter('serviceClasses'); $service_types = $this->getParameter('serviceTypes');
if ($service_classes) { if ($service_types) {
$services->withServiceClasses($service_classes); $services->withServiceTypes($service_types);
} }
$services = $this->executeQuery($services); $services = $this->executeQuery($services);

View file

@ -0,0 +1,43 @@
<?php
final class AlmanacServiceTypeDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Service Types');
}
public function getPlaceholderText() {
return pht('Type a service type name...');
}
public function getDatasourceApplicationClass() {
return 'PhabricatorAlmanacApplication';
}
public function loadResults() {
$results = $this->buildResults();
return $this->filterResultsAgainstTokens($results);
}
protected function renderSpecialTokens(array $values) {
return $this->renderTokensFromResults($this->buildResults(), $values);
}
private function buildResults() {
$results = array();
$types = AlmanacServiceType::getAllServiceTypes();
$results = array();
foreach ($types as $key => $type) {
$results[$key] = id(new PhabricatorTypeaheadResult())
->setName($type->getServiceTypeName())
->setIcon($type->getServiceTypeIcon())
->setPHID($key);
}
return $results;
}
}

View file

@ -10,9 +10,9 @@ final class PhabricatorRepositoriesSetupCheck extends PhabricatorSetupCheck {
$cluster_services = id(new AlmanacServiceQuery()) $cluster_services = id(new AlmanacServiceQuery())
->setViewer(PhabricatorUser::getOmnipotentUser()) ->setViewer(PhabricatorUser::getOmnipotentUser())
->withServiceClasses( ->withServiceTypes(
array( array(
'AlmanacClusterRepositoryServiceType', AlmanacClusterRepositoryServiceType::SERVICETYPE,
)) ))
->setLimit(1) ->setLimit(1)
->execute(); ->execute();

View file

@ -47,9 +47,9 @@ final class DiffusionRepositoryCreateController
// allocations, we fail. // allocations, we fail.
$services = id(new AlmanacServiceQuery()) $services = id(new AlmanacServiceQuery())
->setViewer(PhabricatorUser::getOmnipotentUser()) ->setViewer(PhabricatorUser::getOmnipotentUser())
->withServiceClasses( ->withServiceTypes(
array( array(
'AlmanacClusterRepositoryServiceType', AlmanacClusterRepositoryServiceType::SERVICETYPE,
)) ))
->needProperties(true) ->needProperties(true)
->execute(); ->execute();

View file

@ -184,7 +184,7 @@ final class DrydockAlmanacServiceHostBlueprintImplementation
'type' => 'datasource', 'type' => 'datasource',
'datasource.class' => 'AlmanacServiceDatasource', 'datasource.class' => 'AlmanacServiceDatasource',
'datasource.parameters' => array( 'datasource.parameters' => array(
'serviceClasses' => $this->getAlmanacServiceClasses(), 'serviceTypes' => $this->getAlmanacServiceTypes(),
), ),
'required' => true, 'required' => true,
), ),
@ -213,7 +213,7 @@ final class DrydockAlmanacServiceHostBlueprintImplementation
$services = id(new AlmanacServiceQuery()) $services = id(new AlmanacServiceQuery())
->setViewer($viewer) ->setViewer($viewer)
->withPHIDs($service_phids) ->withPHIDs($service_phids)
->withServiceClasses($this->getAlmanacServiceClasses()) ->withServiceTypes($this->getAlmanacServiceTypes())
->needBindings(true) ->needBindings(true)
->execute(); ->execute();
$services = mpull($services, null, 'getPHID'); $services = mpull($services, null, 'getPHID');
@ -283,9 +283,9 @@ final class DrydockAlmanacServiceHostBlueprintImplementation
return $this->freeBindings; return $this->freeBindings;
} }
private function getAlmanacServiceClasses() { private function getAlmanacServiceTypes() {
return array( return array(
'AlmanacDrydockPoolServiceType', AlmanacDrydockPoolServiceType::SERVICETYPE,
); );
} }

View file

@ -2047,7 +2047,7 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO
'be loaded.')); 'be loaded.'));
} }
$service_type = $service->getServiceType(); $service_type = $service->getServiceImplementation();
if (!($service_type instanceof AlmanacClusterRepositoryServiceType)) { if (!($service_type instanceof AlmanacClusterRepositoryServiceType)) {
throw new Exception( throw new Exception(
pht( pht(