2014-10-17 14:01:57 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
final class AlmanacService
|
|
|
|
extends AlmanacDAO
|
Give Almanac generic, custom-field-based properties
Summary:
Ref T5833. Currently, we have an `AlmanacDeviceProperty`, but it doesn't use CustomFields and is specific to devices. Make this more generic:
- Reuse most of the CustomField infrastructure (so we can eventually get easy support for nice editor UIs, etc).
- Make properties more generic so Services, Bindings and Devices can all have them.
The major difference between this implementation and existing CustomField implementations is that all other implementations are application-authoritative: the application code determines what the available list of fields is.
I want Almanac to be a bit more freeform (basically: you can write whatever properties you want, and we'll put nice UIs on them if we have a nice UI available). For example, we might have some sort of "ServiceTemplate" that says "a database binding should usually have the fields 'writable', 'active', 'credential'", which would do things like offer these as options and put a nice UI on them, but you should also be able to write whatever other properties you want and add services without building a specific service template for them.
This involves a little bit of rule bending, but ends up pretty clean. We can adjust CustomField to accommodate this a bit more gracefully later on if it makes sense.
Test Plan: {F229172}
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T5833
Differential Revision: https://secure.phabricator.com/D10777
2014-11-06 00:27:16 +01:00
|
|
|
implements
|
|
|
|
PhabricatorPolicyInterface,
|
|
|
|
PhabricatorCustomFieldInterface,
|
|
|
|
PhabricatorApplicationTransactionInterface,
|
2014-11-06 00:30:00 +01:00
|
|
|
PhabricatorProjectInterface,
|
2014-12-22 21:50:44 +01:00
|
|
|
AlmanacPropertyInterface,
|
|
|
|
PhabricatorDestructibleInterface {
|
2014-10-17 14:01:57 +02:00
|
|
|
|
|
|
|
protected $name;
|
|
|
|
protected $nameIndex;
|
|
|
|
protected $mailKey;
|
|
|
|
protected $viewPolicy;
|
|
|
|
protected $editPolicy;
|
2014-12-17 20:10:27 +01:00
|
|
|
protected $serviceClass;
|
2014-12-18 23:31:36 +01:00
|
|
|
protected $isLocked;
|
2014-10-17 14:01:57 +02:00
|
|
|
|
Give Almanac generic, custom-field-based properties
Summary:
Ref T5833. Currently, we have an `AlmanacDeviceProperty`, but it doesn't use CustomFields and is specific to devices. Make this more generic:
- Reuse most of the CustomField infrastructure (so we can eventually get easy support for nice editor UIs, etc).
- Make properties more generic so Services, Bindings and Devices can all have them.
The major difference between this implementation and existing CustomField implementations is that all other implementations are application-authoritative: the application code determines what the available list of fields is.
I want Almanac to be a bit more freeform (basically: you can write whatever properties you want, and we'll put nice UIs on them if we have a nice UI available). For example, we might have some sort of "ServiceTemplate" that says "a database binding should usually have the fields 'writable', 'active', 'credential'", which would do things like offer these as options and put a nice UI on them, but you should also be able to write whatever other properties you want and add services without building a specific service template for them.
This involves a little bit of rule bending, but ends up pretty clean. We can adjust CustomField to accommodate this a bit more gracefully later on if it makes sense.
Test Plan: {F229172}
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T5833
Differential Revision: https://secure.phabricator.com/D10777
2014-11-06 00:27:16 +01:00
|
|
|
private $customFields = self::ATTACHABLE;
|
|
|
|
private $almanacProperties = self::ATTACHABLE;
|
2014-12-12 21:07:11 +01:00
|
|
|
private $bindings = self::ATTACHABLE;
|
2014-12-17 20:10:27 +01:00
|
|
|
private $serviceType = self::ATTACHABLE;
|
Give Almanac generic, custom-field-based properties
Summary:
Ref T5833. Currently, we have an `AlmanacDeviceProperty`, but it doesn't use CustomFields and is specific to devices. Make this more generic:
- Reuse most of the CustomField infrastructure (so we can eventually get easy support for nice editor UIs, etc).
- Make properties more generic so Services, Bindings and Devices can all have them.
The major difference between this implementation and existing CustomField implementations is that all other implementations are application-authoritative: the application code determines what the available list of fields is.
I want Almanac to be a bit more freeform (basically: you can write whatever properties you want, and we'll put nice UIs on them if we have a nice UI available). For example, we might have some sort of "ServiceTemplate" that says "a database binding should usually have the fields 'writable', 'active', 'credential'", which would do things like offer these as options and put a nice UI on them, but you should also be able to write whatever other properties you want and add services without building a specific service template for them.
This involves a little bit of rule bending, but ends up pretty clean. We can adjust CustomField to accommodate this a bit more gracefully later on if it makes sense.
Test Plan: {F229172}
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T5833
Differential Revision: https://secure.phabricator.com/D10777
2014-11-06 00:27:16 +01:00
|
|
|
|
2014-10-17 14:01:57 +02:00
|
|
|
public static function initializeNewService() {
|
|
|
|
return id(new AlmanacService())
|
|
|
|
->setViewPolicy(PhabricatorPolicies::POLICY_USER)
|
2014-11-16 22:54:11 +01:00
|
|
|
->setEditPolicy(PhabricatorPolicies::POLICY_ADMIN)
|
2014-12-18 23:31:36 +01:00
|
|
|
->attachAlmanacProperties(array())
|
|
|
|
->setIsLocked(0);
|
2014-10-17 14:01:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public function getConfiguration() {
|
|
|
|
return array(
|
|
|
|
self::CONFIG_AUX_PHID => true,
|
|
|
|
self::CONFIG_COLUMN_SCHEMA => array(
|
|
|
|
'name' => 'text128',
|
|
|
|
'nameIndex' => 'bytes12',
|
|
|
|
'mailKey' => 'bytes20',
|
2014-12-17 20:10:27 +01:00
|
|
|
'serviceClass' => 'text64',
|
2014-12-18 23:31:36 +01:00
|
|
|
'isLocked' => 'bool',
|
2014-10-17 14:01:57 +02:00
|
|
|
),
|
|
|
|
self::CONFIG_KEY_SCHEMA => array(
|
|
|
|
'key_name' => array(
|
|
|
|
'columns' => array('nameIndex'),
|
|
|
|
'unique' => true,
|
|
|
|
),
|
|
|
|
'key_nametext' => array(
|
|
|
|
'columns' => array('name'),
|
|
|
|
),
|
2014-12-17 20:10:27 +01:00
|
|
|
'key_class' => array(
|
|
|
|
'columns' => array('serviceClass'),
|
|
|
|
),
|
2014-10-17 14:01:57 +02:00
|
|
|
),
|
|
|
|
) + parent::getConfiguration();
|
|
|
|
}
|
|
|
|
|
|
|
|
public function generatePHID() {
|
|
|
|
return PhabricatorPHID::generateNewPHID(AlmanacServicePHIDType::TYPECONST);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function save() {
|
2014-10-17 14:02:14 +02:00
|
|
|
AlmanacNames::validateServiceOrDeviceName($this->getName());
|
|
|
|
|
2014-10-17 14:01:57 +02:00
|
|
|
$this->nameIndex = PhabricatorHash::digestForIndex($this->getName());
|
|
|
|
|
|
|
|
if (!$this->mailKey) {
|
|
|
|
$this->mailKey = Filesystem::readRandomCharacters(20);
|
|
|
|
}
|
|
|
|
|
|
|
|
return parent::save();
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getURI() {
|
|
|
|
return '/almanac/service/view/'.$this->getName().'/';
|
|
|
|
}
|
|
|
|
|
2014-12-12 21:07:11 +01:00
|
|
|
public function getBindings() {
|
|
|
|
return $this->assertAttached($this->bindings);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function attachBindings(array $bindings) {
|
|
|
|
$this->bindings = $bindings;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2014-12-17 20:10:27 +01:00
|
|
|
public function getServiceType() {
|
|
|
|
return $this->assertAttached($this->serviceType);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function attachServiceType(AlmanacServiceType $type) {
|
|
|
|
$this->serviceType = $type;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
Give Almanac generic, custom-field-based properties
Summary:
Ref T5833. Currently, we have an `AlmanacDeviceProperty`, but it doesn't use CustomFields and is specific to devices. Make this more generic:
- Reuse most of the CustomField infrastructure (so we can eventually get easy support for nice editor UIs, etc).
- Make properties more generic so Services, Bindings and Devices can all have them.
The major difference between this implementation and existing CustomField implementations is that all other implementations are application-authoritative: the application code determines what the available list of fields is.
I want Almanac to be a bit more freeform (basically: you can write whatever properties you want, and we'll put nice UIs on them if we have a nice UI available). For example, we might have some sort of "ServiceTemplate" that says "a database binding should usually have the fields 'writable', 'active', 'credential'", which would do things like offer these as options and put a nice UI on them, but you should also be able to write whatever other properties you want and add services without building a specific service template for them.
This involves a little bit of rule bending, but ends up pretty clean. We can adjust CustomField to accommodate this a bit more gracefully later on if it makes sense.
Test Plan: {F229172}
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T5833
Differential Revision: https://secure.phabricator.com/D10777
2014-11-06 00:27:16 +01:00
|
|
|
|
|
|
|
/* -( AlmanacPropertyInterface )------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
|
|
public function attachAlmanacProperties(array $properties) {
|
|
|
|
assert_instances_of($properties, 'AlmanacProperty');
|
|
|
|
$this->almanacProperties = mpull($properties, null, 'getFieldName');
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getAlmanacProperties() {
|
|
|
|
return $this->assertAttached($this->almanacProperties);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function hasAlmanacProperty($key) {
|
|
|
|
$this->assertAttached($this->almanacProperties);
|
|
|
|
return isset($this->almanacProperties[$key]);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getAlmanacProperty($key) {
|
|
|
|
return $this->assertAttachedKey($this->almanacProperties, $key);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getAlmanacPropertyValue($key, $default = null) {
|
|
|
|
if ($this->hasAlmanacProperty($key)) {
|
|
|
|
return $this->getAlmanacProperty($key)->getFieldValue();
|
|
|
|
} else {
|
|
|
|
return $default;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-17 20:10:50 +01:00
|
|
|
public function getAlmanacPropertyFieldSpecifications() {
|
|
|
|
return $this->getServiceType()->getFieldSpecifications();
|
|
|
|
}
|
|
|
|
|
Give Almanac generic, custom-field-based properties
Summary:
Ref T5833. Currently, we have an `AlmanacDeviceProperty`, but it doesn't use CustomFields and is specific to devices. Make this more generic:
- Reuse most of the CustomField infrastructure (so we can eventually get easy support for nice editor UIs, etc).
- Make properties more generic so Services, Bindings and Devices can all have them.
The major difference between this implementation and existing CustomField implementations is that all other implementations are application-authoritative: the application code determines what the available list of fields is.
I want Almanac to be a bit more freeform (basically: you can write whatever properties you want, and we'll put nice UIs on them if we have a nice UI available). For example, we might have some sort of "ServiceTemplate" that says "a database binding should usually have the fields 'writable', 'active', 'credential'", which would do things like offer these as options and put a nice UI on them, but you should also be able to write whatever other properties you want and add services without building a specific service template for them.
This involves a little bit of rule bending, but ends up pretty clean. We can adjust CustomField to accommodate this a bit more gracefully later on if it makes sense.
Test Plan: {F229172}
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T5833
Differential Revision: https://secure.phabricator.com/D10777
2014-11-06 00:27:16 +01:00
|
|
|
|
2014-10-17 14:01:57 +02:00
|
|
|
/* -( 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:
|
2014-12-18 23:31:36 +01:00
|
|
|
if ($this->getIsLocked()) {
|
|
|
|
return PhabricatorPolicies::POLICY_NOONE;
|
|
|
|
} else {
|
|
|
|
return $this->getEditPolicy();
|
|
|
|
}
|
2014-10-17 14:01:57 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function describeAutomaticCapability($capability) {
|
2014-12-18 23:31:36 +01:00
|
|
|
switch ($capability) {
|
|
|
|
case PhabricatorPolicyCapability::CAN_EDIT:
|
|
|
|
if ($this->getIsLocked()) {
|
|
|
|
return pht('This service is locked and can not be edited.');
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-10-17 14:01:57 +02:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
Give Almanac generic, custom-field-based properties
Summary:
Ref T5833. Currently, we have an `AlmanacDeviceProperty`, but it doesn't use CustomFields and is specific to devices. Make this more generic:
- Reuse most of the CustomField infrastructure (so we can eventually get easy support for nice editor UIs, etc).
- Make properties more generic so Services, Bindings and Devices can all have them.
The major difference between this implementation and existing CustomField implementations is that all other implementations are application-authoritative: the application code determines what the available list of fields is.
I want Almanac to be a bit more freeform (basically: you can write whatever properties you want, and we'll put nice UIs on them if we have a nice UI available). For example, we might have some sort of "ServiceTemplate" that says "a database binding should usually have the fields 'writable', 'active', 'credential'", which would do things like offer these as options and put a nice UI on them, but you should also be able to write whatever other properties you want and add services without building a specific service template for them.
This involves a little bit of rule bending, but ends up pretty clean. We can adjust CustomField to accommodate this a bit more gracefully later on if it makes sense.
Test Plan: {F229172}
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T5833
Differential Revision: https://secure.phabricator.com/D10777
2014-11-06 00:27:16 +01:00
|
|
|
|
|
|
|
/* -( PhabricatorCustomFieldInterface )------------------------------------ */
|
|
|
|
|
|
|
|
|
|
|
|
public function getCustomFieldSpecificationForRole($role) {
|
|
|
|
return array();
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getCustomFieldBaseClass() {
|
|
|
|
return 'AlmanacCustomField';
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getCustomFields() {
|
|
|
|
return $this->assertAttached($this->customFields);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function attachCustomFields(PhabricatorCustomFieldAttachment $fields) {
|
|
|
|
$this->customFields = $fields;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
|
|
|
|
|
|
|
|
|
|
|
|
public function getApplicationTransactionEditor() {
|
|
|
|
return new AlmanacServiceEditor();
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getApplicationTransactionObject() {
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getApplicationTransactionTemplate() {
|
|
|
|
return new AlmanacServiceTransaction();
|
|
|
|
}
|
|
|
|
|
2014-12-04 22:58:52 +01:00
|
|
|
public function willRenderTimeline(
|
|
|
|
PhabricatorApplicationTransactionView $timeline,
|
|
|
|
AphrontRequest $request) {
|
|
|
|
|
|
|
|
return $timeline;
|
|
|
|
}
|
|
|
|
|
2014-12-22 21:50:44 +01:00
|
|
|
|
|
|
|
/* -( PhabricatorDestructibleInterface )----------------------------------- */
|
|
|
|
|
|
|
|
|
|
|
|
public function destroyObjectPermanently(
|
|
|
|
PhabricatorDestructionEngine $engine) {
|
|
|
|
|
|
|
|
$bindings = id(new AlmanacBindingQuery())
|
|
|
|
->setViewer(PhabricatorUser::getOmnipotentUser())
|
|
|
|
->withServicePHIDs(array($this->getPHID()))
|
|
|
|
->execute();
|
|
|
|
foreach ($bindings as $binding) {
|
|
|
|
$engine->destroyObject($binding);
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->delete();
|
|
|
|
}
|
|
|
|
|
2014-10-17 14:01:57 +02:00
|
|
|
}
|