mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-29 02:02:41 +01:00
(stable) Promote 2016 Week 9
This commit is contained in:
commit
9d051cddd3
178 changed files with 4373 additions and 2469 deletions
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
return array(
|
||||
'names' => array(
|
||||
'core.pkg.css' => '7935f211',
|
||||
'core.pkg.css' => 'ecdca229',
|
||||
'core.pkg.js' => '7d8faf57',
|
||||
'darkconsole.pkg.js' => 'e7393ebb',
|
||||
'differential.pkg.css' => '2de124c9',
|
||||
|
@ -35,7 +35,7 @@ return array(
|
|||
'rsrc/css/application/base/main-menu-view.css' => 'd00a795a',
|
||||
'rsrc/css/application/base/notification-menu.css' => 'f31c0bde',
|
||||
'rsrc/css/application/base/phabricator-application-launch-view.css' => '95351601',
|
||||
'rsrc/css/application/base/phui-theme.css' => 'ab7b848c',
|
||||
'rsrc/css/application/base/phui-theme.css' => '027ba77e',
|
||||
'rsrc/css/application/base/standard-page-view.css' => 'e709f6d0',
|
||||
'rsrc/css/application/chatlog/chatlog.css' => 'd295b020',
|
||||
'rsrc/css/application/conduit/conduit-api.css' => '7bc725c4',
|
||||
|
@ -81,7 +81,7 @@ return array(
|
|||
'rsrc/css/application/owners/owners-path-editor.css' => '2f00933b',
|
||||
'rsrc/css/application/paste/paste.css' => 'a5157c48',
|
||||
'rsrc/css/application/people/people-profile.css' => '2473d929',
|
||||
'rsrc/css/application/phame/phame.css' => '4ca6fd6c',
|
||||
'rsrc/css/application/phame/phame.css' => '737792d6',
|
||||
'rsrc/css/application/pholio/pholio-edit.css' => '3ad9d1ee',
|
||||
'rsrc/css/application/pholio/pholio-inline-comments.css' => '8e545e49',
|
||||
'rsrc/css/application/pholio/pholio.css' => 'ca89d380',
|
||||
|
@ -92,9 +92,9 @@ return array(
|
|||
'rsrc/css/application/policy/policy-edit.css' => '815c66f7',
|
||||
'rsrc/css/application/policy/policy-transaction-detail.css' => '82100a43',
|
||||
'rsrc/css/application/policy/policy.css' => '957ea14c',
|
||||
'rsrc/css/application/ponder/ponder-view.css' => 'b40dc156',
|
||||
'rsrc/css/application/ponder/ponder-view.css' => '212495e0',
|
||||
'rsrc/css/application/project/project-card-view.css' => '9418c97d',
|
||||
'rsrc/css/application/project/project-view.css' => '83bb6654',
|
||||
'rsrc/css/application/project/project-view.css' => '298b7c5b',
|
||||
'rsrc/css/application/releeph/releeph-core.css' => '9b3c5733',
|
||||
'rsrc/css/application/releeph/releeph-preview-branch.css' => 'b7a6f4a5',
|
||||
'rsrc/css/application/releeph/releeph-request-differential-create-dialog.css' => '8d8b92cd',
|
||||
|
@ -127,14 +127,14 @@ return array(
|
|||
'rsrc/css/phui/phui-button.css' => 'edf464e9',
|
||||
'rsrc/css/phui/phui-chart.css' => '6bf6f78e',
|
||||
'rsrc/css/phui/phui-crumbs-view.css' => '79d536e5',
|
||||
'rsrc/css/phui/phui-document-pro.css' => 'a8872307',
|
||||
'rsrc/css/phui/phui-document-pro.css' => '92d5b648',
|
||||
'rsrc/css/phui/phui-document-summary.css' => '9ca48bdf',
|
||||
'rsrc/css/phui/phui-document.css' => '9c71d2bf',
|
||||
'rsrc/css/phui/phui-feed-story.css' => '04aec08f',
|
||||
'rsrc/css/phui/phui-fontkit.css' => '9cda225e',
|
||||
'rsrc/css/phui/phui-form-view.css' => '4a1a0f5e',
|
||||
'rsrc/css/phui/phui-form.css' => 'aac1d51d',
|
||||
'rsrc/css/phui/phui-header-view.css' => '50c5cb6a',
|
||||
'rsrc/css/phui/phui-header-view.css' => 'a6d7b20d',
|
||||
'rsrc/css/phui/phui-hovercard.css' => 'de1a2119',
|
||||
'rsrc/css/phui/phui-icon-set-selector.css' => '1ab67aad',
|
||||
'rsrc/css/phui/phui-icon.css' => '3f33ab57',
|
||||
|
@ -154,7 +154,7 @@ return array(
|
|||
'rsrc/css/phui/phui-status.css' => '888cedb8',
|
||||
'rsrc/css/phui/phui-tag-view.css' => '9d5d4400',
|
||||
'rsrc/css/phui/phui-timeline-view.css' => '2efceff8',
|
||||
'rsrc/css/phui/phui-two-column-view.css' => '0763177e',
|
||||
'rsrc/css/phui/phui-two-column-view.css' => 'a317616a',
|
||||
'rsrc/css/phui/workboards/phui-workboard-color.css' => 'ac6fe6a7',
|
||||
'rsrc/css/phui/workboards/phui-workboard.css' => 'e6d89647',
|
||||
'rsrc/css/phui/workboards/phui-workcard.css' => '3646fb96',
|
||||
|
@ -790,7 +790,7 @@ return array(
|
|||
'phabricator-uiexample-reactor-sendclass' => '1def2711',
|
||||
'phabricator-uiexample-reactor-sendproperties' => 'b1f0ccee',
|
||||
'phabricator-zindex-css' => '5b6fcf3f',
|
||||
'phame-css' => '4ca6fd6c',
|
||||
'phame-css' => '737792d6',
|
||||
'pholio-css' => 'ca89d380',
|
||||
'pholio-edit-css' => '3ad9d1ee',
|
||||
'pholio-inline-comments-css' => '8e545e49',
|
||||
|
@ -812,13 +812,13 @@ return array(
|
|||
'phui-crumbs-view-css' => '79d536e5',
|
||||
'phui-document-summary-view-css' => '9ca48bdf',
|
||||
'phui-document-view-css' => '9c71d2bf',
|
||||
'phui-document-view-pro-css' => 'a8872307',
|
||||
'phui-document-view-pro-css' => '92d5b648',
|
||||
'phui-feed-story-css' => '04aec08f',
|
||||
'phui-font-icon-base-css' => 'ecbbb4c2',
|
||||
'phui-fontkit-css' => '9cda225e',
|
||||
'phui-form-css' => 'aac1d51d',
|
||||
'phui-form-view-css' => '4a1a0f5e',
|
||||
'phui-header-view-css' => '50c5cb6a',
|
||||
'phui-header-view-css' => 'a6d7b20d',
|
||||
'phui-hovercard' => '1bd28176',
|
||||
'phui-hovercard-view-css' => 'de1a2119',
|
||||
'phui-icon-set-selector-css' => '1ab67aad',
|
||||
|
@ -839,9 +839,9 @@ return array(
|
|||
'phui-spacing-css' => '042804d6',
|
||||
'phui-status-list-view-css' => '888cedb8',
|
||||
'phui-tag-view-css' => '9d5d4400',
|
||||
'phui-theme-css' => 'ab7b848c',
|
||||
'phui-theme-css' => '027ba77e',
|
||||
'phui-timeline-view-css' => '2efceff8',
|
||||
'phui-two-column-view-css' => '0763177e',
|
||||
'phui-two-column-view-css' => 'a317616a',
|
||||
'phui-workboard-color-css' => 'ac6fe6a7',
|
||||
'phui-workboard-view-css' => 'e6d89647',
|
||||
'phui-workcard-view-css' => '3646fb96',
|
||||
|
@ -855,9 +855,9 @@ return array(
|
|||
'policy-css' => '957ea14c',
|
||||
'policy-edit-css' => '815c66f7',
|
||||
'policy-transaction-detail-css' => '82100a43',
|
||||
'ponder-view-css' => 'b40dc156',
|
||||
'ponder-view-css' => '212495e0',
|
||||
'project-card-view-css' => '9418c97d',
|
||||
'project-view-css' => '83bb6654',
|
||||
'project-view-css' => '298b7c5b',
|
||||
'releeph-core' => '9b3c5733',
|
||||
'releeph-preview-branch' => 'b7a6f4a5',
|
||||
'releeph-request-differential-create-dialog' => '8d8b92cd',
|
||||
|
|
7
resources/sql/autopatches/20160221.almanac.1.devicen.sql
Normal file
7
resources/sql/autopatches/20160221.almanac.1.devicen.sql
Normal file
|
@ -0,0 +1,7 @@
|
|||
CREATE TABLE {$NAMESPACE}_almanac.almanac_devicename_ngrams (
|
||||
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
objectID INT UNSIGNED NOT NULL,
|
||||
ngram CHAR(3) NOT NULL COLLATE {$COLLATE_TEXT},
|
||||
KEY `key_object` (objectID),
|
||||
KEY `key_ngram` (ngram, objectID)
|
||||
) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
|
11
resources/sql/autopatches/20160221.almanac.2.devicei.php
Normal file
11
resources/sql/autopatches/20160221.almanac.2.devicei.php
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
$table = new AlmanacDevice();
|
||||
|
||||
foreach (new LiskMigrationIterator($table) as $device) {
|
||||
PhabricatorSearchWorker::queueDocumentForIndexing(
|
||||
$device->getPHID(),
|
||||
array(
|
||||
'force' => true,
|
||||
));
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
CREATE TABLE {$NAMESPACE}_almanac.almanac_servicename_ngrams (
|
||||
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
objectID INT UNSIGNED NOT NULL,
|
||||
ngram CHAR(3) NOT NULL COLLATE {$COLLATE_TEXT},
|
||||
KEY `key_object` (objectID),
|
||||
KEY `key_ngram` (ngram, objectID)
|
||||
) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
|
11
resources/sql/autopatches/20160221.almanac.4.servicei.php
Normal file
11
resources/sql/autopatches/20160221.almanac.4.servicei.php
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
$table = new AlmanacService();
|
||||
|
||||
foreach (new LiskMigrationIterator($table) as $service) {
|
||||
PhabricatorSearchWorker::queueDocumentForIndexing(
|
||||
$service->getPHID(),
|
||||
array(
|
||||
'force' => true,
|
||||
));
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
CREATE TABLE {$NAMESPACE}_almanac.almanac_networkname_ngrams (
|
||||
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
objectID INT UNSIGNED NOT NULL,
|
||||
ngram CHAR(3) NOT NULL COLLATE {$COLLATE_TEXT},
|
||||
KEY `key_object` (objectID),
|
||||
KEY `key_ngram` (ngram, objectID)
|
||||
) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
|
11
resources/sql/autopatches/20160221.almanac.6.networki.php
Normal file
11
resources/sql/autopatches/20160221.almanac.6.networki.php
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
$table = new AlmanacNetwork();
|
||||
|
||||
foreach (new LiskMigrationIterator($table) as $network) {
|
||||
PhabricatorSearchWorker::queueDocumentForIndexing(
|
||||
$network->getPHID(),
|
||||
array(
|
||||
'force' => true,
|
||||
));
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
CREATE TABLE {$NAMESPACE}_almanac.almanac_namespacename_ngrams (
|
||||
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
objectID INT UNSIGNED NOT NULL,
|
||||
ngram CHAR(3) NOT NULL COLLATE {$COLLATE_TEXT},
|
||||
KEY `key_object` (objectID),
|
||||
KEY `key_ngram` (ngram, objectID)
|
||||
) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
|
14
resources/sql/autopatches/20160221.almanac.8.namespace.sql
Normal file
14
resources/sql/autopatches/20160221.almanac.8.namespace.sql
Normal file
|
@ -0,0 +1,14 @@
|
|||
CREATE TABLE {$NAMESPACE}_almanac.almanac_namespace (
|
||||
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
phid VARBINARY(64) NOT NULL,
|
||||
name VARCHAR(128) NOT NULL COLLATE {$COLLATE_TEXT},
|
||||
nameIndex BINARY(12) NOT NULL,
|
||||
mailKey BINARY(20) NOT NULL,
|
||||
viewPolicy VARBINARY(64) NOT NULL,
|
||||
editPolicy VARBINARY(64) NOT NULL,
|
||||
dateCreated INT UNSIGNED NOT NULL,
|
||||
dateModified INT UNSIGNED NOT NULL,
|
||||
UNIQUE KEY `key_phid` (phid),
|
||||
UNIQUE KEY `key_nameindex` (nameIndex),
|
||||
KEY `key_name` (name)
|
||||
) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
|
19
resources/sql/autopatches/20160221.almanac.9.namespacex.sql
Normal file
19
resources/sql/autopatches/20160221.almanac.9.namespacex.sql
Normal file
|
@ -0,0 +1,19 @@
|
|||
CREATE TABLE {$NAMESPACE}_almanac.almanac_namespacetransaction (
|
||||
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
phid VARBINARY(64) NOT NULL,
|
||||
authorPHID VARBINARY(64) NOT NULL,
|
||||
objectPHID VARBINARY(64) NOT NULL,
|
||||
viewPolicy VARBINARY(64) NOT NULL,
|
||||
editPolicy VARBINARY(64) NOT NULL,
|
||||
commentPHID VARBINARY(64) DEFAULT NULL,
|
||||
commentVersion INT UNSIGNED NOT NULL,
|
||||
transactionType VARCHAR(32) COLLATE {$COLLATE_TEXT} NOT NULL,
|
||||
oldValue LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
|
||||
newValue LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
|
||||
contentSource LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
|
||||
metadata LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
|
||||
dateCreated INT UNSIGNED NOT NULL,
|
||||
dateModified INT UNSIGNED NOT NULL,
|
||||
UNIQUE KEY `key_phid` (`phid`),
|
||||
KEY `key_object` (`objectPHID`)
|
||||
) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
|
28
resources/sql/autopatches/20160222.almanac.1.properties.php
Normal file
28
resources/sql/autopatches/20160222.almanac.1.properties.php
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
$table = new AlmanacProperty();
|
||||
$conn_w = $table->establishConnection('w');
|
||||
|
||||
// We're going to JSON-encode the value in each row: previously rows stored
|
||||
// plain strings, but now they store JSON, so we need to update them.
|
||||
|
||||
foreach (new LiskMigrationIterator($table) as $property) {
|
||||
$key = $property->getFieldName();
|
||||
|
||||
$current_row = queryfx_one(
|
||||
$conn_w,
|
||||
'SELECT fieldValue FROM %T WHERE id = %d',
|
||||
$table->getTableName(),
|
||||
$property->getID());
|
||||
|
||||
if (!$current_row) {
|
||||
continue;
|
||||
}
|
||||
|
||||
queryfx(
|
||||
$conn_w,
|
||||
'UPDATE %T SET fieldValue = %s WHERE id = %d',
|
||||
$table->getTableName(),
|
||||
phutil_json_encode($current_row['fieldValue']),
|
||||
$property->getID());
|
||||
}
|
2
resources/sql/autopatches/20160223.almanac.1.bound.sql
Normal file
2
resources/sql/autopatches/20160223.almanac.1.bound.sql
Normal file
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE {$NAMESPACE}_almanac.almanac_device
|
||||
ADD isBoundToClusterService BOOL NOT NULL;
|
|
@ -0,0 +1,2 @@
|
|||
UPDATE {$NAMESPACE}_almanac.almanac_device
|
||||
SET isBoundToClusterService = isLocked;
|
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE {$NAMESPACE}_almanac.almanac_device
|
||||
DROP isLocked;
|
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE {$NAMESPACE}_almanac.almanac_service
|
||||
DROP isLocked;
|
21
resources/sql/autopatches/20160223.paste.fileedges.php
Normal file
21
resources/sql/autopatches/20160223.paste.fileedges.php
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
// For a while in November 2015, attachment edges between pastes and their
|
||||
// underlying file data were not written correctly. This restores edges for
|
||||
// any missing pastes.
|
||||
|
||||
$table = new PhabricatorPaste();
|
||||
$edge_type = PhabricatorObjectHasFileEdgeType::EDGECONST;
|
||||
|
||||
foreach (new LiskMigrationIterator($table) as $paste) {
|
||||
$paste_phid = $paste->getPHID();
|
||||
$file_phid = $paste->getFilePHID();
|
||||
|
||||
if (!$file_phid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
id(new PhabricatorEdgeEditor())
|
||||
->addEdge($paste_phid, $edge_type, $file_phid)
|
||||
->save();
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE {$NAMESPACE}_almanac.almanac_binding
|
||||
ADD isDisabled BOOL NOT NULL;
|
2
resources/sql/autopatches/20160225.almanac.2.stype.sql
Normal file
2
resources/sql/autopatches/20160225.almanac.2.stype.sql
Normal file
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE {$NAMESPACE}_almanac.almanac_service
|
||||
CHANGE serviceClass serviceType VARCHAR(64) NOT NULL COLLATE {$COLLATE_TEXT};
|
30
resources/sql/autopatches/20160225.almanac.3.stype.php
Normal file
30
resources/sql/autopatches/20160225.almanac.3.stype.php
Normal 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());
|
||||
}
|
|
@ -11,26 +11,26 @@ phutil_register_library_map(array(
|
|||
'class' => array(
|
||||
'AlmanacAddress' => 'applications/almanac/util/AlmanacAddress.php',
|
||||
'AlmanacBinding' => 'applications/almanac/storage/AlmanacBinding.php',
|
||||
'AlmanacBindingDisableController' => 'applications/almanac/controller/AlmanacBindingDisableController.php',
|
||||
'AlmanacBindingEditController' => 'applications/almanac/controller/AlmanacBindingEditController.php',
|
||||
'AlmanacBindingEditor' => 'applications/almanac/editor/AlmanacBindingEditor.php',
|
||||
'AlmanacBindingPHIDType' => 'applications/almanac/phid/AlmanacBindingPHIDType.php',
|
||||
'AlmanacBindingPropertyEditEngine' => 'applications/almanac/editor/AlmanacBindingPropertyEditEngine.php',
|
||||
'AlmanacBindingQuery' => 'applications/almanac/query/AlmanacBindingQuery.php',
|
||||
'AlmanacBindingTableView' => 'applications/almanac/view/AlmanacBindingTableView.php',
|
||||
'AlmanacBindingTransaction' => 'applications/almanac/storage/AlmanacBindingTransaction.php',
|
||||
'AlmanacBindingTransactionQuery' => 'applications/almanac/query/AlmanacBindingTransactionQuery.php',
|
||||
'AlmanacBindingViewController' => 'applications/almanac/controller/AlmanacBindingViewController.php',
|
||||
'AlmanacBindingsSearchEngineAttachment' => 'applications/almanac/engineextension/AlmanacBindingsSearchEngineAttachment.php',
|
||||
'AlmanacClusterDatabaseServiceType' => 'applications/almanac/servicetype/AlmanacClusterDatabaseServiceType.php',
|
||||
'AlmanacClusterRepositoryServiceType' => 'applications/almanac/servicetype/AlmanacClusterRepositoryServiceType.php',
|
||||
'AlmanacClusterServiceType' => 'applications/almanac/servicetype/AlmanacClusterServiceType.php',
|
||||
'AlmanacConduitAPIMethod' => 'applications/almanac/conduit/AlmanacConduitAPIMethod.php',
|
||||
'AlmanacConsoleController' => 'applications/almanac/controller/AlmanacConsoleController.php',
|
||||
'AlmanacController' => 'applications/almanac/controller/AlmanacController.php',
|
||||
'AlmanacCoreCustomField' => 'applications/almanac/customfield/AlmanacCoreCustomField.php',
|
||||
'AlmanacCreateClusterServicesCapability' => 'applications/almanac/capability/AlmanacCreateClusterServicesCapability.php',
|
||||
'AlmanacCreateDevicesCapability' => 'applications/almanac/capability/AlmanacCreateDevicesCapability.php',
|
||||
'AlmanacCreateNamespacesCapability' => 'applications/almanac/capability/AlmanacCreateNamespacesCapability.php',
|
||||
'AlmanacCreateNetworksCapability' => 'applications/almanac/capability/AlmanacCreateNetworksCapability.php',
|
||||
'AlmanacCreateServicesCapability' => 'applications/almanac/capability/AlmanacCreateServicesCapability.php',
|
||||
'AlmanacCustomField' => 'applications/almanac/customfield/AlmanacCustomField.php',
|
||||
'AlmanacCustomServiceType' => 'applications/almanac/servicetype/AlmanacCustomServiceType.php',
|
||||
'AlmanacDAO' => 'applications/almanac/storage/AlmanacDAO.php',
|
||||
'AlmanacDevice' => 'applications/almanac/storage/AlmanacDevice.php',
|
||||
|
@ -38,33 +38,52 @@ phutil_register_library_map(array(
|
|||
'AlmanacDeviceEditController' => 'applications/almanac/controller/AlmanacDeviceEditController.php',
|
||||
'AlmanacDeviceEditor' => 'applications/almanac/editor/AlmanacDeviceEditor.php',
|
||||
'AlmanacDeviceListController' => 'applications/almanac/controller/AlmanacDeviceListController.php',
|
||||
'AlmanacDeviceNameNgrams' => 'applications/almanac/storage/AlmanacDeviceNameNgrams.php',
|
||||
'AlmanacDevicePHIDType' => 'applications/almanac/phid/AlmanacDevicePHIDType.php',
|
||||
'AlmanacDevicePropertyEditEngine' => 'applications/almanac/editor/AlmanacDevicePropertyEditEngine.php',
|
||||
'AlmanacDeviceQuery' => 'applications/almanac/query/AlmanacDeviceQuery.php',
|
||||
'AlmanacDeviceSearchConduitAPIMethod' => 'applications/almanac/conduit/AlmanacDeviceSearchConduitAPIMethod.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',
|
||||
'AlmanacDrydockPoolServiceType' => 'applications/almanac/servicetype/AlmanacDrydockPoolServiceType.php',
|
||||
'AlmanacEditor' => 'applications/almanac/editor/AlmanacEditor.php',
|
||||
'AlmanacInterface' => 'applications/almanac/storage/AlmanacInterface.php',
|
||||
'AlmanacInterfaceDatasource' => 'applications/almanac/typeahead/AlmanacInterfaceDatasource.php',
|
||||
'AlmanacInterfaceDeleteController' => 'applications/almanac/controller/AlmanacInterfaceDeleteController.php',
|
||||
'AlmanacInterfaceEditController' => 'applications/almanac/controller/AlmanacInterfaceEditController.php',
|
||||
'AlmanacInterfacePHIDType' => 'applications/almanac/phid/AlmanacInterfacePHIDType.php',
|
||||
'AlmanacInterfaceQuery' => 'applications/almanac/query/AlmanacInterfaceQuery.php',
|
||||
'AlmanacInterfaceTableView' => 'applications/almanac/view/AlmanacInterfaceTableView.php',
|
||||
'AlmanacKeys' => 'applications/almanac/util/AlmanacKeys.php',
|
||||
'AlmanacManagementLockWorkflow' => 'applications/almanac/management/AlmanacManagementLockWorkflow.php',
|
||||
'AlmanacManageClusterServicesCapability' => 'applications/almanac/capability/AlmanacManageClusterServicesCapability.php',
|
||||
'AlmanacManagementRegisterWorkflow' => 'applications/almanac/management/AlmanacManagementRegisterWorkflow.php',
|
||||
'AlmanacManagementTrustKeyWorkflow' => 'applications/almanac/management/AlmanacManagementTrustKeyWorkflow.php',
|
||||
'AlmanacManagementUnlockWorkflow' => 'applications/almanac/management/AlmanacManagementUnlockWorkflow.php',
|
||||
'AlmanacManagementUntrustKeyWorkflow' => 'applications/almanac/management/AlmanacManagementUntrustKeyWorkflow.php',
|
||||
'AlmanacManagementWorkflow' => 'applications/almanac/management/AlmanacManagementWorkflow.php',
|
||||
'AlmanacNames' => 'applications/almanac/util/AlmanacNames.php',
|
||||
'AlmanacNamesTestCase' => 'applications/almanac/util/__tests__/AlmanacNamesTestCase.php',
|
||||
'AlmanacNamespace' => 'applications/almanac/storage/AlmanacNamespace.php',
|
||||
'AlmanacNamespaceController' => 'applications/almanac/controller/AlmanacNamespaceController.php',
|
||||
'AlmanacNamespaceEditController' => 'applications/almanac/controller/AlmanacNamespaceEditController.php',
|
||||
'AlmanacNamespaceEditEngine' => 'applications/almanac/editor/AlmanacNamespaceEditEngine.php',
|
||||
'AlmanacNamespaceEditor' => 'applications/almanac/editor/AlmanacNamespaceEditor.php',
|
||||
'AlmanacNamespaceListController' => 'applications/almanac/controller/AlmanacNamespaceListController.php',
|
||||
'AlmanacNamespaceNameNgrams' => 'applications/almanac/storage/AlmanacNamespaceNameNgrams.php',
|
||||
'AlmanacNamespacePHIDType' => 'applications/almanac/phid/AlmanacNamespacePHIDType.php',
|
||||
'AlmanacNamespaceQuery' => 'applications/almanac/query/AlmanacNamespaceQuery.php',
|
||||
'AlmanacNamespaceSearchEngine' => 'applications/almanac/query/AlmanacNamespaceSearchEngine.php',
|
||||
'AlmanacNamespaceTransaction' => 'applications/almanac/storage/AlmanacNamespaceTransaction.php',
|
||||
'AlmanacNamespaceTransactionQuery' => 'applications/almanac/query/AlmanacNamespaceTransactionQuery.php',
|
||||
'AlmanacNamespaceViewController' => 'applications/almanac/controller/AlmanacNamespaceViewController.php',
|
||||
'AlmanacNetwork' => 'applications/almanac/storage/AlmanacNetwork.php',
|
||||
'AlmanacNetworkController' => 'applications/almanac/controller/AlmanacNetworkController.php',
|
||||
'AlmanacNetworkEditController' => 'applications/almanac/controller/AlmanacNetworkEditController.php',
|
||||
'AlmanacNetworkEditEngine' => 'applications/almanac/editor/AlmanacNetworkEditEngine.php',
|
||||
'AlmanacNetworkEditor' => 'applications/almanac/editor/AlmanacNetworkEditor.php',
|
||||
'AlmanacNetworkListController' => 'applications/almanac/controller/AlmanacNetworkListController.php',
|
||||
'AlmanacNetworkNameNgrams' => 'applications/almanac/storage/AlmanacNetworkNameNgrams.php',
|
||||
'AlmanacNetworkPHIDType' => 'applications/almanac/phid/AlmanacNetworkPHIDType.php',
|
||||
'AlmanacNetworkQuery' => 'applications/almanac/query/AlmanacNetworkQuery.php',
|
||||
'AlmanacNetworkSearchEngine' => 'applications/almanac/query/AlmanacNetworkSearchEngine.php',
|
||||
|
@ -72,30 +91,36 @@ phutil_register_library_map(array(
|
|||
'AlmanacNetworkTransactionQuery' => 'applications/almanac/query/AlmanacNetworkTransactionQuery.php',
|
||||
'AlmanacNetworkViewController' => 'applications/almanac/controller/AlmanacNetworkViewController.php',
|
||||
'AlmanacPropertiesDestructionEngineExtension' => 'applications/almanac/engineextension/AlmanacPropertiesDestructionEngineExtension.php',
|
||||
'AlmanacPropertiesSearchEngineAttachment' => 'applications/almanac/engineextension/AlmanacPropertiesSearchEngineAttachment.php',
|
||||
'AlmanacProperty' => 'applications/almanac/storage/AlmanacProperty.php',
|
||||
'AlmanacPropertyController' => 'applications/almanac/controller/AlmanacPropertyController.php',
|
||||
'AlmanacPropertyDeleteController' => 'applications/almanac/controller/AlmanacPropertyDeleteController.php',
|
||||
'AlmanacPropertyEditController' => 'applications/almanac/controller/AlmanacPropertyEditController.php',
|
||||
'AlmanacPropertyEditEngine' => 'applications/almanac/editor/AlmanacPropertyEditEngine.php',
|
||||
'AlmanacPropertyInterface' => 'applications/almanac/property/AlmanacPropertyInterface.php',
|
||||
'AlmanacPropertyQuery' => 'applications/almanac/query/AlmanacPropertyQuery.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',
|
||||
'AlmanacSearchEngineAttachment' => 'applications/almanac/engineextension/AlmanacSearchEngineAttachment.php',
|
||||
'AlmanacService' => 'applications/almanac/storage/AlmanacService.php',
|
||||
'AlmanacServiceController' => 'applications/almanac/controller/AlmanacServiceController.php',
|
||||
'AlmanacServiceDatasource' => 'applications/almanac/typeahead/AlmanacServiceDatasource.php',
|
||||
'AlmanacServiceEditController' => 'applications/almanac/controller/AlmanacServiceEditController.php',
|
||||
'AlmanacServiceEditor' => 'applications/almanac/editor/AlmanacServiceEditor.php',
|
||||
'AlmanacServiceListController' => 'applications/almanac/controller/AlmanacServiceListController.php',
|
||||
'AlmanacServiceNameNgrams' => 'applications/almanac/storage/AlmanacServiceNameNgrams.php',
|
||||
'AlmanacServicePHIDType' => 'applications/almanac/phid/AlmanacServicePHIDType.php',
|
||||
'AlmanacServicePropertyEditEngine' => 'applications/almanac/editor/AlmanacServicePropertyEditEngine.php',
|
||||
'AlmanacServiceQuery' => 'applications/almanac/query/AlmanacServiceQuery.php',
|
||||
'AlmanacServiceSearchConduitAPIMethod' => 'applications/almanac/conduit/AlmanacServiceSearchConduitAPIMethod.php',
|
||||
'AlmanacServiceSearchEngine' => 'applications/almanac/query/AlmanacServiceSearchEngine.php',
|
||||
'AlmanacServiceTransaction' => 'applications/almanac/storage/AlmanacServiceTransaction.php',
|
||||
'AlmanacServiceTransactionQuery' => 'applications/almanac/query/AlmanacServiceTransactionQuery.php',
|
||||
'AlmanacServiceType' => 'applications/almanac/servicetype/AlmanacServiceType.php',
|
||||
'AlmanacServiceTypeDatasource' => 'applications/almanac/typeahead/AlmanacServiceTypeDatasource.php',
|
||||
'AlmanacServiceTypeTestCase' => 'applications/almanac/servicetype/__tests__/AlmanacServiceTypeTestCase.php',
|
||||
'AlmanacServiceViewController' => 'applications/almanac/controller/AlmanacServiceViewController.php',
|
||||
'AlmanacTransaction' => 'applications/almanac/storage/AlmanacTransaction.php',
|
||||
'AphlictDropdownDataQuery' => 'applications/aphlict/query/AphlictDropdownDataQuery.php',
|
||||
'Aphront304Response' => 'aphront/response/Aphront304Response.php',
|
||||
'Aphront400Response' => 'aphront/response/Aphront400Response.php',
|
||||
|
@ -858,6 +883,7 @@ phutil_register_library_map(array(
|
|||
'DrydockBlueprintTransactionQuery' => 'applications/drydock/query/DrydockBlueprintTransactionQuery.php',
|
||||
'DrydockBlueprintViewController' => 'applications/drydock/controller/DrydockBlueprintViewController.php',
|
||||
'DrydockCommand' => 'applications/drydock/storage/DrydockCommand.php',
|
||||
'DrydockCommandError' => 'applications/drydock/DrydockCommandError/DrydockCommandError.php',
|
||||
'DrydockCommandInterface' => 'applications/drydock/interface/command/DrydockCommandInterface.php',
|
||||
'DrydockCommandQuery' => 'applications/drydock/query/DrydockCommandQuery.php',
|
||||
'DrydockConsoleController' => 'applications/drydock/controller/DrydockConsoleController.php',
|
||||
|
@ -1068,7 +1094,6 @@ phutil_register_library_map(array(
|
|||
'HarbormasterBuildableTransactionQuery' => 'applications/harbormaster/query/HarbormasterBuildableTransactionQuery.php',
|
||||
'HarbormasterBuildableViewController' => 'applications/harbormaster/controller/HarbormasterBuildableViewController.php',
|
||||
'HarbormasterBuiltinBuildStepGroup' => 'applications/harbormaster/stepgroup/HarbormasterBuiltinBuildStepGroup.php',
|
||||
'HarbormasterCommandBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterCommandBuildStepImplementation.php',
|
||||
'HarbormasterConduitAPIMethod' => 'applications/harbormaster/conduit/HarbormasterConduitAPIMethod.php',
|
||||
'HarbormasterController' => 'applications/harbormaster/controller/HarbormasterController.php',
|
||||
'HarbormasterCreateArtifactConduitAPIMethod' => 'applications/harbormaster/conduit/HarbormasterCreateArtifactConduitAPIMethod.php',
|
||||
|
@ -1082,7 +1107,6 @@ phutil_register_library_map(array(
|
|||
'HarbormasterFileArtifact' => 'applications/harbormaster/artifact/HarbormasterFileArtifact.php',
|
||||
'HarbormasterHTTPRequestBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterHTTPRequestBuildStepImplementation.php',
|
||||
'HarbormasterHostArtifact' => 'applications/harbormaster/artifact/HarbormasterHostArtifact.php',
|
||||
'HarbormasterLeaseHostBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterLeaseHostBuildStepImplementation.php',
|
||||
'HarbormasterLeaseWorkingCopyBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterLeaseWorkingCopyBuildStepImplementation.php',
|
||||
'HarbormasterLintMessagesController' => 'applications/harbormaster/controller/HarbormasterLintMessagesController.php',
|
||||
'HarbormasterLintPropertyView' => 'applications/harbormaster/view/HarbormasterLintPropertyView.php',
|
||||
|
@ -3783,7 +3807,6 @@ phutil_register_library_map(array(
|
|||
'PonderAnswerCommentController' => 'applications/ponder/controller/PonderAnswerCommentController.php',
|
||||
'PonderAnswerEditController' => 'applications/ponder/controller/PonderAnswerEditController.php',
|
||||
'PonderAnswerEditor' => 'applications/ponder/editor/PonderAnswerEditor.php',
|
||||
'PonderAnswerHasVotingUserEdgeType' => 'applications/ponder/edge/PonderAnswerHasVotingUserEdgeType.php',
|
||||
'PonderAnswerHistoryController' => 'applications/ponder/controller/PonderAnswerHistoryController.php',
|
||||
'PonderAnswerMailReceiver' => 'applications/ponder/mail/PonderAnswerMailReceiver.php',
|
||||
'PonderAnswerPHIDType' => 'applications/ponder/phid/PonderAnswerPHIDType.php',
|
||||
|
@ -3801,7 +3824,6 @@ phutil_register_library_map(array(
|
|||
'PonderDefaultViewCapability' => 'applications/ponder/capability/PonderDefaultViewCapability.php',
|
||||
'PonderEditor' => 'applications/ponder/editor/PonderEditor.php',
|
||||
'PonderFooterView' => 'applications/ponder/view/PonderFooterView.php',
|
||||
'PonderHelpfulSaveController' => 'applications/ponder/controller/PonderHelpfulSaveController.php',
|
||||
'PonderModerateCapability' => 'applications/ponder/capability/PonderModerateCapability.php',
|
||||
'PonderQuestion' => 'applications/ponder/storage/PonderQuestion.php',
|
||||
'PonderQuestionCommentController' => 'applications/ponder/controller/PonderQuestionCommentController.php',
|
||||
|
@ -3823,10 +3845,6 @@ phutil_register_library_map(array(
|
|||
'PonderQuestionViewController' => 'applications/ponder/controller/PonderQuestionViewController.php',
|
||||
'PonderRemarkupRule' => 'applications/ponder/remarkup/PonderRemarkupRule.php',
|
||||
'PonderSchemaSpec' => 'applications/ponder/storage/PonderSchemaSpec.php',
|
||||
'PonderVotableInterface' => 'applications/ponder/storage/PonderVotableInterface.php',
|
||||
'PonderVote' => 'applications/ponder/constants/PonderVote.php',
|
||||
'PonderVoteEditor' => 'applications/ponder/editor/PonderVoteEditor.php',
|
||||
'PonderVotingUserHasAnswerEdgeType' => 'applications/ponder/edge/PonderVotingUserHasAnswerEdgeType.php',
|
||||
'ProjectAddProjectsEmailCommand' => 'applications/project/command/ProjectAddProjectsEmailCommand.php',
|
||||
'ProjectBoardTaskCard' => 'applications/project/view/ProjectBoardTaskCard.php',
|
||||
'ProjectCanLockProjectsCapability' => 'applications/project/capability/ProjectCanLockProjectsCapability.php',
|
||||
|
@ -3972,127 +3990,163 @@ phutil_register_library_map(array(
|
|||
'AlmanacBinding' => array(
|
||||
'AlmanacDAO',
|
||||
'PhabricatorPolicyInterface',
|
||||
'PhabricatorCustomFieldInterface',
|
||||
'PhabricatorApplicationTransactionInterface',
|
||||
'AlmanacPropertyInterface',
|
||||
'PhabricatorDestructibleInterface',
|
||||
'PhabricatorExtendedPolicyInterface',
|
||||
),
|
||||
'AlmanacBindingDisableController' => 'AlmanacServiceController',
|
||||
'AlmanacBindingEditController' => 'AlmanacServiceController',
|
||||
'AlmanacBindingEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||
'AlmanacBindingEditor' => 'AlmanacEditor',
|
||||
'AlmanacBindingPHIDType' => 'PhabricatorPHIDType',
|
||||
'AlmanacBindingPropertyEditEngine' => 'AlmanacPropertyEditEngine',
|
||||
'AlmanacBindingQuery' => 'AlmanacQuery',
|
||||
'AlmanacBindingTableView' => 'AphrontView',
|
||||
'AlmanacBindingTransaction' => 'PhabricatorApplicationTransaction',
|
||||
'AlmanacBindingTransaction' => 'AlmanacTransaction',
|
||||
'AlmanacBindingTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||
'AlmanacBindingViewController' => 'AlmanacServiceController',
|
||||
'AlmanacBindingsSearchEngineAttachment' => 'AlmanacSearchEngineAttachment',
|
||||
'AlmanacClusterDatabaseServiceType' => 'AlmanacClusterServiceType',
|
||||
'AlmanacClusterRepositoryServiceType' => 'AlmanacClusterServiceType',
|
||||
'AlmanacClusterServiceType' => 'AlmanacServiceType',
|
||||
'AlmanacConduitAPIMethod' => 'ConduitAPIMethod',
|
||||
'AlmanacConsoleController' => 'AlmanacController',
|
||||
'AlmanacController' => 'PhabricatorController',
|
||||
'AlmanacCoreCustomField' => array(
|
||||
'AlmanacCustomField',
|
||||
'PhabricatorStandardCustomFieldInterface',
|
||||
),
|
||||
'AlmanacCreateClusterServicesCapability' => 'PhabricatorPolicyCapability',
|
||||
'AlmanacCreateDevicesCapability' => 'PhabricatorPolicyCapability',
|
||||
'AlmanacCreateNamespacesCapability' => 'PhabricatorPolicyCapability',
|
||||
'AlmanacCreateNetworksCapability' => 'PhabricatorPolicyCapability',
|
||||
'AlmanacCreateServicesCapability' => 'PhabricatorPolicyCapability',
|
||||
'AlmanacCustomField' => 'PhabricatorCustomField',
|
||||
'AlmanacCustomServiceType' => 'AlmanacServiceType',
|
||||
'AlmanacDAO' => 'PhabricatorLiskDAO',
|
||||
'AlmanacDevice' => array(
|
||||
'AlmanacDAO',
|
||||
'PhabricatorPolicyInterface',
|
||||
'PhabricatorCustomFieldInterface',
|
||||
'PhabricatorApplicationTransactionInterface',
|
||||
'PhabricatorProjectInterface',
|
||||
'PhabricatorSSHPublicKeyInterface',
|
||||
'AlmanacPropertyInterface',
|
||||
'PhabricatorDestructibleInterface',
|
||||
'PhabricatorNgramsInterface',
|
||||
'PhabricatorConduitResultInterface',
|
||||
'PhabricatorExtendedPolicyInterface',
|
||||
),
|
||||
'AlmanacDeviceController' => 'AlmanacController',
|
||||
'AlmanacDeviceEditController' => 'AlmanacDeviceController',
|
||||
'AlmanacDeviceEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||
'AlmanacDeviceEditor' => 'AlmanacEditor',
|
||||
'AlmanacDeviceListController' => 'AlmanacDeviceController',
|
||||
'AlmanacDeviceNameNgrams' => 'PhabricatorSearchNgrams',
|
||||
'AlmanacDevicePHIDType' => 'PhabricatorPHIDType',
|
||||
'AlmanacDevicePropertyEditEngine' => 'AlmanacPropertyEditEngine',
|
||||
'AlmanacDeviceQuery' => 'AlmanacQuery',
|
||||
'AlmanacDeviceSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod',
|
||||
'AlmanacDeviceSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||
'AlmanacDeviceTransaction' => 'PhabricatorApplicationTransaction',
|
||||
'AlmanacDeviceTransaction' => 'AlmanacTransaction',
|
||||
'AlmanacDeviceTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||
'AlmanacDeviceViewController' => 'AlmanacDeviceController',
|
||||
'AlmanacDrydockPoolServiceType' => 'AlmanacServiceType',
|
||||
'AlmanacEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||
'AlmanacInterface' => array(
|
||||
'AlmanacDAO',
|
||||
'PhabricatorPolicyInterface',
|
||||
'PhabricatorDestructibleInterface',
|
||||
'PhabricatorExtendedPolicyInterface',
|
||||
),
|
||||
'AlmanacInterfaceDatasource' => 'PhabricatorTypeaheadDatasource',
|
||||
'AlmanacInterfaceDeleteController' => 'AlmanacDeviceController',
|
||||
'AlmanacInterfaceEditController' => 'AlmanacDeviceController',
|
||||
'AlmanacInterfacePHIDType' => 'PhabricatorPHIDType',
|
||||
'AlmanacInterfaceQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'AlmanacInterfaceQuery' => 'AlmanacQuery',
|
||||
'AlmanacInterfaceTableView' => 'AphrontView',
|
||||
'AlmanacKeys' => 'Phobject',
|
||||
'AlmanacManagementLockWorkflow' => 'AlmanacManagementWorkflow',
|
||||
'AlmanacManageClusterServicesCapability' => 'PhabricatorPolicyCapability',
|
||||
'AlmanacManagementRegisterWorkflow' => 'AlmanacManagementWorkflow',
|
||||
'AlmanacManagementTrustKeyWorkflow' => 'AlmanacManagementWorkflow',
|
||||
'AlmanacManagementUnlockWorkflow' => 'AlmanacManagementWorkflow',
|
||||
'AlmanacManagementUntrustKeyWorkflow' => 'AlmanacManagementWorkflow',
|
||||
'AlmanacManagementWorkflow' => 'PhabricatorManagementWorkflow',
|
||||
'AlmanacNames' => 'Phobject',
|
||||
'AlmanacNamesTestCase' => 'PhabricatorTestCase',
|
||||
'AlmanacNamespace' => array(
|
||||
'AlmanacDAO',
|
||||
'PhabricatorPolicyInterface',
|
||||
'PhabricatorApplicationTransactionInterface',
|
||||
'PhabricatorProjectInterface',
|
||||
'AlmanacPropertyInterface',
|
||||
'PhabricatorDestructibleInterface',
|
||||
'PhabricatorNgramsInterface',
|
||||
),
|
||||
'AlmanacNamespaceController' => 'AlmanacController',
|
||||
'AlmanacNamespaceEditController' => 'AlmanacNamespaceController',
|
||||
'AlmanacNamespaceEditEngine' => 'PhabricatorEditEngine',
|
||||
'AlmanacNamespaceEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||
'AlmanacNamespaceListController' => 'AlmanacNamespaceController',
|
||||
'AlmanacNamespaceNameNgrams' => 'PhabricatorSearchNgrams',
|
||||
'AlmanacNamespacePHIDType' => 'PhabricatorPHIDType',
|
||||
'AlmanacNamespaceQuery' => 'AlmanacQuery',
|
||||
'AlmanacNamespaceSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||
'AlmanacNamespaceTransaction' => 'PhabricatorApplicationTransaction',
|
||||
'AlmanacNamespaceTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||
'AlmanacNamespaceViewController' => 'AlmanacNamespaceController',
|
||||
'AlmanacNetwork' => array(
|
||||
'AlmanacDAO',
|
||||
'PhabricatorApplicationTransactionInterface',
|
||||
'PhabricatorPolicyInterface',
|
||||
'PhabricatorDestructibleInterface',
|
||||
'PhabricatorNgramsInterface',
|
||||
),
|
||||
'AlmanacNetworkController' => 'AlmanacController',
|
||||
'AlmanacNetworkEditController' => 'AlmanacNetworkController',
|
||||
'AlmanacNetworkEditEngine' => 'PhabricatorEditEngine',
|
||||
'AlmanacNetworkEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||
'AlmanacNetworkListController' => 'AlmanacNetworkController',
|
||||
'AlmanacNetworkNameNgrams' => 'PhabricatorSearchNgrams',
|
||||
'AlmanacNetworkPHIDType' => 'PhabricatorPHIDType',
|
||||
'AlmanacNetworkQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'AlmanacNetworkQuery' => 'AlmanacQuery',
|
||||
'AlmanacNetworkSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||
'AlmanacNetworkTransaction' => 'PhabricatorApplicationTransaction',
|
||||
'AlmanacNetworkTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||
'AlmanacNetworkViewController' => 'AlmanacNetworkController',
|
||||
'AlmanacPropertiesDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension',
|
||||
'AlmanacPropertiesSearchEngineAttachment' => 'AlmanacSearchEngineAttachment',
|
||||
'AlmanacProperty' => array(
|
||||
'PhabricatorCustomFieldStorage',
|
||||
'AlmanacDAO',
|
||||
'PhabricatorPolicyInterface',
|
||||
),
|
||||
'AlmanacPropertyController' => 'AlmanacController',
|
||||
'AlmanacPropertyDeleteController' => 'AlmanacDeviceController',
|
||||
'AlmanacPropertyEditController' => 'AlmanacDeviceController',
|
||||
'AlmanacPropertyDeleteController' => 'AlmanacPropertyController',
|
||||
'AlmanacPropertyEditController' => 'AlmanacPropertyController',
|
||||
'AlmanacPropertyEditEngine' => 'PhabricatorEditEngine',
|
||||
'AlmanacPropertyQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'AlmanacQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'AlmanacQueryDevicesConduitAPIMethod' => 'AlmanacConduitAPIMethod',
|
||||
'AlmanacQueryServicesConduitAPIMethod' => 'AlmanacConduitAPIMethod',
|
||||
'AlmanacSchemaSpec' => 'PhabricatorConfigSchemaSpec',
|
||||
'AlmanacSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment',
|
||||
'AlmanacService' => array(
|
||||
'AlmanacDAO',
|
||||
'PhabricatorPolicyInterface',
|
||||
'PhabricatorCustomFieldInterface',
|
||||
'PhabricatorApplicationTransactionInterface',
|
||||
'PhabricatorProjectInterface',
|
||||
'AlmanacPropertyInterface',
|
||||
'PhabricatorDestructibleInterface',
|
||||
'PhabricatorNgramsInterface',
|
||||
'PhabricatorConduitResultInterface',
|
||||
'PhabricatorExtendedPolicyInterface',
|
||||
),
|
||||
'AlmanacServiceController' => 'AlmanacController',
|
||||
'AlmanacServiceDatasource' => 'PhabricatorTypeaheadDatasource',
|
||||
'AlmanacServiceEditController' => 'AlmanacServiceController',
|
||||
'AlmanacServiceEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||
'AlmanacServiceEditor' => 'AlmanacEditor',
|
||||
'AlmanacServiceListController' => 'AlmanacServiceController',
|
||||
'AlmanacServiceNameNgrams' => 'PhabricatorSearchNgrams',
|
||||
'AlmanacServicePHIDType' => 'PhabricatorPHIDType',
|
||||
'AlmanacServicePropertyEditEngine' => 'AlmanacPropertyEditEngine',
|
||||
'AlmanacServiceQuery' => 'AlmanacQuery',
|
||||
'AlmanacServiceSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod',
|
||||
'AlmanacServiceSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||
'AlmanacServiceTransaction' => 'PhabricatorApplicationTransaction',
|
||||
'AlmanacServiceTransaction' => 'AlmanacTransaction',
|
||||
'AlmanacServiceTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||
'AlmanacServiceType' => 'Phobject',
|
||||
'AlmanacServiceTypeDatasource' => 'PhabricatorTypeaheadDatasource',
|
||||
'AlmanacServiceTypeTestCase' => 'PhabricatorTestCase',
|
||||
'AlmanacServiceViewController' => 'AlmanacServiceController',
|
||||
'AlmanacTransaction' => 'PhabricatorApplicationTransaction',
|
||||
'AphlictDropdownDataQuery' => 'Phobject',
|
||||
'Aphront304Response' => 'AphrontResponse',
|
||||
'Aphront400Response' => 'AphrontResponse',
|
||||
|
@ -5203,7 +5257,6 @@ phutil_register_library_map(array(
|
|||
'HarbormasterBuildableTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||
'HarbormasterBuildableViewController' => 'HarbormasterController',
|
||||
'HarbormasterBuiltinBuildStepGroup' => 'HarbormasterBuildStepGroup',
|
||||
'HarbormasterCommandBuildStepImplementation' => 'HarbormasterBuildStepImplementation',
|
||||
'HarbormasterConduitAPIMethod' => 'ConduitAPIMethod',
|
||||
'HarbormasterController' => 'PhabricatorController',
|
||||
'HarbormasterCreateArtifactConduitAPIMethod' => 'HarbormasterConduitAPIMethod',
|
||||
|
@ -5217,7 +5270,6 @@ phutil_register_library_map(array(
|
|||
'HarbormasterFileArtifact' => 'HarbormasterArtifact',
|
||||
'HarbormasterHTTPRequestBuildStepImplementation' => 'HarbormasterBuildStepImplementation',
|
||||
'HarbormasterHostArtifact' => 'HarbormasterDrydockLeaseArtifact',
|
||||
'HarbormasterLeaseHostBuildStepImplementation' => 'HarbormasterBuildStepImplementation',
|
||||
'HarbormasterLeaseWorkingCopyBuildStepImplementation' => 'HarbormasterBuildStepImplementation',
|
||||
'HarbormasterLintMessagesController' => 'HarbormasterController',
|
||||
'HarbormasterLintPropertyView' => 'AphrontView',
|
||||
|
@ -8418,7 +8470,6 @@ phutil_register_library_map(array(
|
|||
'PonderDAO',
|
||||
'PhabricatorApplicationTransactionInterface',
|
||||
'PhabricatorMarkupInterface',
|
||||
'PonderVotableInterface',
|
||||
'PhabricatorPolicyInterface',
|
||||
'PhabricatorFlaggableInterface',
|
||||
'PhabricatorSubscribableInterface',
|
||||
|
@ -8427,7 +8478,6 @@ phutil_register_library_map(array(
|
|||
'PonderAnswerCommentController' => 'PonderController',
|
||||
'PonderAnswerEditController' => 'PonderController',
|
||||
'PonderAnswerEditor' => 'PonderEditor',
|
||||
'PonderAnswerHasVotingUserEdgeType' => 'PhabricatorEdgeType',
|
||||
'PonderAnswerHistoryController' => 'PonderController',
|
||||
'PonderAnswerMailReceiver' => 'PhabricatorObjectMailReceiver',
|
||||
'PonderAnswerPHIDType' => 'PhabricatorPHIDType',
|
||||
|
@ -8445,7 +8495,6 @@ phutil_register_library_map(array(
|
|||
'PonderDefaultViewCapability' => 'PhabricatorPolicyCapability',
|
||||
'PonderEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||
'PonderFooterView' => 'AphrontTagView',
|
||||
'PonderHelpfulSaveController' => 'PonderController',
|
||||
'PonderModerateCapability' => 'PhabricatorPolicyCapability',
|
||||
'PonderQuestion' => array(
|
||||
'PonderDAO',
|
||||
|
@ -8479,9 +8528,6 @@ phutil_register_library_map(array(
|
|||
'PonderQuestionViewController' => 'PonderController',
|
||||
'PonderRemarkupRule' => 'PhabricatorObjectRemarkupRule',
|
||||
'PonderSchemaSpec' => 'PhabricatorConfigSchemaSpec',
|
||||
'PonderVote' => 'PonderConstants',
|
||||
'PonderVoteEditor' => 'PhabricatorEditor',
|
||||
'PonderVotingUserHasAnswerEdgeType' => 'PhabricatorEdgeType',
|
||||
'ProjectAddProjectsEmailCommand' => 'MetaMTAEmailTransactionCommand',
|
||||
'ProjectBoardTaskCard' => 'Phobject',
|
||||
'ProjectCanLockProjectsCapability' => 'PhabricatorPolicyCapability',
|
||||
|
|
|
@ -29,7 +29,7 @@ final class PhabricatorAlmanacApplication extends PhabricatorApplication {
|
|||
public function getHelpDocumentationArticles(PhabricatorUser $viewer) {
|
||||
return array(
|
||||
array(
|
||||
'name' => pht('Alamanac User Guide'),
|
||||
'name' => pht('Almanac User Guide'),
|
||||
'href' => PhabricatorEnv::getDoclink('Almanac User Guide'),
|
||||
),
|
||||
);
|
||||
|
@ -43,37 +43,56 @@ final class PhabricatorAlmanacApplication extends PhabricatorApplication {
|
|||
return array(
|
||||
'/almanac/' => array(
|
||||
'' => 'AlmanacConsoleController',
|
||||
'service/' => array(
|
||||
'(?:query/(?P<queryKey>[^/]+)/)?' => 'AlmanacServiceListController',
|
||||
'(?P<objectType>service)/' => array(
|
||||
$this->getQueryRoutePattern() => 'AlmanacServiceListController',
|
||||
'edit/(?:(?P<id>\d+)/)?' => 'AlmanacServiceEditController',
|
||||
'view/(?P<name>[^/]+)/' => 'AlmanacServiceViewController',
|
||||
),
|
||||
'device/' => array(
|
||||
'(?:query/(?P<queryKey>[^/]+)/)?' => 'AlmanacDeviceListController',
|
||||
'(?P<objectType>device)/' => array(
|
||||
$this->getQueryRoutePattern() => 'AlmanacDeviceListController',
|
||||
'edit/(?:(?P<id>\d+)/)?' => 'AlmanacDeviceEditController',
|
||||
'view/(?P<name>[^/]+)/' => 'AlmanacDeviceViewController',
|
||||
),
|
||||
'interface/' => array(
|
||||
'edit/(?:(?P<id>\d+)/)?' => 'AlmanacInterfaceEditController',
|
||||
'delete/(?:(?P<id>\d+)/)?' => 'AlmanacInterfaceDeleteController',
|
||||
),
|
||||
'binding/' => array(
|
||||
'edit/(?:(?P<id>\d+)/)?' => 'AlmanacBindingEditController',
|
||||
'disable/(?:(?P<id>\d+)/)?' => 'AlmanacBindingDisableController',
|
||||
'(?P<id>\d+)/' => 'AlmanacBindingViewController',
|
||||
),
|
||||
'network/' => array(
|
||||
'(?:query/(?P<queryKey>[^/]+)/)?' => 'AlmanacNetworkListController',
|
||||
$this->getQueryRoutePattern() => 'AlmanacNetworkListController',
|
||||
'edit/(?:(?P<id>\d+)/)?' => 'AlmanacNetworkEditController',
|
||||
'(?P<id>\d+)/' => 'AlmanacNetworkViewController',
|
||||
),
|
||||
'namespace/' => array(
|
||||
$this->getQueryRoutePattern() => 'AlmanacNamespaceListController',
|
||||
$this->getEditRoutePattern('edit/')
|
||||
=> 'AlmanacNamespaceEditController',
|
||||
'(?P<id>\d+)/' => 'AlmanacNamespaceViewController',
|
||||
),
|
||||
'property/' => array(
|
||||
'edit/' => 'AlmanacPropertyEditController',
|
||||
'delete/' => 'AlmanacPropertyDeleteController',
|
||||
'update/' => 'AlmanacPropertyEditController',
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
protected function getCustomCapabilities() {
|
||||
$cluster_caption = pht(
|
||||
'This permission is very dangerous. %s',
|
||||
phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => PhabricatorEnv::getDoclink(
|
||||
'User Guide: Phabricator Clusters'),
|
||||
'target' => '_blank',
|
||||
),
|
||||
pht('Learn More')));
|
||||
|
||||
return array(
|
||||
AlmanacCreateServicesCapability::CAPABILITY => array(
|
||||
'default' => PhabricatorPolicies::POLICY_ADMIN,
|
||||
|
@ -84,9 +103,13 @@ final class PhabricatorAlmanacApplication extends PhabricatorApplication {
|
|||
AlmanacCreateNetworksCapability::CAPABILITY => array(
|
||||
'default' => PhabricatorPolicies::POLICY_ADMIN,
|
||||
),
|
||||
AlmanacCreateClusterServicesCapability::CAPABILITY => array(
|
||||
AlmanacCreateNamespacesCapability::CAPABILITY => array(
|
||||
'default' => PhabricatorPolicies::POLICY_ADMIN,
|
||||
),
|
||||
AlmanacManageClusterServicesCapability::CAPABILITY => array(
|
||||
'default' => PhabricatorPolicies::POLICY_NOONE,
|
||||
'caption' => $cluster_caption,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacCreateNamespacesCapability
|
||||
extends PhabricatorPolicyCapability {
|
||||
|
||||
const CAPABILITY = 'almanac.namespaces';
|
||||
|
||||
public function getCapabilityName() {
|
||||
return pht('Can Create Namespaces');
|
||||
}
|
||||
|
||||
public function describeCapabilityRejection() {
|
||||
return pht('You do not have permission to create Almanac namespaces.');
|
||||
}
|
||||
|
||||
}
|
|
@ -1,17 +1,17 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacCreateClusterServicesCapability
|
||||
final class AlmanacManageClusterServicesCapability
|
||||
extends PhabricatorPolicyCapability {
|
||||
|
||||
const CAPABILITY = 'almanac.cluster';
|
||||
|
||||
public function getCapabilityName() {
|
||||
return pht('Can Create Cluster Services');
|
||||
return pht('Can Manage Cluster Services');
|
||||
}
|
||||
|
||||
public function describeCapabilityRejection() {
|
||||
return pht(
|
||||
'You do not have permission to create Almanac cluster services.');
|
||||
'You do not have permission to manage Almanac cluster services.');
|
||||
}
|
||||
|
||||
}
|
|
@ -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_UNSTABLE;
|
||||
}
|
||||
|
||||
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(),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacDeviceSearchConduitAPIMethod
|
||||
extends PhabricatorSearchEngineAPIMethod {
|
||||
|
||||
public function getAPIMethodName() {
|
||||
return 'almanac.device.search';
|
||||
}
|
||||
|
||||
public function newSearchEngine() {
|
||||
return new AlmanacDeviceSearchEngine();
|
||||
}
|
||||
|
||||
public function getMethodSummary() {
|
||||
return pht('Read information about Almanac devices.');
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacServiceSearchConduitAPIMethod
|
||||
extends PhabricatorSearchEngineAPIMethod {
|
||||
|
||||
public function getAPIMethodName() {
|
||||
return 'almanac.service.search';
|
||||
}
|
||||
|
||||
public function newSearchEngine() {
|
||||
return new AlmanacServiceSearchEngine();
|
||||
}
|
||||
|
||||
public function getMethodSummary() {
|
||||
return pht('Read information about Almanac services.');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacBindingDisableController
|
||||
extends AlmanacServiceController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
|
||||
$id = $request->getURIData('id');
|
||||
$binding = id(new AlmanacBindingQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($id))
|
||||
->requireCapabilities(
|
||||
array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
))
|
||||
->executeOne();
|
||||
if (!$binding) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$id = $binding->getID();
|
||||
$is_disable = !$binding->getIsDisabled();
|
||||
$done_uri = $binding->getURI();
|
||||
|
||||
if ($is_disable) {
|
||||
$disable_title = pht('Disable Binding');
|
||||
$disable_body = pht('Disable this binding?');
|
||||
$disable_button = pht('Disable Binding');
|
||||
|
||||
$v_disable = 1;
|
||||
} else {
|
||||
$disable_title = pht('Enable Binding');
|
||||
$disable_body = pht('Enable this binding?');
|
||||
$disable_button = pht('Enable Binding');
|
||||
|
||||
$v_disable = 0;
|
||||
}
|
||||
|
||||
|
||||
if ($request->isFormPost()) {
|
||||
$type_disable = AlmanacBindingTransaction::TYPE_DISABLE;
|
||||
|
||||
$xactions = array();
|
||||
|
||||
$xactions[] = id(new AlmanacBindingTransaction())
|
||||
->setTransactionType($type_disable)
|
||||
->setNewValue($v_disable);
|
||||
|
||||
$editor = id(new AlmanacBindingEditor())
|
||||
->setActor($viewer)
|
||||
->setContentSourceFromRequest($request)
|
||||
->setContinueOnNoEffect(true)
|
||||
->setContinueOnMissingFields(true);
|
||||
|
||||
$editor->applyTransactions($binding, $xactions);
|
||||
|
||||
return id(new AphrontRedirectResponse())->setURI($done_uri);
|
||||
}
|
||||
|
||||
return $this->newDialog()
|
||||
->setTitle($disable_title)
|
||||
->appendParagraph($disable_body)
|
||||
->addSubmitButton($disable_button)
|
||||
->addCancelButton($done_uri);
|
||||
}
|
||||
|
||||
}
|
|
@ -15,6 +15,7 @@ final class AlmanacBindingViewController
|
|||
$binding = id(new AlmanacBindingQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($id))
|
||||
->needProperties(true)
|
||||
->executeOne();
|
||||
if (!$binding) {
|
||||
return new Aphront404Response();
|
||||
|
@ -34,15 +35,21 @@ final class AlmanacBindingViewController
|
|||
->setHeader($title)
|
||||
->setPolicyObject($binding);
|
||||
|
||||
if ($binding->getIsDisabled()) {
|
||||
$header->setStatus('fa-ban', 'red', pht('Disabled'));
|
||||
}
|
||||
|
||||
$box = id(new PHUIObjectBoxView())
|
||||
->setHeader($header)
|
||||
->addPropertyList($property_list);
|
||||
|
||||
if ($binding->getService()->getIsLocked()) {
|
||||
$this->addLockMessage(
|
||||
if ($binding->getService()->isClusterService()) {
|
||||
$this->addClusterMessage(
|
||||
$box,
|
||||
pht('The service for this binding is a cluster service.'),
|
||||
pht(
|
||||
'This service for this binding is locked, so the binding can '.
|
||||
'The service for this binding is a cluster service. You do not '.
|
||||
'have permission to manage cluster services, so this binding can '.
|
||||
'not be edited.'));
|
||||
}
|
||||
|
||||
|
@ -111,6 +118,24 @@ final class AlmanacBindingViewController
|
|||
->setWorkflow(!$can_edit)
|
||||
->setDisabled(!$can_edit));
|
||||
|
||||
if ($binding->getIsDisabled()) {
|
||||
$disable_icon = 'fa-check';
|
||||
$disable_text = pht('Enable Binding');
|
||||
} else {
|
||||
$disable_icon = 'fa-ban';
|
||||
$disable_text = pht('Disable Binding');
|
||||
}
|
||||
|
||||
$disable_href = $this->getApplicationURI("binding/disable/{$id}/");
|
||||
|
||||
$actions->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon($disable_icon)
|
||||
->setName($disable_text)
|
||||
->setHref($disable_href)
|
||||
->setWorkflow(true)
|
||||
->setDisabled(!$can_edit));
|
||||
|
||||
return $actions;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,26 +12,52 @@ final class AlmanacConsoleController extends AlmanacController {
|
|||
$menu = id(new PHUIObjectItemListView())
|
||||
->setUser($viewer);
|
||||
|
||||
$menu->addItem(
|
||||
id(new PHUIObjectItemView())
|
||||
->setHeader(pht('Services'))
|
||||
->setHref($this->getApplicationURI('service/'))
|
||||
->setIcon('fa-plug')
|
||||
->addAttribute(pht('Manage Almanac services.')));
|
||||
|
||||
$menu->addItem(
|
||||
id(new PHUIObjectItemView())
|
||||
->setHeader(pht('Devices'))
|
||||
->setHref($this->getApplicationURI('device/'))
|
||||
->setIcon('fa-server')
|
||||
->addAttribute(pht('Manage Almanac devices.')));
|
||||
->addAttribute(
|
||||
pht(
|
||||
'Create an inventory of physical and virtual hosts and '.
|
||||
'devices.')));
|
||||
|
||||
$menu->addItem(
|
||||
id(new PHUIObjectItemView())
|
||||
->setHeader(pht('Services'))
|
||||
->setHref($this->getApplicationURI('service/'))
|
||||
->setIcon('fa-plug')
|
||||
->addAttribute(
|
||||
pht(
|
||||
'Create and update services, and map them to interfaces on '.
|
||||
'devices.')));
|
||||
|
||||
$menu->addItem(
|
||||
id(new PHUIObjectItemView())
|
||||
->setHeader(pht('Networks'))
|
||||
->setHref($this->getApplicationURI('network/'))
|
||||
->setIcon('fa-globe')
|
||||
->addAttribute(pht('Manage Almanac networks.')));
|
||||
->addAttribute(
|
||||
pht(
|
||||
'Manage public and private networks.')));
|
||||
|
||||
$menu->addItem(
|
||||
id(new PHUIObjectItemView())
|
||||
->setHeader(pht('Namespaces'))
|
||||
->setHref($this->getApplicationURI('namespace/'))
|
||||
->setIcon('fa-asterisk')
|
||||
->addAttribute(
|
||||
pht('Control who can create new named services and devices.')));
|
||||
|
||||
$docs_uri = PhabricatorEnv::getDoclink(
|
||||
'Almanac User Guide');
|
||||
|
||||
$menu->addItem(
|
||||
id(new PHUIObjectItemView())
|
||||
->setHeader(pht('Documentation'))
|
||||
->setHref($docs_uri)
|
||||
->setIcon('fa-book')
|
||||
->addAttribute(pht('Browse documentation for Almanac.')));
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
$crumbs->addTextCrumb(pht('Console'));
|
||||
|
|
|
@ -10,27 +10,14 @@ abstract class AlmanacController
|
|||
$properties = $object->getAlmanacProperties();
|
||||
|
||||
$this->requireResource('almanac-css');
|
||||
Javelin::initBehavior('phabricator-tooltips', array());
|
||||
|
||||
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
||||
$viewer,
|
||||
$object,
|
||||
PhabricatorPolicyCapability::CAN_EDIT);
|
||||
|
||||
$field_list = PhabricatorCustomField::getObjectFields(
|
||||
$object,
|
||||
PhabricatorCustomField::ROLE_DEFAULT);
|
||||
|
||||
// Before reading values from the object, read defaults.
|
||||
$defaults = mpull(
|
||||
$field_list->getFields(),
|
||||
'getValueForStorage',
|
||||
'getFieldKey');
|
||||
|
||||
$field_list
|
||||
->setViewer($viewer)
|
||||
->readFieldsFromStorage($object);
|
||||
|
||||
Javelin::initBehavior('phabricator-tooltips', array());
|
||||
$properties = $object->getAlmanacProperties();
|
||||
|
||||
$icon_builtin = id(new PHUIIconView())
|
||||
->setIcon('fa-circle')
|
||||
|
@ -51,45 +38,46 @@ abstract class AlmanacController
|
|||
));
|
||||
|
||||
$builtins = $object->getAlmanacPropertyFieldSpecifications();
|
||||
$defaults = mpull($builtins, null, 'getValueForTransaction');
|
||||
|
||||
// Sort fields so builtin fields appear first, then fields are ordered
|
||||
// alphabetically.
|
||||
$fields = $field_list->getFields();
|
||||
$fields = msort($fields, 'getFieldKey');
|
||||
$properties = msort($properties, 'getFieldName');
|
||||
|
||||
$head = array();
|
||||
$tail = array();
|
||||
foreach ($fields as $field) {
|
||||
$key = $field->getFieldKey();
|
||||
foreach ($properties as $property) {
|
||||
$key = $property->getFieldName();
|
||||
if (isset($builtins[$key])) {
|
||||
$head[$key] = $field;
|
||||
$head[$key] = $property;
|
||||
} else {
|
||||
$tail[$key] = $field;
|
||||
$tail[$key] = $property;
|
||||
}
|
||||
}
|
||||
|
||||
$fields = $head + $tail;
|
||||
$properties = $head + $tail;
|
||||
|
||||
$delete_base = $this->getApplicationURI('property/delete/');
|
||||
$edit_base = $this->getApplicationURI('property/update/');
|
||||
|
||||
$rows = array();
|
||||
foreach ($fields as $key => $field) {
|
||||
$value = $field->getValueForStorage();
|
||||
foreach ($properties as $key => $property) {
|
||||
$value = $property->getFieldValue();
|
||||
|
||||
$is_builtin = isset($builtins[$key]);
|
||||
|
||||
$delete_uri = $this->getApplicationURI('property/delete/');
|
||||
$delete_uri = id(new PhutilURI($delete_uri))
|
||||
$delete_uri = id(new PhutilURI($delete_base))
|
||||
->setQueryParams(
|
||||
array(
|
||||
'objectPHID' => $object->getPHID(),
|
||||
'key' => $key,
|
||||
'objectPHID' => $object->getPHID(),
|
||||
));
|
||||
|
||||
$edit_uri = $this->getApplicationURI('property/edit/');
|
||||
$edit_uri = id(new PhutilURI($edit_uri))
|
||||
$edit_uri = id(new PhutilURI($edit_base))
|
||||
->setQueryParams(
|
||||
array(
|
||||
'objectPHID' => $object->getPHID(),
|
||||
'key' => $key,
|
||||
'objectPHID' => $object->getPHID(),
|
||||
));
|
||||
|
||||
$delete = javelin_tag(
|
||||
|
@ -153,7 +141,8 @@ abstract class AlmanacController
|
|||
));
|
||||
|
||||
$phid = $object->getPHID();
|
||||
$add_uri = $this->getApplicationURI("property/edit/?objectPHID={$phid}");
|
||||
$add_uri = id(new PhutilURI($edit_base))
|
||||
->setQueryParam('objectPHID', $object->getPHID());
|
||||
|
||||
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
||||
$viewer,
|
||||
|
@ -177,23 +166,50 @@ abstract class AlmanacController
|
|||
->setTable($table);
|
||||
}
|
||||
|
||||
protected function addLockMessage(PHUIObjectBoxView $box, $message) {
|
||||
protected function addClusterMessage(
|
||||
PHUIObjectBoxView $box,
|
||||
$positive,
|
||||
$negative) {
|
||||
|
||||
$can_manage = $this->hasApplicationCapability(
|
||||
AlmanacManageClusterServicesCapability::CAPABILITY);
|
||||
|
||||
$doc_link = phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => PhabricatorEnv::getDoclink('Almanac User Guide'),
|
||||
'href' => PhabricatorEnv::getDoclink(
|
||||
'User Guide: Phabricator Clusters'),
|
||||
'target' => '_blank',
|
||||
),
|
||||
pht('Learn More'));
|
||||
|
||||
if ($can_manage) {
|
||||
$severity = PHUIInfoView::SEVERITY_NOTICE;
|
||||
$message = $positive;
|
||||
} else {
|
||||
$severity = PHUIInfoView::SEVERITY_WARNING;
|
||||
$message = $negative;
|
||||
}
|
||||
|
||||
$icon = id(new PHUIIconView())
|
||||
->setIcon('fa-sitemap');
|
||||
|
||||
$error_view = id(new PHUIInfoView())
|
||||
->setSeverity(PHUIInfoView::SEVERITY_WARNING)
|
||||
->setSeverity($severity)
|
||||
->setErrors(
|
||||
array(
|
||||
array($message, ' ', $doc_link),
|
||||
array($icon, ' ', $message, ' ', $doc_link),
|
||||
));
|
||||
|
||||
$box->setInfoView($error_view);
|
||||
}
|
||||
|
||||
protected function getPropertyDeleteURI($object) {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function getPropertyUpdateURI($object) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,15 +15,12 @@ final class AlmanacDeviceViewController
|
|||
$device = id(new AlmanacDeviceQuery())
|
||||
->setViewer($viewer)
|
||||
->withNames(array($name))
|
||||
->needProperties(true)
|
||||
->executeOne();
|
||||
if (!$device) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
// We rebuild locks on a device when viewing the detail page, so they
|
||||
// automatically get corrected if they fall out of sync.
|
||||
$device->rebuildDeviceLocks();
|
||||
|
||||
$title = pht('Device %s', $device->getName());
|
||||
|
||||
$property_list = $this->buildPropertyList($device);
|
||||
|
@ -39,12 +36,14 @@ final class AlmanacDeviceViewController
|
|||
->setHeader($header)
|
||||
->addPropertyList($property_list);
|
||||
|
||||
if ($device->getIsLocked()) {
|
||||
$this->addLockMessage(
|
||||
if ($device->isClusterDevice()) {
|
||||
$this->addClusterMessage(
|
||||
$box,
|
||||
pht('This device is bound to a cluster service.'),
|
||||
pht(
|
||||
'This device is bound to a locked service, so it can not be '.
|
||||
'edited.'));
|
||||
'This device is bound to a cluster service. You do not have '.
|
||||
'permission to manage cluster services, so the device can not '.
|
||||
'be edited.'));
|
||||
}
|
||||
|
||||
$interfaces = $this->buildInterfaceList($device);
|
||||
|
@ -218,14 +217,14 @@ final class AlmanacDeviceViewController
|
|||
|
||||
$handles = $viewer->loadHandles(mpull($services, 'getPHID'));
|
||||
|
||||
$icon_lock = id(new PHUIIconView())
|
||||
->setIcon('fa-lock');
|
||||
$icon_cluster = id(new PHUIIconView())
|
||||
->setIcon('fa-sitemap');
|
||||
|
||||
$rows = array();
|
||||
foreach ($services as $service) {
|
||||
$rows[] = array(
|
||||
($service->getIsLocked()
|
||||
? $icon_lock
|
||||
($service->isClusterService()
|
||||
? $icon_cluster
|
||||
: null),
|
||||
$handles->renderHandle($service->getPHID()),
|
||||
);
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacInterfaceDeleteController
|
||||
extends AlmanacDeviceController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
|
||||
$id = $request->getURIData('id');
|
||||
$interface = id(new AlmanacInterfaceQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($id))
|
||||
->requireCapabilities(
|
||||
array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
))
|
||||
->executeOne();
|
||||
if (!$interface) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$device = $interface->getDevice();
|
||||
$device_uri = $device->getURI();
|
||||
|
||||
if ($interface->loadIsInUse()) {
|
||||
return $this->newDialog()
|
||||
->setTitle(pht('Interface In Use'))
|
||||
->appendParagraph(
|
||||
pht(
|
||||
'You can not delete this interface because it is currently in '.
|
||||
'use. One or more services are bound to it.'))
|
||||
->addCancelButton($device_uri);
|
||||
}
|
||||
|
||||
if ($request->isFormPost()) {
|
||||
$type_interface = AlmanacDeviceTransaction::TYPE_INTERFACE;
|
||||
|
||||
$xactions = array();
|
||||
|
||||
$v_old = array(
|
||||
'id' => $interface->getID(),
|
||||
) + $interface->toAddress()->toDictionary();
|
||||
|
||||
$xactions[] = id(new AlmanacDeviceTransaction())
|
||||
->setTransactionType($type_interface)
|
||||
->setOldValue($v_old)
|
||||
->setNewValue(null);
|
||||
|
||||
$editor = id(new AlmanacDeviceEditor())
|
||||
->setActor($viewer)
|
||||
->setContentSourceFromRequest($request)
|
||||
->setContinueOnNoEffect(true)
|
||||
->setContinueOnMissingFields(true);
|
||||
|
||||
$editor->applyTransactions($device, $xactions);
|
||||
|
||||
return id(new AphrontRedirectResponse())->setURI($device_uri);
|
||||
}
|
||||
|
||||
return $this->newDialog()
|
||||
->setTitle(pht('Delete Interface'))
|
||||
->appendParagraph(
|
||||
pht(
|
||||
'Remove interface %s on device %s?',
|
||||
phutil_tag('strong', array(), $interface->renderDisplayAddress()),
|
||||
phutil_tag('strong', array(), $device->getName())))
|
||||
->addCancelButton($device_uri)
|
||||
->addSubmitButton(pht('Delete Interface'));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
abstract class AlmanacNamespaceController extends AlmanacController {
|
||||
|
||||
protected function buildApplicationCrumbs() {
|
||||
$crumbs = parent::buildApplicationCrumbs();
|
||||
|
||||
$list_uri = $this->getApplicationURI('namespace/');
|
||||
$crumbs->addTextCrumb(pht('Namespaces'), $list_uri);
|
||||
|
||||
return $crumbs;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacNamespaceEditController extends AlmanacNamespaceController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
return id(new AlmanacNamespaceEditEngine())
|
||||
->setController($this)
|
||||
->buildResponse();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacNamespaceListController
|
||||
extends AlmanacNamespaceController {
|
||||
|
||||
public function shouldAllowPublic() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
return id(new AlmanacNamespaceSearchEngine())
|
||||
->setController($this)
|
||||
->buildResponse();
|
||||
}
|
||||
|
||||
protected function buildApplicationCrumbs() {
|
||||
$crumbs = parent::buildApplicationCrumbs();
|
||||
|
||||
id(new AlmanacNamespaceEditEngine())
|
||||
->setViewer($this->getViewer())
|
||||
->addActionToCrumbs($crumbs);
|
||||
|
||||
return $crumbs;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacNamespaceViewController
|
||||
extends AlmanacNamespaceController {
|
||||
|
||||
public function shouldAllowPublic() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
|
||||
$id = $request->getURIData('id');
|
||||
$namespace = id(new AlmanacNamespaceQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($id))
|
||||
->executeOne();
|
||||
if (!$namespace) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$title = pht('Namespace %s', $namespace->getName());
|
||||
|
||||
$property_list = $this->buildPropertyList($namespace);
|
||||
$action_list = $this->buildActionList($namespace);
|
||||
$property_list->setActionList($action_list);
|
||||
|
||||
$header = id(new PHUIHeaderView())
|
||||
->setUser($viewer)
|
||||
->setHeader($namespace->getName())
|
||||
->setPolicyObject($namespace);
|
||||
|
||||
$box = id(new PHUIObjectBoxView())
|
||||
->setHeader($header)
|
||||
->addPropertyList($property_list);
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
$crumbs->addTextCrumb($namespace->getName());
|
||||
|
||||
$timeline = $this->buildTransactionTimeline(
|
||||
$namespace,
|
||||
new AlmanacNamespaceTransactionQuery());
|
||||
$timeline->setShouldTerminate(true);
|
||||
|
||||
return $this->newPage()
|
||||
->setTitle($title)
|
||||
->setCrumbs($crumbs)
|
||||
->appendChild(
|
||||
array(
|
||||
$box,
|
||||
$timeline,
|
||||
));
|
||||
}
|
||||
|
||||
private function buildPropertyList(AlmanacNamespace $namespace) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$properties = id(new PHUIPropertyListView())
|
||||
->setUser($viewer);
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
private function buildActionList(AlmanacNamespace $namespace) {
|
||||
$viewer = $this->getViewer();
|
||||
$id = $namespace->getID();
|
||||
|
||||
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
||||
$viewer,
|
||||
$namespace,
|
||||
PhabricatorPolicyCapability::CAN_EDIT);
|
||||
|
||||
$actions = id(new PhabricatorActionListView())
|
||||
->setUser($viewer);
|
||||
|
||||
$actions->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon('fa-pencil')
|
||||
->setName(pht('Edit Namespace'))
|
||||
->setHref($this->getApplicationURI("namespace/edit/{$id}/"))
|
||||
->setWorkflow(!$can_edit)
|
||||
->setDisabled(!$can_edit));
|
||||
|
||||
return $actions;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,142 +1,11 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacNetworkEditController
|
||||
extends AlmanacNetworkController {
|
||||
final class AlmanacNetworkEditController extends AlmanacNetworkController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
|
||||
$list_uri = $this->getApplicationURI('network/');
|
||||
|
||||
$id = $request->getURIData('id');
|
||||
if ($id) {
|
||||
$network = id(new AlmanacNetworkQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($id))
|
||||
->requireCapabilities(
|
||||
array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
))
|
||||
->executeOne();
|
||||
if (!$network) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$is_new = false;
|
||||
$network_uri = $this->getApplicationURI('network/'.$network->getID().'/');
|
||||
$cancel_uri = $network_uri;
|
||||
$title = pht('Edit Network');
|
||||
$save_button = pht('Save Changes');
|
||||
} else {
|
||||
$this->requireApplicationCapability(
|
||||
AlmanacCreateNetworksCapability::CAPABILITY);
|
||||
|
||||
$network = AlmanacNetwork::initializeNewNetwork();
|
||||
$is_new = true;
|
||||
|
||||
$cancel_uri = $list_uri;
|
||||
$title = pht('Create Network');
|
||||
$save_button = pht('Create Network');
|
||||
}
|
||||
|
||||
$v_name = $network->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 = AlmanacNetworkTransaction::TYPE_NAME;
|
||||
$type_view = PhabricatorTransactions::TYPE_VIEW_POLICY;
|
||||
$type_edit = PhabricatorTransactions::TYPE_EDIT_POLICY;
|
||||
|
||||
$xactions = array();
|
||||
|
||||
$xactions[] = id(new AlmanacNetworkTransaction())
|
||||
->setTransactionType($type_name)
|
||||
->setNewValue($v_name);
|
||||
|
||||
$xactions[] = id(new AlmanacNetworkTransaction())
|
||||
->setTransactionType($type_view)
|
||||
->setNewValue($v_view);
|
||||
|
||||
$xactions[] = id(new AlmanacNetworkTransaction())
|
||||
->setTransactionType($type_edit)
|
||||
->setNewValue($v_edit);
|
||||
|
||||
$editor = id(new AlmanacNetworkEditor())
|
||||
->setActor($viewer)
|
||||
->setContentSourceFromRequest($request)
|
||||
->setContinueOnNoEffect(true);
|
||||
|
||||
try {
|
||||
$editor->applyTransactions($network, $xactions);
|
||||
|
||||
$id = $network->getID();
|
||||
$network_uri = $this->getApplicationURI("network/{$id}/");
|
||||
return id(new AphrontRedirectResponse())->setURI($network_uri);
|
||||
} catch (PhabricatorApplicationTransactionValidationException $ex) {
|
||||
$validation_exception = $ex;
|
||||
$e_name = $ex->getShortMessage($type_name);
|
||||
|
||||
$network->setViewPolicy($v_view);
|
||||
$network->setEditPolicy($v_edit);
|
||||
}
|
||||
}
|
||||
|
||||
$policies = id(new PhabricatorPolicyQuery())
|
||||
->setViewer($viewer)
|
||||
->setObject($network)
|
||||
->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($network)
|
||||
->setCapability(PhabricatorPolicyCapability::CAN_VIEW)
|
||||
->setPolicies($policies))
|
||||
->appendChild(
|
||||
id(new AphrontFormPolicyControl())
|
||||
->setName('editPolicy')
|
||||
->setPolicyObject($network)
|
||||
->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)
|
||||
->setForm($form);
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
if ($is_new) {
|
||||
$crumbs->addTextCrumb(pht('Create Network'));
|
||||
} else {
|
||||
$crumbs->addTextCrumb($network->getName(), $network_uri);
|
||||
$crumbs->addTextCrumb(pht('Edit'));
|
||||
}
|
||||
|
||||
return $this->newPage()
|
||||
->setTitle($title)
|
||||
->setCrumbs($crumbs)
|
||||
->appendChild(
|
||||
array(
|
||||
$box,
|
||||
));
|
||||
return id(new AlmanacNetworkEditEngine())
|
||||
->setController($this)
|
||||
->buildResponse();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,3 +1,56 @@
|
|||
<?php
|
||||
|
||||
abstract class AlmanacPropertyController extends AlmanacController {}
|
||||
abstract class AlmanacPropertyController extends AlmanacController {
|
||||
|
||||
private $propertyObject;
|
||||
|
||||
public function getPropertyObject() {
|
||||
return $this->propertyObject;
|
||||
}
|
||||
|
||||
protected function loadPropertyObject() {
|
||||
$viewer = $this->getViewer();
|
||||
$request = $this->getRequest();
|
||||
$object_phid = $request->getStr('objectPHID');
|
||||
|
||||
|
||||
switch (phid_get_type($object_phid)) {
|
||||
case AlmanacBindingPHIDType::TYPECONST:
|
||||
$query = new AlmanacBindingQuery();
|
||||
break;
|
||||
case AlmanacDevicePHIDType::TYPECONST:
|
||||
$query = new AlmanacDeviceQuery();
|
||||
break;
|
||||
case AlmanacServicePHIDType::TYPECONST:
|
||||
$query = new AlmanacServiceQuery();
|
||||
break;
|
||||
default:
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$object = $query
|
||||
->setViewer($viewer)
|
||||
->withPHIDs(array($object_phid))
|
||||
->requireCapabilities(
|
||||
array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
))
|
||||
->needProperties(true)
|
||||
->executeOne();
|
||||
|
||||
if (!$object) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
if (!($object instanceof AlmanacPropertyInterface)) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$this->propertyObject = $object;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,27 +1,17 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacPropertyDeleteController
|
||||
extends AlmanacDeviceController {
|
||||
extends AlmanacPropertyController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
|
||||
$object = id(new PhabricatorObjectQuery())
|
||||
->setViewer($viewer)
|
||||
->withPHIDs(array($request->getStr('objectPHID')))
|
||||
->requireCapabilities(
|
||||
array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
))
|
||||
->executeOne();
|
||||
if (!$object) {
|
||||
return new Aphront404Response();
|
||||
$response = $this->loadPropertyObject();
|
||||
if ($response) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
if (!($object instanceof AlmanacPropertyInterface)) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
$object = $this->getPropertyObject();
|
||||
|
||||
$key = $request->getStr('key');
|
||||
if (!strlen($key)) {
|
||||
|
@ -34,53 +24,24 @@ final class AlmanacPropertyDeleteController
|
|||
$is_builtin = isset($builtins[$key]);
|
||||
|
||||
if ($is_builtin) {
|
||||
// This is a builtin property, so we're going to reset it to the
|
||||
// default value.
|
||||
$field_list = PhabricatorCustomField::getObjectFields(
|
||||
$object,
|
||||
PhabricatorCustomField::ROLE_DEFAULT);
|
||||
|
||||
// Note that we're NOT loading field values from the object: we just want
|
||||
// to get the field's default value so we can reset it.
|
||||
|
||||
$fields = $field_list->getFields();
|
||||
$field = $fields[$key];
|
||||
|
||||
$is_delete = false;
|
||||
$new_value = $field->getValueForStorage();
|
||||
|
||||
// Now, load the field to get the old value.
|
||||
|
||||
$field_list
|
||||
->setViewer($viewer)
|
||||
->readFieldsFromStorage($object);
|
||||
|
||||
$old_value = $field->getValueForStorage();
|
||||
|
||||
$title = pht('Reset Property');
|
||||
$body = pht('Reset this property to its default value?');
|
||||
$submit_text = pht('Reset');
|
||||
$body = pht(
|
||||
'Reset property "%s" to its default value?',
|
||||
$key);
|
||||
$submit_text = pht('Reset Property');
|
||||
} else {
|
||||
// This is a custom property, so we're going to delete it outright.
|
||||
$is_delete = true;
|
||||
$old_value = $object->getAlmanacPropertyValue($key);
|
||||
$new_value = null;
|
||||
|
||||
$title = pht('Delete Property');
|
||||
$body = pht('Delete this property? TODO: DOES NOT WORK YET');
|
||||
$submit_text = pht('Delete');
|
||||
$body = pht(
|
||||
'Delete property "%s"?',
|
||||
$key);
|
||||
$submit_text = pht('Delete Property');
|
||||
}
|
||||
|
||||
$validation_exception = null;
|
||||
if ($request->isFormPost()) {
|
||||
$xaction = $object->getApplicationTransactionTemplate()
|
||||
->setTransactionType(PhabricatorTransactions::TYPE_CUSTOMFIELD)
|
||||
->setMetadataValue('customfield:key', $key)
|
||||
->setOldValue($old_value)
|
||||
->setNewValue($new_value);
|
||||
|
||||
// TODO: We aren't really deleting properties that we claim to delete
|
||||
// yet, but that needs to be specialized a little bit.
|
||||
->setTransactionType(AlmanacTransaction::TYPE_PROPERTY_REMOVE)
|
||||
->setMetadataValue('almanac.property', $key);
|
||||
|
||||
$editor = $object->getApplicationTransactionEditor()
|
||||
->setActor($viewer)
|
||||
|
|
|
@ -1,157 +1,95 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacPropertyEditController
|
||||
extends AlmanacDeviceController {
|
||||
extends AlmanacPropertyController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
|
||||
$object = id(new PhabricatorObjectQuery())
|
||||
->setViewer($viewer)
|
||||
->withPHIDs(array($request->getStr('objectPHID')))
|
||||
->requireCapabilities(
|
||||
array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
))
|
||||
->executeOne();
|
||||
if (!$object) {
|
||||
return new Aphront404Response();
|
||||
$response = $this->loadPropertyObject();
|
||||
if ($response) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
if (!($object instanceof AlmanacPropertyInterface)) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
$object = $this->getPropertyObject();
|
||||
|
||||
$cancel_uri = $object->getURI();
|
||||
$property_key = $request->getStr('key');
|
||||
|
||||
$key = $request->getStr('key');
|
||||
if ($key) {
|
||||
$property_key = $key;
|
||||
|
||||
$is_new = false;
|
||||
$title = pht('Edit Property');
|
||||
$save_button = pht('Save Changes');
|
||||
if (!strlen($property_key)) {
|
||||
return $this->buildPropertyKeyResponse($cancel_uri, null);
|
||||
} else {
|
||||
$property_key = null;
|
||||
|
||||
$is_new = true;
|
||||
$title = pht('Add Property');
|
||||
$save_button = pht('Add Property');
|
||||
}
|
||||
|
||||
if ($is_new) {
|
||||
$errors = array();
|
||||
$property = null;
|
||||
|
||||
$v_name = null;
|
||||
$e_name = true;
|
||||
|
||||
if ($request->isFormPost()) {
|
||||
$name = $request->getStr('name');
|
||||
if (!strlen($name)) {
|
||||
$e_name = pht('Required');
|
||||
$errors[] = pht('You must provide a property name.');
|
||||
} else {
|
||||
$caught = null;
|
||||
$error = null;
|
||||
try {
|
||||
AlmanacNames::validateServiceOrDeviceName($name);
|
||||
AlmanacNames::validateName($property_key);
|
||||
} catch (Exception $ex) {
|
||||
$caught = $ex;
|
||||
$error = $ex->getMessage();
|
||||
}
|
||||
|
||||
// NOTE: If you enter an existing name, we're just treating it as an
|
||||
// edit operation. This might be a little confusing.
|
||||
|
||||
if ($error !== null) {
|
||||
if ($request->isFormPost()) {
|
||||
// The user is creating a new property and picked a bad name. Give
|
||||
// them an opportunity to fix it.
|
||||
return $this->buildPropertyKeyResponse($cancel_uri, $error);
|
||||
} else {
|
||||
// The user is editing an invalid property.
|
||||
return $this->newDialog()
|
||||
->setTitle(pht('Invalid Property'))
|
||||
->appendParagraph(
|
||||
pht(
|
||||
'The property name "%s" is invalid. This property can not '.
|
||||
'be edited.',
|
||||
$property_key))
|
||||
->appendParagraph($error)
|
||||
->addCancelButton($cancel_uri);
|
||||
}
|
||||
if ($caught) {
|
||||
$e_name = pht('Invalid');
|
||||
$errors[] = $caught->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
if (!$errors) {
|
||||
$property_key = $name;
|
||||
}
|
||||
return $object->newAlmanacPropertyEditEngine()
|
||||
->addContextParameter('objectPHID')
|
||||
->addContextParameter('key')
|
||||
->setTargetObject($object)
|
||||
->setPropertyKey($property_key)
|
||||
->setController($this)
|
||||
->buildResponse();
|
||||
}
|
||||
|
||||
private function buildPropertyKeyResponse($cancel_uri, $error) {
|
||||
$viewer = $this->getViewer();
|
||||
$request = $this->getRequest();
|
||||
$v_key = $request->getStr('key');
|
||||
|
||||
if ($error !== null) {
|
||||
$e_key = pht('Invalid');
|
||||
} else {
|
||||
$e_key = true;
|
||||
}
|
||||
|
||||
if ($property_key === null) {
|
||||
$form = id(new AphrontFormView())
|
||||
->setUser($viewer)
|
||||
->appendChild(
|
||||
id(new AphrontFormTextControl())
|
||||
->setName('name')
|
||||
->setName('key')
|
||||
->setLabel(pht('Name'))
|
||||
->setValue($v_name)
|
||||
->setError($e_name));
|
||||
->setValue($v_key)
|
||||
->setError($e_key));
|
||||
|
||||
$errors = array();
|
||||
if ($error !== null) {
|
||||
$errors[] = $error;
|
||||
}
|
||||
|
||||
return $this->newDialog()
|
||||
->setTitle($title)
|
||||
->setErrors($errors)
|
||||
->setTitle(pht('Add Property'))
|
||||
->addHiddenInput('objectPHID', $request->getStr('objectPHID'))
|
||||
->setErrors($errors)
|
||||
->appendForm($form)
|
||||
->addSubmitButton(pht('Continue'))
|
||||
->addCancelButton($cancel_uri);
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure property key is appropriate.
|
||||
// TODO: It would be cleaner to put this safety check in the Editor.
|
||||
AlmanacNames::validateServiceOrDeviceName($property_key);
|
||||
|
||||
// If we're adding a new property, put a placeholder on the object so
|
||||
// that we can build a CustomField for it.
|
||||
if (!$object->hasAlmanacProperty($property_key)) {
|
||||
$temporary_property = id(new AlmanacProperty())
|
||||
->setObjectPHID($object->getPHID())
|
||||
->setFieldName($property_key);
|
||||
|
||||
$object->attachAlmanacProperties(array($temporary_property));
|
||||
}
|
||||
|
||||
$field_list = PhabricatorCustomField::getObjectFields(
|
||||
$object,
|
||||
PhabricatorCustomField::ROLE_DEFAULT);
|
||||
|
||||
// Select only the field being edited.
|
||||
$fields = $field_list->getFields();
|
||||
$fields = array_select_keys($fields, array($property_key));
|
||||
$field_list = new PhabricatorCustomFieldList($fields);
|
||||
|
||||
$field_list
|
||||
->setViewer($viewer)
|
||||
->readFieldsFromStorage($object);
|
||||
|
||||
$validation_exception = null;
|
||||
if ($request->isFormPost() && $request->getStr('isValueEdit')) {
|
||||
$xactions = $field_list->buildFieldTransactionsFromRequest(
|
||||
$object->getApplicationTransactionTemplate(),
|
||||
$request);
|
||||
|
||||
$editor = $object->getApplicationTransactionEditor()
|
||||
->setActor($viewer)
|
||||
->setContentSourceFromRequest($request)
|
||||
->setContinueOnNoEffect(true)
|
||||
->setContinueOnMissingFields(true);
|
||||
|
||||
try {
|
||||
$editor->applyTransactions($object, $xactions);
|
||||
return id(new AphrontRedirectResponse())->setURI($cancel_uri);
|
||||
} catch (PhabricatorApplicationTransactionValidationException $ex) {
|
||||
$validation_exception = $ex;
|
||||
}
|
||||
}
|
||||
|
||||
$form = id(new AphrontFormView())
|
||||
->setUser($viewer)
|
||||
->addHiddenInput('objectPHID', $request->getStr('objectPHID'))
|
||||
->addHiddenInput('key', $request->getStr('key'))
|
||||
->addHiddenInput('name', $property_key)
|
||||
->addHiddenInput('isValueEdit', true);
|
||||
|
||||
$field_list->appendFieldsToForm($form);
|
||||
|
||||
return $this->newDialog()
|
||||
->setTitle($title)
|
||||
->setValidationException($validation_exception)
|
||||
->appendForm($form)
|
||||
->addSubmitButton($save_button)
|
||||
->addCancelButton($cancel_uri);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,4 +11,14 @@ abstract class AlmanacServiceController extends AlmanacController {
|
|||
return $crumbs;
|
||||
}
|
||||
|
||||
protected function getPropertyDeleteURI($object) {
|
||||
$id = $object->getID();
|
||||
return "/almanac/service/delete/{$id}/";
|
||||
}
|
||||
|
||||
protected function getPropertyUpdateURI($object) {
|
||||
$id = $object->getID();
|
||||
return "/almanac/service/property/{$id}/";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -34,21 +34,19 @@ final class AlmanacServiceEditController
|
|||
$this->requireApplicationCapability(
|
||||
AlmanacCreateServicesCapability::CAPABILITY);
|
||||
|
||||
$service_class = $request->getStr('serviceClass');
|
||||
$service_types = AlmanacServiceType::getAllServiceTypes();
|
||||
if (empty($service_types[$service_class])) {
|
||||
return $this->buildServiceTypeResponse($service_types, $cancel_uri);
|
||||
$service_type = $request->getStr('serviceType');
|
||||
|
||||
try {
|
||||
$service = AlmanacService::initializeNewService($service_type);
|
||||
} catch (Exception $ex) {
|
||||
return $this->buildServiceTypeResponse($cancel_uri);
|
||||
}
|
||||
|
||||
$service_type = $service_types[$service_class];
|
||||
if ($service_type->isClusterServiceType()) {
|
||||
if ($service->isClusterService()) {
|
||||
$this->requireApplicationCapability(
|
||||
AlmanacCreateClusterServicesCapability::CAPABILITY);
|
||||
AlmanacManageClusterServicesCapability::CAPABILITY);
|
||||
}
|
||||
|
||||
$service = AlmanacService::initializeNewService();
|
||||
$service->setServiceClass($service_class);
|
||||
$service->attachServiceType($service_type);
|
||||
$is_new = true;
|
||||
|
||||
$title = pht('Create Service');
|
||||
|
@ -125,7 +123,7 @@ final class AlmanacServiceEditController
|
|||
$form = id(new AphrontFormView())
|
||||
->setUser($viewer)
|
||||
->addHiddenInput('edit', true)
|
||||
->addHiddenInput('serviceClass', $service->getServiceClass())
|
||||
->addHiddenInput('serviceType', $service->getServiceType())
|
||||
->appendChild(
|
||||
id(new AphrontFormTextControl())
|
||||
->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();
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
|
@ -190,14 +190,14 @@ final class AlmanacServiceEditController
|
|||
}
|
||||
|
||||
list($can_cluster, $cluster_link) = $this->explainApplicationCapability(
|
||||
AlmanacCreateClusterServicesCapability::CAPABILITY,
|
||||
AlmanacManageClusterServicesCapability::CAPABILITY,
|
||||
pht('You have permission to create cluster services.'),
|
||||
pht('You do not have permission to create new cluster services.'));
|
||||
|
||||
|
||||
$type_control = id(new AphrontFormRadioButtonControl())
|
||||
->setLabel(pht('Service Type'))
|
||||
->setName('serviceClass')
|
||||
->setName('serviceType')
|
||||
->setError($e_service);
|
||||
|
||||
foreach ($service_types as $service_type) {
|
||||
|
@ -211,7 +211,7 @@ final class AlmanacServiceEditController
|
|||
}
|
||||
|
||||
$type_control->addButton(
|
||||
get_class($service_type),
|
||||
$service_type->getServiceTypeConstant(),
|
||||
$service_type->getServiceTypeName(),
|
||||
array(
|
||||
$service_type->getServiceTypeDescription(),
|
||||
|
|
|
@ -15,6 +15,7 @@ final class AlmanacServiceViewController
|
|||
$service = id(new AlmanacServiceQuery())
|
||||
->setViewer($viewer)
|
||||
->withNames(array($name))
|
||||
->needProperties(true)
|
||||
->executeOne();
|
||||
if (!$service) {
|
||||
return new Aphront404Response();
|
||||
|
@ -35,15 +36,13 @@ final class AlmanacServiceViewController
|
|||
->setHeader($header)
|
||||
->addPropertyList($property_list);
|
||||
|
||||
$messages = $service->getServiceType()->getStatusMessages($service);
|
||||
if ($messages) {
|
||||
$box->setFormErrors($messages);
|
||||
}
|
||||
|
||||
if ($service->getIsLocked()) {
|
||||
$this->addLockMessage(
|
||||
if ($service->isClusterService()) {
|
||||
$this->addClusterMessage(
|
||||
$box,
|
||||
pht('This service is locked, and can not be edited.'));
|
||||
pht('This is a cluster service.'),
|
||||
pht(
|
||||
'This service is a cluster service. You do not have permission to '.
|
||||
'edit cluster services, so you can not edit this service.'));
|
||||
}
|
||||
|
||||
$bindings = $this->buildBindingList($service);
|
||||
|
@ -77,7 +76,7 @@ final class AlmanacServiceViewController
|
|||
|
||||
$properties->addProperty(
|
||||
pht('Service Type'),
|
||||
$service->getServiceType()->getServiceTypeShortName());
|
||||
$service->getServiceImplementation()->getServiceTypeShortName());
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
@ -123,7 +122,8 @@ final class AlmanacServiceViewController
|
|||
->setNoDataString(
|
||||
pht('This service has not been bound to any device interfaces yet.'))
|
||||
->setUser($viewer)
|
||||
->setBindings($bindings);
|
||||
->setBindings($bindings)
|
||||
->setHideServiceColumn(true);
|
||||
|
||||
$header = id(new PHUIHeaderView())
|
||||
->setHeader(pht('Service Bindings'))
|
||||
|
|
|
@ -1,77 +0,0 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacCoreCustomField
|
||||
extends AlmanacCustomField
|
||||
implements PhabricatorStandardCustomFieldInterface {
|
||||
|
||||
public function getStandardCustomFieldNamespace() {
|
||||
return 'almanac:core';
|
||||
}
|
||||
|
||||
public function getFieldKey() {
|
||||
return $this->getProxy()->getRawStandardFieldKey();
|
||||
}
|
||||
|
||||
public function getFieldName() {
|
||||
return $this->getFieldKey();
|
||||
}
|
||||
|
||||
public function createFields($object) {
|
||||
|
||||
$specs = $object->getAlmanacPropertyFieldSpecifications();
|
||||
|
||||
$default_specs = array();
|
||||
foreach ($object->getAlmanacProperties() as $property) {
|
||||
$default_specs[$property->getFieldName()] = array(
|
||||
'name' => $property->getFieldName(),
|
||||
'type' => 'text',
|
||||
);
|
||||
}
|
||||
|
||||
return PhabricatorStandardCustomField::buildStandardFields(
|
||||
$this,
|
||||
$specs + $default_specs);
|
||||
}
|
||||
|
||||
public function shouldUseStorage() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function readValueFromObject(PhabricatorCustomFieldInterface $object) {
|
||||
$key = $this->getFieldKey();
|
||||
|
||||
if ($object->hasAlmanacProperty($key)) {
|
||||
$this->setValueFromStorage($object->getAlmanacPropertyValue($key));
|
||||
}
|
||||
}
|
||||
|
||||
public function applyApplicationTransactionInternalEffects(
|
||||
PhabricatorApplicationTransaction $xaction) {
|
||||
return;
|
||||
}
|
||||
|
||||
public function applyApplicationTransactionExternalEffects(
|
||||
PhabricatorApplicationTransaction $xaction) {
|
||||
|
||||
$object = $this->getObject();
|
||||
$phid = $object->getPHID();
|
||||
$key = $this->getFieldKey();
|
||||
|
||||
$property = id(new AlmanacPropertyQuery())
|
||||
->setViewer($this->getViewer())
|
||||
->withObjectPHIDs(array($phid))
|
||||
->withNames(array($key))
|
||||
->executeOne();
|
||||
if (!$property) {
|
||||
$property = id(new AlmanacProperty())
|
||||
->setObjectPHID($phid)
|
||||
->setFieldIndex(PhabricatorHash::digestForIndex($key))
|
||||
->setFieldName($key);
|
||||
}
|
||||
|
||||
$property
|
||||
->setFieldValue($xaction->getNewValue())
|
||||
->save();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
<?php
|
||||
|
||||
abstract class AlmanacCustomField
|
||||
extends PhabricatorCustomField {}
|
|
@ -1,11 +1,9 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacBindingEditor
|
||||
extends PhabricatorApplicationTransactionEditor {
|
||||
extends AlmanacEditor {
|
||||
|
||||
public function getEditorApplicationClass() {
|
||||
return 'PhabricatorAlmanacApplication';
|
||||
}
|
||||
private $devicePHID;
|
||||
|
||||
public function getEditorObjectsDescription() {
|
||||
return pht('Almanac Binding');
|
||||
|
@ -15,6 +13,7 @@ final class AlmanacBindingEditor
|
|||
$types = parent::getTransactionTypes();
|
||||
|
||||
$types[] = AlmanacBindingTransaction::TYPE_INTERFACE;
|
||||
$types[] = AlmanacBindingTransaction::TYPE_DISABLE;
|
||||
|
||||
return $types;
|
||||
}
|
||||
|
@ -25,6 +24,8 @@ final class AlmanacBindingEditor
|
|||
switch ($xaction->getTransactionType()) {
|
||||
case AlmanacBindingTransaction::TYPE_INTERFACE:
|
||||
return $object->getInterfacePHID();
|
||||
case AlmanacBindingTransaction::TYPE_DISABLE:
|
||||
return $object->getIsDisabled();
|
||||
}
|
||||
|
||||
return parent::getCustomTransactionOldValue($object, $xaction);
|
||||
|
@ -37,6 +38,8 @@ final class AlmanacBindingEditor
|
|||
switch ($xaction->getTransactionType()) {
|
||||
case AlmanacBindingTransaction::TYPE_INTERFACE:
|
||||
return $xaction->getNewValue();
|
||||
case AlmanacBindingTransaction::TYPE_DISABLE:
|
||||
return (int)$xaction->getNewValue();
|
||||
}
|
||||
|
||||
return parent::getCustomTransactionNewValue($object, $xaction);
|
||||
|
@ -55,6 +58,9 @@ final class AlmanacBindingEditor
|
|||
$object->setDevicePHID($interface->getDevicePHID());
|
||||
$object->setInterfacePHID($interface->getPHID());
|
||||
return;
|
||||
case AlmanacBindingTransaction::TYPE_DISABLE:
|
||||
$object->setIsDisabled($xaction->getNewValue());
|
||||
return;
|
||||
}
|
||||
|
||||
return parent::applyCustomInternalTransaction($object, $xaction);
|
||||
|
@ -65,7 +71,37 @@ final class AlmanacBindingEditor
|
|||
PhabricatorApplicationTransaction $xaction) {
|
||||
|
||||
switch ($xaction->getTransactionType()) {
|
||||
case AlmanacBindingTransaction::TYPE_DISABLE:
|
||||
return;
|
||||
case AlmanacBindingTransaction::TYPE_INTERFACE:
|
||||
$interface_phids = array();
|
||||
|
||||
$interface_phids[] = $xaction->getOldValue();
|
||||
$interface_phids[] = $xaction->getNewValue();
|
||||
|
||||
$interface_phids = array_filter($interface_phids);
|
||||
$interface_phids = array_unique($interface_phids);
|
||||
|
||||
$interfaces = id(new AlmanacInterfaceQuery())
|
||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||
->withPHIDs($interface_phids)
|
||||
->execute();
|
||||
|
||||
$device_phids = array();
|
||||
foreach ($interfaces as $interface) {
|
||||
$device_phids[] = $interface->getDevicePHID();
|
||||
}
|
||||
|
||||
$device_phids = array_unique($device_phids);
|
||||
|
||||
$devices = id(new AlmanacDeviceQuery())
|
||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||
->withPHIDs($device_phids)
|
||||
->execute();
|
||||
|
||||
foreach ($devices as $device) {
|
||||
$device->rebuildClusterBindingStatus();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacBindingPropertyEditEngine
|
||||
extends AlmanacPropertyEditEngine {
|
||||
|
||||
const ENGINECONST = 'almanac.binding.property';
|
||||
|
||||
protected function newObjectQuery() {
|
||||
return new AlmanacBindingQuery();
|
||||
}
|
||||
|
||||
protected function getObjectViewURI($object) {
|
||||
return $object->getURI();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,11 +1,7 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacDeviceEditor
|
||||
extends PhabricatorApplicationTransactionEditor {
|
||||
|
||||
public function getEditorApplicationClass() {
|
||||
return 'PhabricatorAlmanacApplication';
|
||||
}
|
||||
extends AlmanacEditor {
|
||||
|
||||
public function getEditorObjectsDescription() {
|
||||
return pht('Almanac Device');
|
||||
|
@ -132,7 +128,7 @@ final class AlmanacDeviceEditor
|
|||
$name = $xaction->getNewValue();
|
||||
|
||||
try {
|
||||
AlmanacNames::validateServiceOrDeviceName($name);
|
||||
AlmanacNames::validateName($name);
|
||||
} catch (Exception $ex) {
|
||||
$message = $ex->getMessage();
|
||||
}
|
||||
|
@ -144,22 +140,42 @@ final class AlmanacDeviceEditor
|
|||
$message,
|
||||
$xaction);
|
||||
$errors[] = $error;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($xactions) {
|
||||
$duplicate = id(new AlmanacDeviceQuery())
|
||||
$other = id(new AlmanacDeviceQuery())
|
||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||
->withNames(array(last($xactions)->getNewValue()))
|
||||
->withNames(array($name))
|
||||
->executeOne();
|
||||
if ($duplicate && ($duplicate->getID() != $object->getID())) {
|
||||
if ($other && ($other->getID() != $object->getID())) {
|
||||
$error = new PhabricatorApplicationTransactionValidationError(
|
||||
$type,
|
||||
pht('Not Unique'),
|
||||
pht('Almanac devices must have unique names.'),
|
||||
last($xactions));
|
||||
$xaction);
|
||||
$errors[] = $error;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($name === $object->getName()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$namespace = AlmanacNamespace::loadRestrictedNamespace(
|
||||
$this->getActor(),
|
||||
$name);
|
||||
if ($namespace) {
|
||||
$error = new PhabricatorApplicationTransactionValidationError(
|
||||
$type,
|
||||
pht('Restricted'),
|
||||
pht(
|
||||
'You do not have permission to create Almanac devices '.
|
||||
'within the "%s" namespace.',
|
||||
$namespace->getName()),
|
||||
$xaction);
|
||||
$errors[] = $error;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -294,6 +310,19 @@ final class AlmanacDeviceEditor
|
|||
pht('You can not edit an invalid or restricted interface.'),
|
||||
$xaction);
|
||||
$errors[] = $error;
|
||||
continue;
|
||||
}
|
||||
|
||||
$new = $xaction->getNewValue();
|
||||
if (!$new) {
|
||||
if ($interface->loadIsInUse()) {
|
||||
$error = new PhabricatorApplicationTransactionValidationError(
|
||||
$type,
|
||||
pht('In Use'),
|
||||
pht('You can not delete an interface which is still in use.'),
|
||||
$xaction);
|
||||
$errors[] = $error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -303,6 +332,4 @@ final class AlmanacDeviceEditor
|
|||
return $errors;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacDevicePropertyEditEngine
|
||||
extends AlmanacPropertyEditEngine {
|
||||
|
||||
const ENGINECONST = 'almanac.device.property';
|
||||
|
||||
protected function newObjectQuery() {
|
||||
return new AlmanacDeviceQuery();
|
||||
}
|
||||
|
||||
protected function getObjectViewURI($object) {
|
||||
return $object->getURI();
|
||||
}
|
||||
|
||||
}
|
156
src/applications/almanac/editor/AlmanacEditor.php
Normal file
156
src/applications/almanac/editor/AlmanacEditor.php
Normal file
|
@ -0,0 +1,156 @@
|
|||
<?php
|
||||
|
||||
abstract class AlmanacEditor
|
||||
extends PhabricatorApplicationTransactionEditor {
|
||||
|
||||
public function getEditorApplicationClass() {
|
||||
return 'PhabricatorAlmanacApplication';
|
||||
}
|
||||
|
||||
protected function supportsSearch() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getTransactionTypes() {
|
||||
$types = parent::getTransactionTypes();
|
||||
|
||||
$types[] = AlmanacTransaction::TYPE_PROPERTY_UPDATE;
|
||||
$types[] = AlmanacTransaction::TYPE_PROPERTY_REMOVE;
|
||||
|
||||
return $types;
|
||||
}
|
||||
|
||||
protected function getCustomTransactionOldValue(
|
||||
PhabricatorLiskDAO $object,
|
||||
PhabricatorApplicationTransaction $xaction) {
|
||||
switch ($xaction->getTransactionType()) {
|
||||
case AlmanacTransaction::TYPE_PROPERTY_UPDATE:
|
||||
case AlmanacTransaction::TYPE_PROPERTY_REMOVE:
|
||||
$property_key = $xaction->getMetadataValue('almanac.property');
|
||||
$exists = $object->hasAlmanacProperty($property_key);
|
||||
$value = $object->getAlmanacPropertyValue($property_key);
|
||||
return array(
|
||||
'existed' => $exists,
|
||||
'value' => $value,
|
||||
);
|
||||
}
|
||||
|
||||
return parent::getCustomTransactionOldValue($object, $xaction);
|
||||
}
|
||||
|
||||
protected function getCustomTransactionNewValue(
|
||||
PhabricatorLiskDAO $object,
|
||||
PhabricatorApplicationTransaction $xaction) {
|
||||
|
||||
switch ($xaction->getTransactionType()) {
|
||||
case AlmanacTransaction::TYPE_PROPERTY_UPDATE:
|
||||
case AlmanacTransaction::TYPE_PROPERTY_REMOVE:
|
||||
return $xaction->getNewValue();
|
||||
}
|
||||
|
||||
return parent::getCustomTransactionNewValue($object, $xaction);
|
||||
}
|
||||
|
||||
protected function applyCustomInternalTransaction(
|
||||
PhabricatorLiskDAO $object,
|
||||
PhabricatorApplicationTransaction $xaction) {
|
||||
|
||||
switch ($xaction->getTransactionType()) {
|
||||
case AlmanacTransaction::TYPE_PROPERTY_UPDATE:
|
||||
case AlmanacTransaction::TYPE_PROPERTY_REMOVE:
|
||||
return;
|
||||
}
|
||||
|
||||
return parent::applyCustomInternalTransaction($object, $xaction);
|
||||
}
|
||||
|
||||
protected function applyCustomExternalTransaction(
|
||||
PhabricatorLiskDAO $object,
|
||||
PhabricatorApplicationTransaction $xaction) {
|
||||
|
||||
switch ($xaction->getTransactionType()) {
|
||||
case AlmanacTransaction::TYPE_PROPERTY_UPDATE:
|
||||
$property_key = $xaction->getMetadataValue('almanac.property');
|
||||
if ($object->hasAlmanacProperty($property_key)) {
|
||||
$property = $object->getAlmanacProperty($property_key);
|
||||
} else {
|
||||
$property = id(new AlmanacProperty())
|
||||
->setObjectPHID($object->getPHID())
|
||||
->setFieldName($property_key);
|
||||
}
|
||||
$property
|
||||
->setFieldValue($xaction->getNewValue())
|
||||
->save();
|
||||
return;
|
||||
case AlmanacTransaction::TYPE_PROPERTY_REMOVE:
|
||||
$property_key = $xaction->getMetadataValue('almanac.property');
|
||||
if ($object->hasAlmanacProperty($property_key)) {
|
||||
$property = $object->getAlmanacProperty($property_key);
|
||||
$property->delete();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
return parent::applyCustomExternalTransaction($object, $xaction);
|
||||
}
|
||||
|
||||
protected function validateTransaction(
|
||||
PhabricatorLiskDAO $object,
|
||||
$type,
|
||||
array $xactions) {
|
||||
|
||||
$errors = parent::validateTransaction($object, $type, $xactions);
|
||||
|
||||
switch ($type) {
|
||||
case AlmanacTransaction::TYPE_PROPERTY_UPDATE:
|
||||
foreach ($xactions as $xaction) {
|
||||
$property_key = $xaction->getMetadataValue('almanac.property');
|
||||
|
||||
$message = null;
|
||||
try {
|
||||
AlmanacNames::validateName($property_key);
|
||||
} catch (Exception $ex) {
|
||||
$message = $ex->getMessage();
|
||||
}
|
||||
|
||||
if ($message !== null) {
|
||||
$error = new PhabricatorApplicationTransactionValidationError(
|
||||
$type,
|
||||
pht('Invalid'),
|
||||
$message,
|
||||
$xaction);
|
||||
$errors[] = $error;
|
||||
continue;
|
||||
}
|
||||
|
||||
$new_value = $xaction->getNewValue();
|
||||
try {
|
||||
phutil_json_encode($new_value);
|
||||
} catch (Exception $ex) {
|
||||
$message = pht(
|
||||
'Almanac property values must be representable in JSON. %s',
|
||||
$ex->getMessage());
|
||||
}
|
||||
|
||||
if ($message !== null) {
|
||||
$error = new PhabricatorApplicationTransactionValidationError(
|
||||
$type,
|
||||
pht('Invalid'),
|
||||
$message,
|
||||
$xaction);
|
||||
$errors[] = $error;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AlmanacTransaction::TYPE_PROPERTY_REMOVE:
|
||||
// NOTE: No name validation on removals since it's OK to delete
|
||||
// an invalid property that somehow came into existence.
|
||||
break;
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacNamespaceEditEngine
|
||||
extends PhabricatorEditEngine {
|
||||
|
||||
const ENGINECONST = 'almanac.namespace';
|
||||
|
||||
public function isEngineConfigurable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getEngineName() {
|
||||
return pht('Almanac Namespaces');
|
||||
}
|
||||
|
||||
public function getSummaryHeader() {
|
||||
return pht('Edit Almanac Namespace Configurations');
|
||||
}
|
||||
|
||||
public function getSummaryText() {
|
||||
return pht('This engine is used to edit Almanac namespaces.');
|
||||
}
|
||||
|
||||
public function getEngineApplicationClass() {
|
||||
return 'PhabricatorAlmanacApplication';
|
||||
}
|
||||
|
||||
protected function newEditableObject() {
|
||||
return AlmanacNamespace::initializeNewNamespace();
|
||||
}
|
||||
|
||||
protected function newObjectQuery() {
|
||||
return new AlmanacNamespaceQuery();
|
||||
}
|
||||
|
||||
protected function getObjectCreateTitleText($object) {
|
||||
return pht('Create Namespace');
|
||||
}
|
||||
|
||||
protected function getObjectCreateButtonText($object) {
|
||||
return pht('Create Namespace');
|
||||
}
|
||||
|
||||
protected function getObjectEditTitleText($object) {
|
||||
return pht('Edit Namespace: %s', $object->getName());
|
||||
}
|
||||
|
||||
protected function getObjectEditShortText($object) {
|
||||
return pht('Edit Namespace');
|
||||
}
|
||||
|
||||
protected function getObjectCreateShortText() {
|
||||
return pht('Create Namespace');
|
||||
}
|
||||
|
||||
protected function getEditorURI() {
|
||||
return '/almanac/namespace/edit/';
|
||||
}
|
||||
|
||||
protected function getObjectCreateCancelURI($object) {
|
||||
return '/almanac/namespace/';
|
||||
}
|
||||
|
||||
protected function getObjectViewURI($object) {
|
||||
$id = $object->getID();
|
||||
return "/almanac/namespace/{$id}/";
|
||||
}
|
||||
|
||||
protected function getCreateNewObjectPolicy() {
|
||||
return $this->getApplication()->getPolicy(
|
||||
AlmanacCreateNamespacesCapability::CAPABILITY);
|
||||
}
|
||||
|
||||
protected function buildCustomEditFields($object) {
|
||||
return array(
|
||||
id(new PhabricatorTextEditField())
|
||||
->setKey('name')
|
||||
->setLabel(pht('Name'))
|
||||
->setDescription(pht('Name of the namespace.'))
|
||||
->setTransactionType(AlmanacNamespaceTransaction::TYPE_NAME)
|
||||
->setIsRequired(true)
|
||||
->setValue($object->getName()),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
182
src/applications/almanac/editor/AlmanacNamespaceEditor.php
Normal file
182
src/applications/almanac/editor/AlmanacNamespaceEditor.php
Normal file
|
@ -0,0 +1,182 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacNamespaceEditor
|
||||
extends PhabricatorApplicationTransactionEditor {
|
||||
|
||||
public function getEditorApplicationClass() {
|
||||
return 'PhabricatorAlmanacApplication';
|
||||
}
|
||||
|
||||
public function getEditorObjectsDescription() {
|
||||
return pht('Almanac Namespace');
|
||||
}
|
||||
|
||||
protected function supportsSearch() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getTransactionTypes() {
|
||||
$types = parent::getTransactionTypes();
|
||||
|
||||
$types[] = AlmanacNamespaceTransaction::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 AlmanacNamespaceTransaction::TYPE_NAME:
|
||||
return $object->getName();
|
||||
}
|
||||
|
||||
return parent::getCustomTransactionOldValue($object, $xaction);
|
||||
}
|
||||
|
||||
protected function getCustomTransactionNewValue(
|
||||
PhabricatorLiskDAO $object,
|
||||
PhabricatorApplicationTransaction $xaction) {
|
||||
|
||||
switch ($xaction->getTransactionType()) {
|
||||
case AlmanacNamespaceTransaction::TYPE_NAME:
|
||||
return $xaction->getNewValue();
|
||||
}
|
||||
|
||||
return parent::getCustomTransactionNewValue($object, $xaction);
|
||||
}
|
||||
|
||||
protected function applyCustomInternalTransaction(
|
||||
PhabricatorLiskDAO $object,
|
||||
PhabricatorApplicationTransaction $xaction) {
|
||||
|
||||
switch ($xaction->getTransactionType()) {
|
||||
case AlmanacNamespaceTransaction::TYPE_NAME:
|
||||
$object->setName($xaction->getNewValue());
|
||||
return;
|
||||
}
|
||||
|
||||
return parent::applyCustomInternalTransaction($object, $xaction);
|
||||
}
|
||||
|
||||
protected function applyCustomExternalTransaction(
|
||||
PhabricatorLiskDAO $object,
|
||||
PhabricatorApplicationTransaction $xaction) {
|
||||
|
||||
switch ($xaction->getTransactionType()) {
|
||||
case AlmanacNamespaceTransaction::TYPE_NAME:
|
||||
return;
|
||||
}
|
||||
|
||||
return parent::applyCustomExternalTransaction($object, $xaction);
|
||||
}
|
||||
|
||||
protected function validateTransaction(
|
||||
PhabricatorLiskDAO $object,
|
||||
$type,
|
||||
array $xactions) {
|
||||
|
||||
$errors = parent::validateTransaction($object, $type, $xactions);
|
||||
|
||||
switch ($type) {
|
||||
case AlmanacNamespaceTransaction::TYPE_NAME:
|
||||
$missing = $this->validateIsEmptyTextField(
|
||||
$object->getName(),
|
||||
$xactions);
|
||||
|
||||
if ($missing) {
|
||||
$error = new PhabricatorApplicationTransactionValidationError(
|
||||
$type,
|
||||
pht('Required'),
|
||||
pht('Namespace name is required.'),
|
||||
nonempty(last($xactions), null));
|
||||
|
||||
$error->setIsMissingFieldError(true);
|
||||
$errors[] = $error;
|
||||
} else {
|
||||
foreach ($xactions as $xaction) {
|
||||
$name = $xaction->getNewValue();
|
||||
|
||||
$message = null;
|
||||
try {
|
||||
AlmanacNames::validateName($name);
|
||||
} catch (Exception $ex) {
|
||||
$message = $ex->getMessage();
|
||||
}
|
||||
|
||||
if ($message !== null) {
|
||||
$error = new PhabricatorApplicationTransactionValidationError(
|
||||
$type,
|
||||
pht('Invalid'),
|
||||
$message,
|
||||
$xaction);
|
||||
$errors[] = $error;
|
||||
continue;
|
||||
}
|
||||
|
||||
$other = id(new AlmanacNamespaceQuery())
|
||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||
->withNames(array($name))
|
||||
->executeOne();
|
||||
if ($other && ($other->getID() != $object->getID())) {
|
||||
$error = new PhabricatorApplicationTransactionValidationError(
|
||||
$type,
|
||||
pht('Not Unique'),
|
||||
pht(
|
||||
'The namespace name "%s" is already in use by another '.
|
||||
'namespace. Each namespace must have a unique name.',
|
||||
$name),
|
||||
$xaction);
|
||||
$errors[] = $error;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($name === $object->getName()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$namespace = AlmanacNamespace::loadRestrictedNamespace(
|
||||
$this->getActor(),
|
||||
$name);
|
||||
if ($namespace) {
|
||||
$error = new PhabricatorApplicationTransactionValidationError(
|
||||
$type,
|
||||
pht('Restricted'),
|
||||
pht(
|
||||
'You do not have permission to create Almanac namespaces '.
|
||||
'within the "%s" namespace.',
|
||||
$namespace->getName()),
|
||||
$xaction);
|
||||
$errors[] = $error;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
protected function didCatchDuplicateKeyException(
|
||||
PhabricatorLiskDAO $object,
|
||||
array $xactions,
|
||||
Exception $ex) {
|
||||
|
||||
$errors = array();
|
||||
|
||||
$errors[] = new PhabricatorApplicationTransactionValidationError(
|
||||
null,
|
||||
pht('Invalid'),
|
||||
pht(
|
||||
'Another namespace with this name already exists. Each namespace '.
|
||||
'must have a unique name.'),
|
||||
null);
|
||||
|
||||
throw new PhabricatorApplicationTransactionValidationException($errors);
|
||||
}
|
||||
|
||||
}
|
86
src/applications/almanac/editor/AlmanacNetworkEditEngine.php
Normal file
86
src/applications/almanac/editor/AlmanacNetworkEditEngine.php
Normal file
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacNetworkEditEngine
|
||||
extends PhabricatorEditEngine {
|
||||
|
||||
const ENGINECONST = 'almanac.network';
|
||||
|
||||
public function isEngineConfigurable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getEngineName() {
|
||||
return pht('Almanac Networks');
|
||||
}
|
||||
|
||||
public function getSummaryHeader() {
|
||||
return pht('Edit Almanac Network Configurations');
|
||||
}
|
||||
|
||||
public function getSummaryText() {
|
||||
return pht('This engine is used to edit Almanac networks.');
|
||||
}
|
||||
|
||||
public function getEngineApplicationClass() {
|
||||
return 'PhabricatorAlmanacApplication';
|
||||
}
|
||||
|
||||
protected function newEditableObject() {
|
||||
return AlmanacNetwork::initializeNewNetwork();
|
||||
}
|
||||
|
||||
protected function newObjectQuery() {
|
||||
return new AlmanacNetworkQuery();
|
||||
}
|
||||
|
||||
protected function getObjectCreateTitleText($object) {
|
||||
return pht('Create Network');
|
||||
}
|
||||
|
||||
protected function getObjectCreateButtonText($object) {
|
||||
return pht('Create Network');
|
||||
}
|
||||
|
||||
protected function getObjectEditTitleText($object) {
|
||||
return pht('Edit Network: %s', $object->getName());
|
||||
}
|
||||
|
||||
protected function getObjectEditShortText($object) {
|
||||
return pht('Edit Network');
|
||||
}
|
||||
|
||||
protected function getObjectCreateShortText() {
|
||||
return pht('Create Network');
|
||||
}
|
||||
|
||||
protected function getEditorURI() {
|
||||
return '/almanac/network/edit/';
|
||||
}
|
||||
|
||||
protected function getObjectCreateCancelURI($object) {
|
||||
return '/almanac/network/';
|
||||
}
|
||||
|
||||
protected function getObjectViewURI($object) {
|
||||
$id = $object->getID();
|
||||
return "/almanac/network/{$id}/";
|
||||
}
|
||||
|
||||
protected function getCreateNewObjectPolicy() {
|
||||
return $this->getApplication()->getPolicy(
|
||||
AlmanacCreateNetworksCapability::CAPABILITY);
|
||||
}
|
||||
|
||||
protected function buildCustomEditFields($object) {
|
||||
return array(
|
||||
id(new PhabricatorTextEditField())
|
||||
->setKey('name')
|
||||
->setLabel(pht('Name'))
|
||||
->setDescription(pht('Name of the network.'))
|
||||
->setTransactionType(AlmanacNetworkTransaction::TYPE_NAME)
|
||||
->setIsRequired(true)
|
||||
->setValue($object->getName()),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -11,6 +11,10 @@ final class AlmanacNetworkEditor
|
|||
return pht('Almanac Network');
|
||||
}
|
||||
|
||||
protected function supportsSearch() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getTransactionTypes() {
|
||||
$types = parent::getTransactionTypes();
|
||||
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
abstract class AlmanacPropertyEditEngine
|
||||
extends PhabricatorEditEngine {
|
||||
|
||||
private $propertyKey;
|
||||
|
||||
public function setPropertyKey($property_key) {
|
||||
$this->propertyKey = $property_key;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPropertyKey() {
|
||||
return $this->propertyKey;
|
||||
}
|
||||
|
||||
public function isEngineConfigurable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isEngineExtensible() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getEngineName() {
|
||||
return pht('Almanac Properties');
|
||||
}
|
||||
|
||||
public function getSummaryHeader() {
|
||||
return pht('Edit Almanac Property Configurations');
|
||||
}
|
||||
|
||||
public function getSummaryText() {
|
||||
return pht('This engine is used to edit Almanac properties.');
|
||||
}
|
||||
|
||||
public function getEngineApplicationClass() {
|
||||
return 'PhabricatorAlmanacApplication';
|
||||
}
|
||||
|
||||
protected function newEditableObject() {
|
||||
throw new PhutilMethodNotImplementedException();
|
||||
}
|
||||
|
||||
protected function getObjectCreateTitleText($object) {
|
||||
return pht('Create Property');
|
||||
}
|
||||
|
||||
protected function getObjectCreateButtonText($object) {
|
||||
return pht('Create Property');
|
||||
}
|
||||
|
||||
protected function getObjectEditTitleText($object) {
|
||||
return pht('Edit Property: %s', $object->getName());
|
||||
}
|
||||
|
||||
protected function getObjectEditShortText($object) {
|
||||
return pht('Edit Property');
|
||||
}
|
||||
|
||||
protected function getObjectCreateShortText() {
|
||||
return pht('Create Property');
|
||||
}
|
||||
|
||||
protected function buildCustomEditFields($object) {
|
||||
$property_key = $this->getPropertyKey();
|
||||
$xaction_type = AlmanacTransaction::TYPE_PROPERTY_UPDATE;
|
||||
|
||||
return array(
|
||||
id(new PhabricatorTextEditField())
|
||||
->setKey('value')
|
||||
->setMetadataValue('almanac.property', $property_key)
|
||||
->setLabel($property_key)
|
||||
->setTransactionType($xaction_type)
|
||||
->setValue($object->getAlmanacPropertyValue($property_key)),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,11 +1,7 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacServiceEditor
|
||||
extends PhabricatorApplicationTransactionEditor {
|
||||
|
||||
public function getEditorApplicationClass() {
|
||||
return 'PhabricatorAlmanacApplication';
|
||||
}
|
||||
extends AlmanacEditor {
|
||||
|
||||
public function getEditorObjectsDescription() {
|
||||
return pht('Almanac Service');
|
||||
|
@ -15,7 +11,6 @@ final class AlmanacServiceEditor
|
|||
$types = parent::getTransactionTypes();
|
||||
|
||||
$types[] = AlmanacServiceTransaction::TYPE_NAME;
|
||||
$types[] = AlmanacServiceTransaction::TYPE_LOCK;
|
||||
|
||||
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
|
||||
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
|
||||
|
@ -29,8 +24,6 @@ final class AlmanacServiceEditor
|
|||
switch ($xaction->getTransactionType()) {
|
||||
case AlmanacServiceTransaction::TYPE_NAME:
|
||||
return $object->getName();
|
||||
case AlmanacServiceTransaction::TYPE_LOCK:
|
||||
return (bool)$object->getIsLocked();
|
||||
}
|
||||
|
||||
return parent::getCustomTransactionOldValue($object, $xaction);
|
||||
|
@ -43,8 +36,6 @@ final class AlmanacServiceEditor
|
|||
switch ($xaction->getTransactionType()) {
|
||||
case AlmanacServiceTransaction::TYPE_NAME:
|
||||
return $xaction->getNewValue();
|
||||
case AlmanacServiceTransaction::TYPE_LOCK:
|
||||
return (bool)$xaction->getNewValue();
|
||||
}
|
||||
|
||||
return parent::getCustomTransactionNewValue($object, $xaction);
|
||||
|
@ -58,9 +49,6 @@ final class AlmanacServiceEditor
|
|||
case AlmanacServiceTransaction::TYPE_NAME:
|
||||
$object->setName($xaction->getNewValue());
|
||||
return;
|
||||
case AlmanacServiceTransaction::TYPE_LOCK:
|
||||
$object->setIsLocked((int)$xaction->getNewValue());
|
||||
return;
|
||||
}
|
||||
|
||||
return parent::applyCustomInternalTransaction($object, $xaction);
|
||||
|
@ -73,23 +61,6 @@ final class AlmanacServiceEditor
|
|||
switch ($xaction->getTransactionType()) {
|
||||
case AlmanacServiceTransaction::TYPE_NAME:
|
||||
return;
|
||||
case AlmanacServiceTransaction::TYPE_LOCK:
|
||||
$service = id(new AlmanacServiceQuery())
|
||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||
->withPHIDs(array($object->getPHID()))
|
||||
->needBindings(true)
|
||||
->executeOne();
|
||||
|
||||
$devices = array();
|
||||
foreach ($service->getBindings() as $binding) {
|
||||
$device = $binding->getInterface()->getDevice();
|
||||
$devices[$device->getPHID()] = $device;
|
||||
}
|
||||
|
||||
foreach ($devices as $device) {
|
||||
$device->rebuildDeviceLocks();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
return parent::applyCustomExternalTransaction($object, $xaction);
|
||||
|
@ -124,7 +95,7 @@ final class AlmanacServiceEditor
|
|||
$name = $xaction->getNewValue();
|
||||
|
||||
try {
|
||||
AlmanacNames::validateServiceOrDeviceName($name);
|
||||
AlmanacNames::validateName($name);
|
||||
} catch (Exception $ex) {
|
||||
$message = $ex->getMessage();
|
||||
}
|
||||
|
@ -136,22 +107,42 @@ final class AlmanacServiceEditor
|
|||
$message,
|
||||
$xaction);
|
||||
$errors[] = $error;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($xactions) {
|
||||
$duplicate = id(new AlmanacServiceQuery())
|
||||
$other = id(new AlmanacServiceQuery())
|
||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||
->withNames(array(last($xactions)->getNewValue()))
|
||||
->withNames(array($name))
|
||||
->executeOne();
|
||||
if ($duplicate && ($duplicate->getID() != $object->getID())) {
|
||||
if ($other && ($other->getID() != $object->getID())) {
|
||||
$error = new PhabricatorApplicationTransactionValidationError(
|
||||
$type,
|
||||
pht('Not Unique'),
|
||||
pht('Almanac services must have unique names.'),
|
||||
last($xactions));
|
||||
$errors[] = $error;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($name === $object->getName()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$namespace = AlmanacNamespace::loadRestrictedNamespace(
|
||||
$this->getActor(),
|
||||
$name);
|
||||
if ($namespace) {
|
||||
$error = new PhabricatorApplicationTransactionValidationError(
|
||||
$type,
|
||||
pht('Restricted'),
|
||||
pht(
|
||||
'You do not have permission to create Almanac services '.
|
||||
'within the "%s" namespace.',
|
||||
$namespace->getName()),
|
||||
$xaction);
|
||||
$errors[] = $error;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -161,6 +152,4 @@ final class AlmanacServiceEditor
|
|||
return $errors;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacServicePropertyEditEngine
|
||||
extends AlmanacPropertyEditEngine {
|
||||
|
||||
const ENGINECONST = 'almanac.service.property';
|
||||
|
||||
protected function newObjectQuery() {
|
||||
return new AlmanacServiceQuery();
|
||||
}
|
||||
|
||||
protected function getObjectViewURI($object) {
|
||||
return $object->getURI();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacBindingsSearchEngineAttachment
|
||||
extends AlmanacSearchEngineAttachment {
|
||||
|
||||
public function getAttachmentName() {
|
||||
return pht('Almanac Bindings');
|
||||
}
|
||||
|
||||
public function getAttachmentDescription() {
|
||||
return pht('Get Almanac bindings for the service.');
|
||||
}
|
||||
|
||||
public function willLoadAttachmentData($query, $spec) {
|
||||
$query->needProperties(true);
|
||||
$query->needBindings(true);
|
||||
}
|
||||
|
||||
public function getAttachmentForObject($object, $data, $spec) {
|
||||
$bindings = array();
|
||||
foreach ($object->getBindings() as $binding) {
|
||||
$bindings[] = $this->getAlmanacBindingDictionary($binding);
|
||||
}
|
||||
|
||||
return array(
|
||||
'bindings' => $bindings,
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacPropertiesSearchEngineAttachment
|
||||
extends AlmanacSearchEngineAttachment {
|
||||
|
||||
public function getAttachmentName() {
|
||||
return pht('Almanac Properties');
|
||||
}
|
||||
|
||||
public function getAttachmentDescription() {
|
||||
return pht('Get Almanac properties for the object.');
|
||||
}
|
||||
|
||||
public function willLoadAttachmentData($query, $spec) {
|
||||
$query->needProperties(true);
|
||||
}
|
||||
|
||||
public function getAttachmentForObject($object, $data, $spec) {
|
||||
$properties = $this->getAlmanacPropertyList($object);
|
||||
|
||||
return array(
|
||||
'properties' => $properties,
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
|
||||
abstract class AlmanacSearchEngineAttachment
|
||||
extends PhabricatorSearchEngineAttachment {
|
||||
|
||||
protected function getAlmanacPropertyList($object) {
|
||||
$builtins = $object->getAlmanacPropertyFieldSpecifications();
|
||||
|
||||
$properties = array();
|
||||
foreach ($object->getAlmanacProperties() as $key => $property) {
|
||||
$is_builtin = isset($builtins[$key]);
|
||||
|
||||
$properties[] = array(
|
||||
'key' => $key,
|
||||
'value' => $property->getFieldValue(),
|
||||
'builtin' => $is_builtin,
|
||||
);
|
||||
}
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
protected function getAlmanacBindingDictionary(AlmanacBinding $binding) {
|
||||
$interface = $binding->getInterface();
|
||||
|
||||
return array(
|
||||
'id' => (int)$binding->getID(),
|
||||
'phid' => $binding->getPHID(),
|
||||
'properties' => $this->getAlmanacPropertyList($binding),
|
||||
'interface' => $this->getAlmanacInterfaceDictionary($interface),
|
||||
'disabled' => (bool)$binding->getIsDisabled(),
|
||||
);
|
||||
}
|
||||
|
||||
protected function getAlmanacInterfaceDictionary(
|
||||
AlmanacInterface $interface) {
|
||||
|
||||
return array(
|
||||
'id' => (int)$interface->getID(),
|
||||
'phid' => $interface->getPHID(),
|
||||
'address' => $interface->getAddress(),
|
||||
'port' => (int)$interface->getPort(),
|
||||
'device' => $this->getAlmanacDeviceDictionary($interface->getDevice()),
|
||||
'network' => $this->getAlmanacNetworkDictionary($interface->getNetwork()),
|
||||
);
|
||||
}
|
||||
|
||||
protected function getAlmanacDeviceDictionary(AlmanacDevice $device) {
|
||||
return array(
|
||||
'id' => (int)$device->getID(),
|
||||
'phid' => $device->getPHID(),
|
||||
'name' => $device->getName(),
|
||||
'properties' => $this->getAlmanacPropertyList($device),
|
||||
);
|
||||
}
|
||||
|
||||
protected function getAlmanacNetworkDictionary(AlmanacNetwork $network) {
|
||||
return array(
|
||||
'id' => (int)$network->getID(),
|
||||
'phid' => $network->getPHID(),
|
||||
'name' => $network->getName(),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacManagementLockWorkflow
|
||||
extends AlmanacManagementWorkflow {
|
||||
|
||||
protected function didConstruct() {
|
||||
$this
|
||||
->setName('lock')
|
||||
->setSynopsis(pht('Lock a service to prevent it from being edited.'))
|
||||
->setArguments(
|
||||
array(
|
||||
array(
|
||||
'name' => 'services',
|
||||
'wildcard' => true,
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
public function execute(PhutilArgumentParser $args) {
|
||||
$console = PhutilConsole::getConsole();
|
||||
|
||||
$services = $this->loadServices($args->getArg('services'));
|
||||
if (!$services) {
|
||||
throw new PhutilArgumentUsageException(
|
||||
pht('Specify at least one service to lock.'));
|
||||
}
|
||||
|
||||
foreach ($services as $service) {
|
||||
if ($service->getIsLocked()) {
|
||||
throw new PhutilArgumentUsageException(
|
||||
pht(
|
||||
'Service "%s" is already locked!',
|
||||
$service->getName()));
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($services as $service) {
|
||||
$this->updateServiceLock($service, true);
|
||||
|
||||
$console->writeOut(
|
||||
"**<bg:green> %s </bg>** %s\n",
|
||||
pht('LOCKED'),
|
||||
pht('Service "%s" was locked.', $service->getName()));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacManagementUnlockWorkflow
|
||||
extends AlmanacManagementWorkflow {
|
||||
|
||||
protected function didConstruct() {
|
||||
$this
|
||||
->setName('unlock')
|
||||
->setSynopsis(pht('Unlock a service to allow it to be edited.'))
|
||||
->setArguments(
|
||||
array(
|
||||
array(
|
||||
'name' => 'services',
|
||||
'wildcard' => true,
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
public function execute(PhutilArgumentParser $args) {
|
||||
$console = PhutilConsole::getConsole();
|
||||
|
||||
$services = $this->loadServices($args->getArg('services'));
|
||||
if (!$services) {
|
||||
throw new PhutilArgumentUsageException(
|
||||
pht('Specify at least one service to unlock.'));
|
||||
}
|
||||
|
||||
foreach ($services as $service) {
|
||||
if (!$service->getIsLocked()) {
|
||||
throw new PhutilArgumentUsageException(
|
||||
pht(
|
||||
'Service "%s" is not locked!',
|
||||
$service->getName()));
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($services as $service) {
|
||||
$this->updateServiceLock($service, false);
|
||||
|
||||
$console->writeOut(
|
||||
"**<bg:green> %s </bg>** %s\n",
|
||||
pht('UNLOCKED'),
|
||||
pht('Service "%s" was unlocked.', $service->getName()));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
44
src/applications/almanac/phid/AlmanacNamespacePHIDType.php
Normal file
44
src/applications/almanac/phid/AlmanacNamespacePHIDType.php
Normal file
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacNamespacePHIDType extends PhabricatorPHIDType {
|
||||
|
||||
const TYPECONST = 'ANAM';
|
||||
|
||||
public function getTypeName() {
|
||||
return pht('Almanac Namespace');
|
||||
}
|
||||
|
||||
public function newObject() {
|
||||
return new AlmanacNamespace();
|
||||
}
|
||||
|
||||
public function getPHIDTypeApplicationClass() {
|
||||
return 'PhabricatorAlmanacApplication';
|
||||
}
|
||||
|
||||
protected function buildQueryForObjects(
|
||||
PhabricatorObjectQuery $query,
|
||||
array $phids) {
|
||||
|
||||
return id(new AlmanacNamespaceQuery())
|
||||
->withPHIDs($phids);
|
||||
}
|
||||
|
||||
public function loadHandles(
|
||||
PhabricatorHandleQuery $query,
|
||||
array $handles,
|
||||
array $objects) {
|
||||
|
||||
foreach ($handles as $phid => $handle) {
|
||||
$namespace = $objects[$phid];
|
||||
|
||||
$id = $namespace->getID();
|
||||
$name = $namespace->getName();
|
||||
|
||||
$handle->setObjectName(pht('Namespace %d', $id));
|
||||
$handle->setName($name);
|
||||
$handle->setURI($namespace->getURI());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -8,5 +8,6 @@ interface AlmanacPropertyInterface {
|
|||
public function getAlmanacProperty($key);
|
||||
public function getAlmanacPropertyValue($key, $default = null);
|
||||
public function getAlmanacPropertyFieldSpecifications();
|
||||
public function newAlmanacPropertyEditEngine();
|
||||
|
||||
}
|
||||
|
|
|
@ -34,19 +34,12 @@ final class AlmanacBindingQuery
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function newResultObject() {
|
||||
return new AlmanacBinding();
|
||||
}
|
||||
|
||||
protected function loadPage() {
|
||||
$table = new AlmanacBinding();
|
||||
$conn_r = $table->establishConnection('r');
|
||||
|
||||
$data = queryfx_all(
|
||||
$conn_r,
|
||||
'SELECT * FROM %T %Q %Q %Q',
|
||||
$table->getTableName(),
|
||||
$this->buildWhereClause($conn_r),
|
||||
$this->buildOrderClause($conn_r),
|
||||
$this->buildLimitClause($conn_r));
|
||||
|
||||
return $table->loadAllFromArray($data);
|
||||
return $this->loadStandardPage($this->newResultObject());
|
||||
}
|
||||
|
||||
protected function willFilterPage(array $bindings) {
|
||||
|
@ -58,6 +51,7 @@ final class AlmanacBindingQuery
|
|||
->setParentQuery($this)
|
||||
->setViewer($this->getViewer())
|
||||
->withPHIDs($service_phids)
|
||||
->needProperties($this->getNeedProperties())
|
||||
->execute();
|
||||
$services = mpull($services, null, 'getPHID');
|
||||
|
||||
|
@ -65,6 +59,7 @@ final class AlmanacBindingQuery
|
|||
->setParentQuery($this)
|
||||
->setViewer($this->getViewer())
|
||||
->withPHIDs($device_phids)
|
||||
->needProperties($this->getNeedProperties())
|
||||
->execute();
|
||||
$devices = mpull($devices, null, 'getPHID');
|
||||
|
||||
|
@ -72,6 +67,7 @@ final class AlmanacBindingQuery
|
|||
->setParentQuery($this)
|
||||
->setViewer($this->getViewer())
|
||||
->withPHIDs($interface_phids)
|
||||
->needProperties($this->getNeedProperties())
|
||||
->execute();
|
||||
$interfaces = mpull($interfaces, null, 'getPHID');
|
||||
|
||||
|
@ -93,47 +89,45 @@ final class AlmanacBindingQuery
|
|||
return $bindings;
|
||||
}
|
||||
|
||||
protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
|
||||
$where = array();
|
||||
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
|
||||
$where = parent::buildWhereClauseParts($conn);
|
||||
|
||||
if ($this->ids !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
$conn,
|
||||
'id IN (%Ld)',
|
||||
$this->ids);
|
||||
}
|
||||
|
||||
if ($this->phids !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
$conn,
|
||||
'phid IN (%Ls)',
|
||||
$this->phids);
|
||||
}
|
||||
|
||||
if ($this->servicePHIDs !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
$conn,
|
||||
'servicePHID IN (%Ls)',
|
||||
$this->servicePHIDs);
|
||||
}
|
||||
|
||||
if ($this->devicePHIDs !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
$conn,
|
||||
'devicePHID IN (%Ls)',
|
||||
$this->devicePHIDs);
|
||||
}
|
||||
|
||||
if ($this->interfacePHIDs !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
$conn,
|
||||
'interfacePHID IN (%Ls)',
|
||||
$this->interfacePHIDs);
|
||||
}
|
||||
|
||||
$where[] = $this->buildPagingClause($conn_r);
|
||||
|
||||
return $this->formatWhereClause($where);
|
||||
return $where;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -34,35 +34,34 @@ final class AlmanacDeviceQuery
|
|||
return $this;
|
||||
}
|
||||
|
||||
protected function loadPage() {
|
||||
$table = new AlmanacDevice();
|
||||
$conn_r = $table->establishConnection('r');
|
||||
|
||||
$data = queryfx_all(
|
||||
$conn_r,
|
||||
'SELECT * FROM %T %Q %Q %Q',
|
||||
$table->getTableName(),
|
||||
$this->buildWhereClause($conn_r),
|
||||
$this->buildOrderClause($conn_r),
|
||||
$this->buildLimitClause($conn_r));
|
||||
|
||||
return $table->loadAllFromArray($data);
|
||||
public function withNameNgrams($ngrams) {
|
||||
return $this->withNgramsConstraint(
|
||||
new AlmanacDeviceNameNgrams(),
|
||||
$ngrams);
|
||||
}
|
||||
|
||||
protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
|
||||
$where = array();
|
||||
public function newResultObject() {
|
||||
return new AlmanacDevice();
|
||||
}
|
||||
|
||||
protected function loadPage() {
|
||||
return $this->loadStandardPage($this->newResultObject());
|
||||
}
|
||||
|
||||
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
|
||||
$where = parent::buildWhereClauseParts($conn);
|
||||
|
||||
if ($this->ids !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'id IN (%Ld)',
|
||||
$conn,
|
||||
'device.id IN (%Ld)',
|
||||
$this->ids);
|
||||
}
|
||||
|
||||
if ($this->phids !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'phid IN (%Ls)',
|
||||
$conn,
|
||||
'device.phid IN (%Ls)',
|
||||
$this->phids);
|
||||
}
|
||||
|
||||
|
@ -72,28 +71,59 @@ final class AlmanacDeviceQuery
|
|||
$hashes[] = PhabricatorHash::digestForIndex($name);
|
||||
}
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'nameIndex IN (%Ls)',
|
||||
$conn,
|
||||
'device.nameIndex IN (%Ls)',
|
||||
$hashes);
|
||||
}
|
||||
|
||||
if ($this->namePrefix !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'name LIKE %>',
|
||||
$conn,
|
||||
'device.name LIKE %>',
|
||||
$this->namePrefix);
|
||||
}
|
||||
|
||||
if ($this->nameSuffix !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'name LIKE %<',
|
||||
$conn,
|
||||
'device.name LIKE %<',
|
||||
$this->nameSuffix);
|
||||
}
|
||||
|
||||
$where[] = $this->buildPagingClause($conn_r);
|
||||
return $where;
|
||||
}
|
||||
|
||||
return $this->formatWhereClause($where);
|
||||
protected function getPrimaryTableAlias() {
|
||||
return 'device';
|
||||
}
|
||||
|
||||
public function getOrderableColumns() {
|
||||
return parent::getOrderableColumns() + array(
|
||||
'name' => array(
|
||||
'table' => $this->getPrimaryTableAlias(),
|
||||
'column' => 'name',
|
||||
'type' => 'string',
|
||||
'unique' => true,
|
||||
'reverse' => true,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
protected function getPagingValueMap($cursor, array $keys) {
|
||||
$device = $this->loadCursorObject($cursor);
|
||||
return array(
|
||||
'id' => $device->getID(),
|
||||
'name' => $device->getName(),
|
||||
);
|
||||
}
|
||||
|
||||
public function getBuiltinOrders() {
|
||||
return array(
|
||||
'name' => array(
|
||||
'vector' => array('name'),
|
||||
'name' => pht('Device Name'),
|
||||
),
|
||||
) + parent::getBuiltinOrders();
|
||||
}
|
||||
|
||||
public function getQueryApplicationClass() {
|
||||
|
|
|
@ -11,22 +11,37 @@ final class AlmanacDeviceSearchEngine
|
|||
return 'PhabricatorAlmanacApplication';
|
||||
}
|
||||
|
||||
public function buildSavedQueryFromRequest(AphrontRequest $request) {
|
||||
$saved = new PhabricatorSavedQuery();
|
||||
|
||||
return $saved;
|
||||
public function newQuery() {
|
||||
return new AlmanacDeviceQuery();
|
||||
}
|
||||
|
||||
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
|
||||
$query = id(new AlmanacDeviceQuery());
|
||||
protected function buildCustomSearchFields() {
|
||||
return array(
|
||||
id(new PhabricatorSearchTextField())
|
||||
->setLabel(pht('Name Contains'))
|
||||
->setKey('match')
|
||||
->setDescription(pht('Search for devices by name substring.')),
|
||||
id(new PhabricatorSearchStringListField())
|
||||
->setLabel(pht('Exact Names'))
|
||||
->setKey('names')
|
||||
->setDescription(pht('Search for devices with specific names.')),
|
||||
);
|
||||
}
|
||||
|
||||
protected function buildQueryFromParameters(array $map) {
|
||||
$query = $this->newQuery();
|
||||
|
||||
if ($map['match'] !== null) {
|
||||
$query->withNameNgrams($map['match']);
|
||||
}
|
||||
|
||||
if ($map['names']) {
|
||||
$query->withNames($map['names']);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function buildSearchForm(
|
||||
AphrontFormView $form,
|
||||
PhabricatorSavedQuery $saved_query) {}
|
||||
|
||||
protected function getURI($path) {
|
||||
return '/almanac/device/'.$path;
|
||||
}
|
||||
|
@ -52,12 +67,6 @@ final class AlmanacDeviceSearchEngine
|
|||
return parent::buildSavedQueryFromBuiltin($query_key);
|
||||
}
|
||||
|
||||
protected function getRequiredHandlePHIDsForResultList(
|
||||
array $devices,
|
||||
PhabricatorSavedQuery $query) {
|
||||
return array();
|
||||
}
|
||||
|
||||
protected function renderResultList(
|
||||
array $devices,
|
||||
PhabricatorSavedQuery $query,
|
||||
|
@ -75,6 +84,10 @@ final class AlmanacDeviceSearchEngine
|
|||
->setHref($device->getURI())
|
||||
->setObject($device);
|
||||
|
||||
if ($device->isClusterDevice()) {
|
||||
$item->addIcon('fa-sitemap', pht('Cluster Device'));
|
||||
}
|
||||
|
||||
$list->addItem($item);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacInterfaceQuery
|
||||
extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||
extends AlmanacQuery {
|
||||
|
||||
private $ids;
|
||||
private $phids;
|
||||
|
@ -34,19 +34,12 @@ final class AlmanacInterfaceQuery
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function newResultObject() {
|
||||
return new AlmanacInterface();
|
||||
}
|
||||
|
||||
protected function loadPage() {
|
||||
$table = new AlmanacInterface();
|
||||
$conn_r = $table->establishConnection('r');
|
||||
|
||||
$data = queryfx_all(
|
||||
$conn_r,
|
||||
'SELECT * FROM %T %Q %Q %Q',
|
||||
$table->getTableName(),
|
||||
$this->buildWhereClause($conn_r),
|
||||
$this->buildOrderClause($conn_r),
|
||||
$this->buildLimitClause($conn_r));
|
||||
|
||||
return $table->loadAllFromArray($data);
|
||||
return $this->loadStandardPage($this->newResultObject());
|
||||
}
|
||||
|
||||
protected function willFilterPage(array $interfaces) {
|
||||
|
@ -57,6 +50,7 @@ final class AlmanacInterfaceQuery
|
|||
->setParentQuery($this)
|
||||
->setViewer($this->getViewer())
|
||||
->withPHIDs($network_phids)
|
||||
->needProperties($this->getNeedProperties())
|
||||
->execute();
|
||||
$networks = mpull($networks, null, 'getPHID');
|
||||
|
||||
|
@ -64,6 +58,7 @@ final class AlmanacInterfaceQuery
|
|||
->setParentQuery($this)
|
||||
->setViewer($this->getViewer())
|
||||
->withPHIDs($device_phids)
|
||||
->needProperties($this->getNeedProperties())
|
||||
->execute();
|
||||
$devices = mpull($devices, null, 'getPHID');
|
||||
|
||||
|
@ -83,34 +78,34 @@ final class AlmanacInterfaceQuery
|
|||
return $interfaces;
|
||||
}
|
||||
|
||||
protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
|
||||
$where = array();
|
||||
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
|
||||
$where = parent::buildWhereClauseParts($conn);
|
||||
|
||||
if ($this->ids !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'id IN (%Ld)',
|
||||
$conn,
|
||||
'interface.id IN (%Ld)',
|
||||
$this->ids);
|
||||
}
|
||||
|
||||
if ($this->phids !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'phid IN (%Ls)',
|
||||
$conn,
|
||||
'interface.phid IN (%Ls)',
|
||||
$this->phids);
|
||||
}
|
||||
|
||||
if ($this->networkPHIDs !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'networkPHID IN (%Ls)',
|
||||
$conn,
|
||||
'interface.networkPHID IN (%Ls)',
|
||||
$this->networkPHIDs);
|
||||
}
|
||||
|
||||
if ($this->devicePHIDs !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'devicePHID IN (%Ls)',
|
||||
$conn,
|
||||
'interface.devicePHID IN (%Ls)',
|
||||
$this->devicePHIDs);
|
||||
}
|
||||
|
||||
|
@ -118,8 +113,10 @@ final class AlmanacInterfaceQuery
|
|||
$parts = array();
|
||||
foreach ($this->addresses as $address) {
|
||||
$parts[] = qsprintf(
|
||||
$conn_r,
|
||||
'(networkPHID = %s AND address = %s AND port = %d)',
|
||||
$conn,
|
||||
'(interface.networkPHID = %s '.
|
||||
'AND interface.address = %s '.
|
||||
'AND interface.port = %d)',
|
||||
$address->getNetworkPHID(),
|
||||
$address->getAddress(),
|
||||
$address->getPort());
|
||||
|
@ -127,13 +124,77 @@ final class AlmanacInterfaceQuery
|
|||
$where[] = implode(' OR ', $parts);
|
||||
}
|
||||
|
||||
$where[] = $this->buildPagingClause($conn_r);
|
||||
return $where;
|
||||
}
|
||||
|
||||
return $this->formatWhereClause($where);
|
||||
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
|
||||
$joins = parent::buildJoinClauseParts($conn);
|
||||
|
||||
if ($this->shouldJoinDeviceTable()) {
|
||||
$joins[] = qsprintf(
|
||||
$conn,
|
||||
'JOIN %T device ON device.phid = interface.devicePHID',
|
||||
id(new AlmanacDevice())->getTableName());
|
||||
}
|
||||
|
||||
return $joins;
|
||||
}
|
||||
|
||||
protected function shouldGroupQueryResultRows() {
|
||||
if ($this->shouldJoinDeviceTable()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return parent::shouldGroupQueryResultRows();
|
||||
}
|
||||
|
||||
private function shouldJoinDeviceTable() {
|
||||
$vector = $this->getOrderVector();
|
||||
|
||||
if ($vector->containsKey('name')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function getPrimaryTableAlias() {
|
||||
return 'interface';
|
||||
}
|
||||
|
||||
public function getQueryApplicationClass() {
|
||||
return 'PhabricatorAlmanacApplication';
|
||||
}
|
||||
|
||||
public function getBuiltinOrders() {
|
||||
return array(
|
||||
'name' => array(
|
||||
'vector' => array('name', 'id'),
|
||||
'name' => pht('Device Name'),
|
||||
),
|
||||
) + parent::getBuiltinOrders();
|
||||
}
|
||||
|
||||
public function getOrderableColumns() {
|
||||
return parent::getOrderableColumns() + array(
|
||||
'name' => array(
|
||||
'table' => 'device',
|
||||
'column' => 'name',
|
||||
'type' => 'string',
|
||||
'reverse' => true,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
protected function getPagingValueMap($cursor, array $keys) {
|
||||
$interface = $this->loadCursorObject($cursor);
|
||||
|
||||
$map = array(
|
||||
'id' => $interface->getID(),
|
||||
'name' => $interface->getDevice()->getName(),
|
||||
);
|
||||
|
||||
return $map;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
103
src/applications/almanac/query/AlmanacNamespaceQuery.php
Normal file
103
src/applications/almanac/query/AlmanacNamespaceQuery.php
Normal file
|
@ -0,0 +1,103 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacNamespaceQuery
|
||||
extends AlmanacQuery {
|
||||
|
||||
private $ids;
|
||||
private $phids;
|
||||
private $names;
|
||||
|
||||
public function withIDs(array $ids) {
|
||||
$this->ids = $ids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withPHIDs(array $phids) {
|
||||
$this->phids = $phids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withNames(array $names) {
|
||||
$this->names = $names;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withNameNgrams($ngrams) {
|
||||
return $this->withNgramsConstraint(
|
||||
new AlmanacNamespaceNameNgrams(),
|
||||
$ngrams);
|
||||
}
|
||||
|
||||
public function newResultObject() {
|
||||
return new AlmanacNamespace();
|
||||
}
|
||||
|
||||
protected function loadPage() {
|
||||
return $this->loadStandardPage($this->newResultObject());
|
||||
}
|
||||
|
||||
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
|
||||
$where = parent::buildWhereClauseParts($conn);
|
||||
|
||||
if ($this->ids !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
'namespace.id IN (%Ld)',
|
||||
$this->ids);
|
||||
}
|
||||
|
||||
if ($this->phids !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
'namespace.phid IN (%Ls)',
|
||||
$this->phids);
|
||||
}
|
||||
|
||||
if ($this->names !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
'namespace.name IN (%Ls)',
|
||||
$this->names);
|
||||
}
|
||||
|
||||
return $where;
|
||||
}
|
||||
|
||||
protected function getPrimaryTableAlias() {
|
||||
return 'namespace';
|
||||
}
|
||||
|
||||
public function getOrderableColumns() {
|
||||
return parent::getOrderableColumns() + array(
|
||||
'name' => array(
|
||||
'table' => $this->getPrimaryTableAlias(),
|
||||
'column' => 'name',
|
||||
'type' => 'string',
|
||||
'unique' => true,
|
||||
'reverse' => true,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
protected function getPagingValueMap($cursor, array $keys) {
|
||||
$namespace = $this->loadCursorObject($cursor);
|
||||
return array(
|
||||
'id' => $namespace->getID(),
|
||||
'name' => $namespace->getName(),
|
||||
);
|
||||
}
|
||||
|
||||
public function getBuiltinOrders() {
|
||||
return array(
|
||||
'name' => array(
|
||||
'vector' => array('name'),
|
||||
'name' => pht('Namespace Name'),
|
||||
),
|
||||
) + parent::getBuiltinOrders();
|
||||
}
|
||||
|
||||
public function getQueryApplicationClass() {
|
||||
return 'PhabricatorAlmanacApplication';
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacNamespaceSearchEngine
|
||||
extends PhabricatorApplicationSearchEngine {
|
||||
|
||||
public function getResultTypeDescription() {
|
||||
return pht('Almanac Namespaces');
|
||||
}
|
||||
|
||||
public function getApplicationClassName() {
|
||||
return 'PhabricatorAlmanacApplication';
|
||||
}
|
||||
|
||||
public function newQuery() {
|
||||
return new AlmanacNamespaceQuery();
|
||||
}
|
||||
|
||||
protected function buildCustomSearchFields() {
|
||||
return array(
|
||||
id(new PhabricatorSearchTextField())
|
||||
->setLabel(pht('Name Contains'))
|
||||
->setKey('match')
|
||||
->setDescription(pht('Search for namespaces by name substring.')),
|
||||
);
|
||||
}
|
||||
|
||||
protected function buildQueryFromParameters(array $map) {
|
||||
$query = $this->newQuery();
|
||||
|
||||
if ($map['match'] !== null) {
|
||||
$query->withNameNgrams($map['match']);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
protected function getURI($path) {
|
||||
return '/almanac/namespace/'.$path;
|
||||
}
|
||||
|
||||
protected function getBuiltinQueryNames() {
|
||||
$names = array(
|
||||
'all' => pht('All Namespaces'),
|
||||
);
|
||||
|
||||
return $names;
|
||||
}
|
||||
|
||||
public function buildSavedQueryFromBuiltin($query_key) {
|
||||
|
||||
$query = $this->newSavedQuery();
|
||||
$query->setQueryKey($query_key);
|
||||
|
||||
switch ($query_key) {
|
||||
case 'all':
|
||||
return $query;
|
||||
}
|
||||
|
||||
return parent::buildSavedQueryFromBuiltin($query_key);
|
||||
}
|
||||
|
||||
protected function renderResultList(
|
||||
array $namespaces,
|
||||
PhabricatorSavedQuery $query,
|
||||
array $handles) {
|
||||
assert_instances_of($namespaces, 'AlmanacNamespace');
|
||||
|
||||
$viewer = $this->requireViewer();
|
||||
|
||||
$list = new PHUIObjectItemListView();
|
||||
$list->setUser($viewer);
|
||||
foreach ($namespaces as $namespace) {
|
||||
$id = $namespace->getID();
|
||||
|
||||
$item = id(new PHUIObjectItemView())
|
||||
->setObjectName(pht('Namespace %d', $id))
|
||||
->setHeader($namespace->getName())
|
||||
->setHref($this->getApplicationURI("namespace/{$id}/"))
|
||||
->setObject($namespace);
|
||||
|
||||
$list->addItem($item);
|
||||
}
|
||||
|
||||
$result = new PhabricatorApplicationSearchResultView();
|
||||
$result->setObjectList($list);
|
||||
$result->setNoDataString(pht('No Almanac namespaces found.'));
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacNamespaceTransactionQuery
|
||||
extends PhabricatorApplicationTransactionQuery {
|
||||
|
||||
public function getTemplateApplicationTransaction() {
|
||||
return new AlmanacNamespaceTransaction();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacNetworkQuery
|
||||
extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||
extends AlmanacQuery {
|
||||
|
||||
private $ids;
|
||||
private $phids;
|
||||
|
@ -16,41 +16,42 @@ final class AlmanacNetworkQuery
|
|||
return $this;
|
||||
}
|
||||
|
||||
protected function loadPage() {
|
||||
$table = new AlmanacNetwork();
|
||||
$conn_r = $table->establishConnection('r');
|
||||
|
||||
$data = queryfx_all(
|
||||
$conn_r,
|
||||
'SELECT * FROM %T %Q %Q %Q',
|
||||
$table->getTableName(),
|
||||
$this->buildWhereClause($conn_r),
|
||||
$this->buildOrderClause($conn_r),
|
||||
$this->buildLimitClause($conn_r));
|
||||
|
||||
return $table->loadAllFromArray($data);
|
||||
public function newResultObject() {
|
||||
return new AlmanacNetwork();
|
||||
}
|
||||
|
||||
protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
|
||||
$where = array();
|
||||
public function withNameNgrams($ngrams) {
|
||||
return $this->withNgramsConstraint(
|
||||
new AlmanacNetworkNameNgrams(),
|
||||
$ngrams);
|
||||
}
|
||||
|
||||
protected function loadPage() {
|
||||
return $this->loadStandardPage($this->newResultObject());
|
||||
}
|
||||
|
||||
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
|
||||
$where = parent::buildWhereClauseParts($conn);
|
||||
|
||||
if ($this->ids !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'id IN (%Ld)',
|
||||
$conn,
|
||||
'network.id IN (%Ld)',
|
||||
$this->ids);
|
||||
}
|
||||
|
||||
if ($this->phids !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'phid IN (%Ls)',
|
||||
$conn,
|
||||
'network.phid IN (%Ls)',
|
||||
$this->phids);
|
||||
}
|
||||
|
||||
$where[] = $this->buildPagingClause($conn_r);
|
||||
return $where;
|
||||
}
|
||||
|
||||
return $this->formatWhereClause($where);
|
||||
protected function getPrimaryTableAlias() {
|
||||
return 'network';
|
||||
}
|
||||
|
||||
public function getQueryApplicationClass() {
|
||||
|
|
|
@ -11,22 +11,29 @@ final class AlmanacNetworkSearchEngine
|
|||
return 'PhabricatorAlmanacApplication';
|
||||
}
|
||||
|
||||
public function buildSavedQueryFromRequest(AphrontRequest $request) {
|
||||
$saved = new PhabricatorSavedQuery();
|
||||
|
||||
return $saved;
|
||||
public function newQuery() {
|
||||
return new AlmanacNetworkQuery();
|
||||
}
|
||||
|
||||
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
|
||||
$query = id(new AlmanacNetworkQuery());
|
||||
protected function buildCustomSearchFields() {
|
||||
return array(
|
||||
id(new PhabricatorSearchTextField())
|
||||
->setLabel(pht('Name Contains'))
|
||||
->setKey('match')
|
||||
->setDescription(pht('Search for networks by name substring.')),
|
||||
);
|
||||
}
|
||||
|
||||
protected function buildQueryFromParameters(array $map) {
|
||||
$query = $this->newQuery();
|
||||
|
||||
if ($map['match'] !== null) {
|
||||
$query->withNameNgrams($map['match']);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function buildSearchForm(
|
||||
AphrontFormView $form,
|
||||
PhabricatorSavedQuery $saved_query) {}
|
||||
|
||||
protected function getURI($path) {
|
||||
return '/almanac/network/'.$path;
|
||||
}
|
||||
|
@ -52,12 +59,6 @@ final class AlmanacNetworkSearchEngine
|
|||
return parent::buildSavedQueryFromBuiltin($query_key);
|
||||
}
|
||||
|
||||
protected function getRequiredHandlePHIDsForResultList(
|
||||
array $networks,
|
||||
PhabricatorSavedQuery $query) {
|
||||
return array();
|
||||
}
|
||||
|
||||
protected function renderResultList(
|
||||
array $networks,
|
||||
PhabricatorSavedQuery $query,
|
||||
|
|
|
@ -5,8 +5,8 @@ final class AlmanacPropertyQuery
|
|||
|
||||
private $ids;
|
||||
private $objectPHIDs;
|
||||
private $objects;
|
||||
private $names;
|
||||
private $disablePolicyFilteringAndAttachment;
|
||||
|
||||
public function withIDs(array $ids) {
|
||||
$this->ids = $ids;
|
||||
|
@ -18,45 +18,46 @@ final class AlmanacPropertyQuery
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function withObjects(array $objects) {
|
||||
$this->objects = mpull($objects, null, 'getPHID');
|
||||
$this->objectPHIDs = array_keys($this->objects);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withNames(array $names) {
|
||||
$this->names = $names;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setDisablePolicyFilteringAndAttachment($disable) {
|
||||
$this->disablePolicyFilteringAndAttachment = $disable;
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function shouldDisablePolicyFiltering() {
|
||||
return $this->disablePolicyFilteringAndAttachment;
|
||||
public function newResultObject() {
|
||||
return new AlmanacProperty();
|
||||
}
|
||||
|
||||
protected function loadPage() {
|
||||
$table = new AlmanacProperty();
|
||||
$conn_r = $table->establishConnection('r');
|
||||
|
||||
$data = queryfx_all(
|
||||
$conn_r,
|
||||
'SELECT * FROM %T %Q %Q %Q',
|
||||
$table->getTableName(),
|
||||
$this->buildWhereClause($conn_r),
|
||||
$this->buildOrderClause($conn_r),
|
||||
$this->buildLimitClause($conn_r));
|
||||
|
||||
return $table->loadAllFromArray($data);
|
||||
return $this->loadStandardPage($this->newResultObject());
|
||||
}
|
||||
|
||||
protected function willFilterPage(array $properties) {
|
||||
if (!$this->disablePolicyFilteringAndAttachment) {
|
||||
$object_phids = mpull($properties, 'getObjectPHID');
|
||||
|
||||
$object_phids = array_fuse($object_phids);
|
||||
|
||||
if ($this->objects !== null) {
|
||||
$object_phids = array_diff_key($object_phids, $this->objects);
|
||||
}
|
||||
|
||||
if ($object_phids) {
|
||||
$objects = id(new PhabricatorObjectQuery())
|
||||
->setViewer($this->getViewer())
|
||||
->setParentQuery($this)
|
||||
->withPHIDs($object_phids)
|
||||
->execute();
|
||||
$objects = mpull($objects, null, 'getPHID');
|
||||
} else {
|
||||
$objects = array();
|
||||
}
|
||||
|
||||
$objects += $this->objects;
|
||||
|
||||
foreach ($properties as $key => $property) {
|
||||
$object = idx($objects, $property->getObjectPHID());
|
||||
|
@ -66,24 +67,23 @@ final class AlmanacPropertyQuery
|
|||
}
|
||||
$property->attachObject($object);
|
||||
}
|
||||
}
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
|
||||
$where = array();
|
||||
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
|
||||
$where = parent::buildWhereClauseParts($conn);
|
||||
|
||||
if ($this->ids !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
$conn,
|
||||
'id IN (%Ld)',
|
||||
$this->ids);
|
||||
}
|
||||
|
||||
if ($this->objectPHIDs !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
$conn,
|
||||
'objectPHID IN (%Ls)',
|
||||
$this->objectPHIDs);
|
||||
}
|
||||
|
@ -94,14 +94,12 @@ final class AlmanacPropertyQuery
|
|||
$hashes[] = PhabricatorHash::digestForIndex($name);
|
||||
}
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
$conn,
|
||||
'fieldIndex IN (%Ls)',
|
||||
$hashes);
|
||||
}
|
||||
|
||||
$where[] = $this->buildPagingClause($conn_r);
|
||||
|
||||
return $this->formatWhereClause($where);
|
||||
return $where;
|
||||
}
|
||||
|
||||
public function getQueryApplicationClass() {
|
||||
|
|
|
@ -3,31 +3,48 @@
|
|||
abstract class AlmanacQuery
|
||||
extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||
|
||||
protected function didFilterPage(array $objects) {
|
||||
if (head($objects) instanceof AlmanacPropertyInterface) {
|
||||
// NOTE: We load properties unconditionally because CustomField assumes
|
||||
// it can always generate a list of fields on an object. It may make
|
||||
// sense to re-examine that assumption eventually.
|
||||
private $needProperties;
|
||||
|
||||
public function needProperties($need_properties) {
|
||||
$this->needProperties = $need_properties;
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function getNeedProperties() {
|
||||
return $this->needProperties;
|
||||
}
|
||||
|
||||
protected function didFilterPage(array $objects) {
|
||||
$has_properties = (head($objects) instanceof AlmanacPropertyInterface);
|
||||
|
||||
if ($has_properties && $this->needProperties) {
|
||||
$property_query = id(new AlmanacPropertyQuery())
|
||||
->setViewer($this->getViewer())
|
||||
->setParentQuery($this)
|
||||
->withObjectPHIDs(mpull($objects, 'getPHID'));
|
||||
|
||||
// NOTE: We disable policy filtering and object attachment to avoid
|
||||
// a cyclic dependency where objects need their properties and properties
|
||||
// need their objects. We'll attach the objects below, and have already
|
||||
// implicitly checked the necessary policies.
|
||||
$property_query->setDisablePolicyFilteringAndAttachment(true);
|
||||
->withObjects($objects);
|
||||
|
||||
$properties = $property_query->execute();
|
||||
|
||||
$properties = mgroup($properties, 'getObjectPHID');
|
||||
foreach ($objects as $object) {
|
||||
$object_properties = idx($properties, $object->getPHID(), array());
|
||||
$object_properties = mpull($object_properties, null, 'getFieldName');
|
||||
|
||||
// Create synthetic properties for defaults on the object itself.
|
||||
$specs = $object->getAlmanacPropertyFieldSpecifications();
|
||||
foreach ($specs as $key => $spec) {
|
||||
if (empty($object_properties[$key])) {
|
||||
$object_properties[$key] = id(new AlmanacProperty())
|
||||
->setObjectPHID($object->getPHID())
|
||||
->setFieldName($key)
|
||||
->setFieldValue($spec->getValueForTransaction());
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($object_properties as $property) {
|
||||
$property->attachObject($object);
|
||||
}
|
||||
|
||||
$object->attachAlmanacProperties($object_properties);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,9 +6,8 @@ final class AlmanacServiceQuery
|
|||
private $ids;
|
||||
private $phids;
|
||||
private $names;
|
||||
private $serviceClasses;
|
||||
private $serviceTypes;
|
||||
private $devicePHIDs;
|
||||
private $locked;
|
||||
private $namePrefix;
|
||||
private $nameSuffix;
|
||||
|
||||
|
@ -29,8 +28,8 @@ final class AlmanacServiceQuery
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function withServiceClasses(array $classes) {
|
||||
$this->serviceClasses = $classes;
|
||||
public function withServiceTypes(array $types) {
|
||||
$this->serviceTypes = $types;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -39,11 +38,6 @@ final class AlmanacServiceQuery
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function withLocked($locked) {
|
||||
$this->locked = $locked;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withNamePrefix($prefix) {
|
||||
$this->namePrefix = $prefix;
|
||||
return $this;
|
||||
|
@ -54,19 +48,29 @@ final class AlmanacServiceQuery
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function withNameNgrams($ngrams) {
|
||||
return $this->withNgramsConstraint(
|
||||
new AlmanacServiceNameNgrams(),
|
||||
$ngrams);
|
||||
}
|
||||
|
||||
public function needBindings($need_bindings) {
|
||||
$this->needBindings = $need_bindings;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function newResultObject() {
|
||||
return new AlmanacService();
|
||||
}
|
||||
|
||||
protected function loadPage() {
|
||||
return $this->loadStandardPage(new AlmanacService());
|
||||
return $this->loadStandardPage($this->newResultObject());
|
||||
}
|
||||
|
||||
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
|
||||
$joins = parent::buildJoinClauseParts($conn);
|
||||
|
||||
if ($this->devicePHIDs !== null) {
|
||||
if ($this->shouldJoinBindingTable()) {
|
||||
$joins[] = qsprintf(
|
||||
$conn,
|
||||
'JOIN %T binding ON service.phid = binding.servicePHID',
|
||||
|
@ -105,11 +109,11 @@ final class AlmanacServiceQuery
|
|||
$hashes);
|
||||
}
|
||||
|
||||
if ($this->serviceClasses !== null) {
|
||||
if ($this->serviceTypes !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
'service.serviceClass IN (%Ls)',
|
||||
$this->serviceClasses);
|
||||
'service.serviceType IN (%Ls)',
|
||||
$this->serviceTypes);
|
||||
}
|
||||
|
||||
if ($this->devicePHIDs !== null) {
|
||||
|
@ -119,13 +123,6 @@ final class AlmanacServiceQuery
|
|||
$this->devicePHIDs);
|
||||
}
|
||||
|
||||
if ($this->locked !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
'service.isLocked = %d',
|
||||
(int)$this->locked);
|
||||
}
|
||||
|
||||
if ($this->namePrefix !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
|
@ -144,17 +141,19 @@ final class AlmanacServiceQuery
|
|||
}
|
||||
|
||||
protected function willFilterPage(array $services) {
|
||||
$service_types = AlmanacServiceType::getAllServiceTypes();
|
||||
$service_map = AlmanacServiceType::getAllServiceTypes();
|
||||
|
||||
foreach ($services as $key => $service) {
|
||||
$service_class = $service->getServiceClass();
|
||||
$service_type = idx($service_types, $service_class);
|
||||
if (!$service_type) {
|
||||
$implementation = idx($service_map, $service->getServiceType());
|
||||
|
||||
if (!$implementation) {
|
||||
$this->didRejectResult($service);
|
||||
unset($services[$key]);
|
||||
continue;
|
||||
}
|
||||
$service->attachServiceType($service_type);
|
||||
|
||||
$implementation = clone $implementation;
|
||||
$service->attachServiceImplementation($implementation);
|
||||
}
|
||||
|
||||
return $services;
|
||||
|
@ -166,6 +165,7 @@ final class AlmanacServiceQuery
|
|||
$bindings = id(new AlmanacBindingQuery())
|
||||
->setViewer($this->getViewer())
|
||||
->withServicePHIDs($service_phids)
|
||||
->needProperties($this->getNeedProperties())
|
||||
->execute();
|
||||
$bindings = mgroup($bindings, 'getServicePHID');
|
||||
|
||||
|
@ -178,6 +178,18 @@ final class AlmanacServiceQuery
|
|||
return parent::didFilterPage($services);
|
||||
}
|
||||
|
||||
private function shouldJoinBindingTable() {
|
||||
return ($this->devicePHIDs !== null);
|
||||
}
|
||||
|
||||
protected function shouldGroupQueryResultRows() {
|
||||
if ($this->shouldJoinBindingTable()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return parent::shouldGroupQueryResultRows();
|
||||
}
|
||||
|
||||
protected function getPrimaryTableAlias() {
|
||||
return 'service';
|
||||
}
|
||||
|
|
|
@ -16,21 +16,53 @@ final class AlmanacServiceSearchEngine
|
|||
}
|
||||
|
||||
public function newResultObject() {
|
||||
// NOTE: We need to attach a service type in order to generate custom
|
||||
// field definitions.
|
||||
return AlmanacService::initializeNewService()
|
||||
->attachServiceType(new AlmanacCustomServiceType());
|
||||
return new AlmanacService();
|
||||
}
|
||||
|
||||
protected function buildQueryFromParameters(array $map) {
|
||||
$query = $this->newQuery();
|
||||
|
||||
if ($map['match'] !== null) {
|
||||
$query->withNameNgrams($map['match']);
|
||||
}
|
||||
|
||||
if ($map['names']) {
|
||||
$query->withNames($map['names']);
|
||||
}
|
||||
|
||||
if ($map['devicePHIDs']) {
|
||||
$query->withDevicePHIDs($map['devicePHIDs']);
|
||||
}
|
||||
|
||||
if ($map['serviceTypes']) {
|
||||
$query->withServiceTypes($map['serviceTypes']);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
|
||||
protected function buildCustomSearchFields() {
|
||||
return array();
|
||||
return array(
|
||||
id(new PhabricatorSearchTextField())
|
||||
->setLabel(pht('Name Contains'))
|
||||
->setKey('match')
|
||||
->setDescription(pht('Search for services by name substring.')),
|
||||
id(new PhabricatorSearchStringListField())
|
||||
->setLabel(pht('Exact Names'))
|
||||
->setKey('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())
|
||||
->setLabel(pht('Devices'))
|
||||
->setKey('devicePHIDs')
|
||||
->setDescription(
|
||||
pht('Search for services bound to particular devices.')),
|
||||
);
|
||||
}
|
||||
|
||||
protected function getURI($path) {
|
||||
|
@ -75,17 +107,8 @@ final class AlmanacServiceSearchEngine
|
|||
->setHref($service->getURI())
|
||||
->setObject($service)
|
||||
->addIcon(
|
||||
$service->getServiceType()->getServiceTypeIcon(),
|
||||
$service->getServiceType()->getServiceTypeShortName());
|
||||
|
||||
if ($service->getIsLocked() ||
|
||||
$service->getServiceType()->isClusterServiceType()) {
|
||||
if ($service->getIsLocked()) {
|
||||
$item->addIcon('fa-lock', pht('Locked'));
|
||||
} else {
|
||||
$item->addIcon('fa-unlock-alt red', pht('Unlocked'));
|
||||
}
|
||||
}
|
||||
$service->getServiceImplementation()->getServiceTypeIcon(),
|
||||
$service->getServiceImplementation()->getServiceTypeShortName());
|
||||
|
||||
$list->addItem($item);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
final class AlmanacClusterDatabaseServiceType
|
||||
extends AlmanacClusterServiceType {
|
||||
|
||||
const SERVICETYPE = 'cluster.database';
|
||||
|
||||
public function getServiceTypeShortName() {
|
||||
return pht('Cluster Database');
|
||||
}
|
||||
|
@ -16,8 +18,4 @@ final class AlmanacClusterDatabaseServiceType
|
|||
'Defines a database service for use in a Phabricator cluster.');
|
||||
}
|
||||
|
||||
public function getFieldSpecifications() {
|
||||
return array();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
final class AlmanacClusterRepositoryServiceType
|
||||
extends AlmanacClusterServiceType {
|
||||
|
||||
const SERVICETYPE = 'cluster.repository';
|
||||
|
||||
public function getServiceTypeShortName() {
|
||||
return pht('Cluster Repository');
|
||||
}
|
||||
|
@ -18,16 +20,7 @@ final class AlmanacClusterRepositoryServiceType
|
|||
|
||||
public function getFieldSpecifications() {
|
||||
return array(
|
||||
'closed' => array(
|
||||
'type' => 'bool',
|
||||
'name' => pht('Closed'),
|
||||
'default' => false,
|
||||
'strings' => array(
|
||||
'edit.checkbox' => pht(
|
||||
'Prevent new repositories from being allocated on this '.
|
||||
'service.'),
|
||||
),
|
||||
),
|
||||
'closed' => id(new PhabricatorTextEditField()),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,28 +11,4 @@ abstract class AlmanacClusterServiceType
|
|||
return 'fa-sitemap';
|
||||
}
|
||||
|
||||
public function getStatusMessages(AlmanacService $service) {
|
||||
$messages = parent::getStatusMessages($service);
|
||||
|
||||
if (!$service->getIsLocked()) {
|
||||
$doc_href = PhabricatorEnv::getDoclink(
|
||||
'User Guide: Phabricator Clusters');
|
||||
|
||||
$doc_link = phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => $doc_href,
|
||||
'target' => '_blank',
|
||||
),
|
||||
pht('Learn More'));
|
||||
|
||||
$messages[] = pht(
|
||||
'This is an unlocked cluster service. After you finish editing '.
|
||||
'it, you should lock it. %s.',
|
||||
$doc_link);
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
final class AlmanacCustomServiceType extends AlmanacServiceType {
|
||||
|
||||
const SERVICETYPE = 'almanac.custom';
|
||||
|
||||
public function getServiceTypeShortName() {
|
||||
return pht('Custom');
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
final class AlmanacDrydockPoolServiceType extends AlmanacServiceType {
|
||||
|
||||
const SERVICETYPE = 'drydock.pool';
|
||||
|
||||
public function getServiceTypeShortName() {
|
||||
return pht('Drydock Pool');
|
||||
}
|
||||
|
|
|
@ -30,6 +30,11 @@ abstract class AlmanacServiceType extends Phobject {
|
|||
abstract public function getServiceTypeDescription();
|
||||
|
||||
|
||||
final public function getServiceTypeConstant() {
|
||||
return $this->getPhobjectClassConstant('SERVICETYPE', 64);
|
||||
}
|
||||
|
||||
|
||||
public function getServiceTypeIcon() {
|
||||
return 'fa-cog';
|
||||
}
|
||||
|
@ -38,7 +43,7 @@ abstract class AlmanacServiceType extends Phobject {
|
|||
* Return `true` if this service type is a Phabricator cluster service type.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
@ -55,10 +60,6 @@ abstract class AlmanacServiceType extends Phobject {
|
|||
return array();
|
||||
}
|
||||
|
||||
public function getStatusMessages(AlmanacService $service) {
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* List all available service type implementations.
|
||||
*
|
||||
|
@ -67,6 +68,7 @@ abstract class AlmanacServiceType extends Phobject {
|
|||
public static function getAllServiceTypes() {
|
||||
return id(new PhutilClassMapQuery())
|
||||
->setAncestorClass(__CLASS__)
|
||||
->setUniqueMethod('getServiceTypeConstant')
|
||||
->setSortMethod('getServiceTypeName')
|
||||
->execute();
|
||||
}
|
||||
|
|
|
@ -4,26 +4,27 @@ final class AlmanacBinding
|
|||
extends AlmanacDAO
|
||||
implements
|
||||
PhabricatorPolicyInterface,
|
||||
PhabricatorCustomFieldInterface,
|
||||
PhabricatorApplicationTransactionInterface,
|
||||
AlmanacPropertyInterface,
|
||||
PhabricatorDestructibleInterface {
|
||||
PhabricatorDestructibleInterface,
|
||||
PhabricatorExtendedPolicyInterface {
|
||||
|
||||
protected $servicePHID;
|
||||
protected $devicePHID;
|
||||
protected $interfacePHID;
|
||||
protected $mailKey;
|
||||
protected $isDisabled;
|
||||
|
||||
private $service = self::ATTACHABLE;
|
||||
private $device = self::ATTACHABLE;
|
||||
private $interface = self::ATTACHABLE;
|
||||
private $customFields = self::ATTACHABLE;
|
||||
private $almanacProperties = self::ATTACHABLE;
|
||||
|
||||
public static function initializeNewBinding(AlmanacService $service) {
|
||||
return id(new AlmanacBinding())
|
||||
->setServicePHID($service->getPHID())
|
||||
->attachAlmanacProperties(array());
|
||||
->attachAlmanacProperties(array())
|
||||
->setIsDisabled(0);
|
||||
}
|
||||
|
||||
protected function getConfiguration() {
|
||||
|
@ -31,6 +32,7 @@ final class AlmanacBinding
|
|||
self::CONFIG_AUX_PHID => true,
|
||||
self::CONFIG_COLUMN_SCHEMA => array(
|
||||
'mailKey' => 'bytes20',
|
||||
'isDisabled' => 'bool',
|
||||
),
|
||||
self::CONFIG_KEY_SCHEMA => array(
|
||||
'key_service' => array(
|
||||
|
@ -58,6 +60,10 @@ final class AlmanacBinding
|
|||
return parent::save();
|
||||
}
|
||||
|
||||
public function getName() {
|
||||
return pht('Binding %s', $this->getID());
|
||||
}
|
||||
|
||||
public function getURI() {
|
||||
return '/almanac/binding/'.$this->getID().'/';
|
||||
}
|
||||
|
@ -124,6 +130,10 @@ final class AlmanacBinding
|
|||
return array();
|
||||
}
|
||||
|
||||
public function newAlmanacPropertyEditEngine() {
|
||||
return new AlmanacBindingPropertyEditEngine();
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||
|
||||
|
@ -151,38 +161,30 @@ final class AlmanacBinding
|
|||
'interface.'),
|
||||
);
|
||||
|
||||
if ($capability === PhabricatorPolicyCapability::CAN_EDIT) {
|
||||
if ($this->getService()->getIsLocked()) {
|
||||
$notes[] = pht(
|
||||
'The service for this binding is locked, so it can not be edited.');
|
||||
}
|
||||
}
|
||||
|
||||
return $notes;
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorCustomFieldInterface )------------------------------------ */
|
||||
/* -( PhabricatorExtendedPolicyInterface )--------------------------------- */
|
||||
|
||||
|
||||
public function getCustomFieldSpecificationForRole($role) {
|
||||
public function getExtendedPolicy($capability, PhabricatorUser $viewer) {
|
||||
switch ($capability) {
|
||||
case PhabricatorPolicyCapability::CAN_EDIT:
|
||||
if ($this->getService()->isClusterService()) {
|
||||
return array(
|
||||
array(
|
||||
new PhabricatorAlmanacApplication(),
|
||||
AlmanacManageClusterServicesCapability::CAPABILITY,
|
||||
),
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
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 )------------------------- */
|
||||
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacBindingTransaction
|
||||
extends PhabricatorApplicationTransaction {
|
||||
extends AlmanacTransaction {
|
||||
|
||||
const TYPE_INTERFACE = 'almanac:binding:interface';
|
||||
const TYPE_DISABLE = 'almanac:binding:disable';
|
||||
|
||||
public function getApplicationName() {
|
||||
return 'almanac';
|
||||
|
@ -57,6 +58,17 @@ final class AlmanacBindingTransaction
|
|||
$this->renderHandleLink($new));
|
||||
}
|
||||
break;
|
||||
case self::TYPE_DISABLE:
|
||||
if ($new) {
|
||||
return pht(
|
||||
'%s disabled this binding.',
|
||||
$this->renderHandleLink($author_phid));
|
||||
} else {
|
||||
return pht(
|
||||
'%s enabled this binding.',
|
||||
$this->renderHandleLink($author_phid));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return parent::getTitle();
|
||||
|
|
|
@ -4,21 +4,22 @@ final class AlmanacDevice
|
|||
extends AlmanacDAO
|
||||
implements
|
||||
PhabricatorPolicyInterface,
|
||||
PhabricatorCustomFieldInterface,
|
||||
PhabricatorApplicationTransactionInterface,
|
||||
PhabricatorProjectInterface,
|
||||
PhabricatorSSHPublicKeyInterface,
|
||||
AlmanacPropertyInterface,
|
||||
PhabricatorDestructibleInterface {
|
||||
PhabricatorDestructibleInterface,
|
||||
PhabricatorNgramsInterface,
|
||||
PhabricatorConduitResultInterface,
|
||||
PhabricatorExtendedPolicyInterface {
|
||||
|
||||
protected $name;
|
||||
protected $nameIndex;
|
||||
protected $mailKey;
|
||||
protected $viewPolicy;
|
||||
protected $editPolicy;
|
||||
protected $isLocked;
|
||||
protected $isBoundToClusterService;
|
||||
|
||||
private $customFields = self::ATTACHABLE;
|
||||
private $almanacProperties = self::ATTACHABLE;
|
||||
|
||||
public static function initializeNewDevice() {
|
||||
|
@ -26,7 +27,7 @@ final class AlmanacDevice
|
|||
->setViewPolicy(PhabricatorPolicies::POLICY_USER)
|
||||
->setEditPolicy(PhabricatorPolicies::POLICY_ADMIN)
|
||||
->attachAlmanacProperties(array())
|
||||
->setIsLocked(0);
|
||||
->setIsBoundToClusterService(0);
|
||||
}
|
||||
|
||||
protected function getConfiguration() {
|
||||
|
@ -36,7 +37,7 @@ final class AlmanacDevice
|
|||
'name' => 'text128',
|
||||
'nameIndex' => 'bytes12',
|
||||
'mailKey' => 'bytes20',
|
||||
'isLocked' => 'bool',
|
||||
'isBoundToClusterService' => 'bool',
|
||||
),
|
||||
self::CONFIG_KEY_SCHEMA => array(
|
||||
'key_name' => array(
|
||||
|
@ -55,7 +56,7 @@ final class AlmanacDevice
|
|||
}
|
||||
|
||||
public function save() {
|
||||
AlmanacNames::validateServiceOrDeviceName($this->getName());
|
||||
AlmanacNames::validateName($this->getName());
|
||||
|
||||
$this->nameIndex = PhabricatorHash::digestForIndex($this->getName());
|
||||
|
||||
|
@ -70,30 +71,28 @@ final class AlmanacDevice
|
|||
return '/almanac/device/view/'.$this->getName().'/';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find locked services which are bound to this device, updating the device
|
||||
* lock flag if necessary.
|
||||
*
|
||||
* @return list<phid> List of locking service PHIDs.
|
||||
*/
|
||||
public function rebuildDeviceLocks() {
|
||||
public function rebuildClusterBindingStatus() {
|
||||
$services = id(new AlmanacServiceQuery())
|
||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||
->withDevicePHIDs(array($this->getPHID()))
|
||||
->withLocked(true)
|
||||
->execute();
|
||||
|
||||
$locked = (bool)count($services);
|
||||
$is_cluster = false;
|
||||
foreach ($services as $service) {
|
||||
if ($service->isClusterService()) {
|
||||
$is_cluster = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($locked != $this->getIsLocked()) {
|
||||
$this->setIsLocked((int)$locked);
|
||||
if ($is_cluster != $this->getIsBoundToClusterService()) {
|
||||
$this->setIsBoundToClusterService((int)$is_cluster);
|
||||
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
|
||||
queryfx(
|
||||
$this->establishConnection('w'),
|
||||
'UPDATE %T SET isLocked = %d WHERE id = %d',
|
||||
'UPDATE %T SET isBoundToClusterService = %d WHERE id = %d',
|
||||
$this->getTableName(),
|
||||
$this->getIsLocked(),
|
||||
$this->getIsBoundToClusterService(),
|
||||
$this->getID());
|
||||
unset($unguarded);
|
||||
}
|
||||
|
@ -101,6 +100,10 @@ final class AlmanacDevice
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function isClusterDevice() {
|
||||
return $this->getIsBoundToClusterService();
|
||||
}
|
||||
|
||||
|
||||
/* -( AlmanacPropertyInterface )------------------------------------------- */
|
||||
|
||||
|
@ -136,6 +139,10 @@ final class AlmanacDevice
|
|||
return array();
|
||||
}
|
||||
|
||||
public function newAlmanacPropertyEditEngine() {
|
||||
return new AlmanacDevicePropertyEditEngine();
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||
|
||||
|
@ -152,51 +159,39 @@ final class AlmanacDevice
|
|||
case PhabricatorPolicyCapability::CAN_VIEW:
|
||||
return $this->getViewPolicy();
|
||||
case PhabricatorPolicyCapability::CAN_EDIT:
|
||||
if ($this->getIsLocked()) {
|
||||
return PhabricatorPolicies::POLICY_NOONE;
|
||||
} else {
|
||||
return $this->getEditPolicy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
if ($capability === PhabricatorPolicyCapability::CAN_EDIT) {
|
||||
if ($this->getIsLocked()) {
|
||||
return pht(
|
||||
'This device is bound to a locked service, so it can not '.
|
||||
'be edited.');
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorCustomFieldInterface )------------------------------------ */
|
||||
/* -( PhabricatorExtendedPolicyInterface )--------------------------------- */
|
||||
|
||||
|
||||
public function getCustomFieldSpecificationForRole($role) {
|
||||
public function getExtendedPolicy($capability, PhabricatorUser $viewer) {
|
||||
switch ($capability) {
|
||||
case PhabricatorPolicyCapability::CAN_EDIT:
|
||||
if ($this->isClusterDevice()) {
|
||||
return array(
|
||||
array(
|
||||
new PhabricatorAlmanacApplication(),
|
||||
AlmanacManageClusterServicesCapability::CAPABILITY,
|
||||
),
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
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 )------------------------- */
|
||||
|
||||
|
@ -250,4 +245,41 @@ final class AlmanacDevice
|
|||
$this->delete();
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorNgramInterface )------------------------------------------ */
|
||||
|
||||
|
||||
public function newNgrams() {
|
||||
return array(
|
||||
id(new AlmanacDeviceNameNgrams())
|
||||
->setValue($this->getName()),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorConduitResultInterface )---------------------------------- */
|
||||
|
||||
|
||||
public function getFieldSpecificationsForConduit() {
|
||||
return array(
|
||||
id(new PhabricatorConduitSearchFieldSpecification())
|
||||
->setKey('name')
|
||||
->setType('string')
|
||||
->setDescription(pht('The name of the device.')),
|
||||
);
|
||||
}
|
||||
|
||||
public function getFieldValuesForConduit() {
|
||||
return array(
|
||||
'name' => $this->getName(),
|
||||
);
|
||||
}
|
||||
|
||||
public function getConduitSearchAttachments() {
|
||||
return array(
|
||||
id(new AlmanacPropertiesSearchEngineAttachment())
|
||||
->setAttachmentKey('properties'),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
18
src/applications/almanac/storage/AlmanacDeviceNameNgrams.php
Normal file
18
src/applications/almanac/storage/AlmanacDeviceNameNgrams.php
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacDeviceNameNgrams
|
||||
extends PhabricatorSearchNgrams {
|
||||
|
||||
public function getNgramKey() {
|
||||
return 'devicename';
|
||||
}
|
||||
|
||||
public function getColumnName() {
|
||||
return 'name';
|
||||
}
|
||||
|
||||
public function getApplicationName() {
|
||||
return 'almanac';
|
||||
}
|
||||
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacDeviceTransaction
|
||||
extends PhabricatorApplicationTransaction {
|
||||
extends AlmanacTransaction {
|
||||
|
||||
const TYPE_NAME = 'almanac:device:name';
|
||||
const TYPE_INTERFACE = 'almanac:device:interface';
|
||||
|
@ -69,7 +69,7 @@ final class AlmanacDeviceTransaction
|
|||
return pht(
|
||||
'%s removed the interface %s from this device.',
|
||||
$this->renderHandleLink($author_phid),
|
||||
$this->describeInterface($new));
|
||||
$this->describeInterface($old));
|
||||
} else if ($new) {
|
||||
return pht(
|
||||
'%s added the interface %s to this device.',
|
||||
|
|
|
@ -4,7 +4,8 @@ final class AlmanacInterface
|
|||
extends AlmanacDAO
|
||||
implements
|
||||
PhabricatorPolicyInterface,
|
||||
PhabricatorDestructibleInterface {
|
||||
PhabricatorDestructibleInterface,
|
||||
PhabricatorExtendedPolicyInterface {
|
||||
|
||||
protected $devicePHID;
|
||||
protected $networkPHID;
|
||||
|
@ -74,6 +75,16 @@ final class AlmanacInterface
|
|||
return $this->getAddress().':'.$this->getPort();
|
||||
}
|
||||
|
||||
public function loadIsInUse() {
|
||||
$binding = id(new AlmanacBindingQuery())
|
||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||
->withInterfacePHIDs(array($this->getPHID()))
|
||||
->setLimit(1)
|
||||
->executeOne();
|
||||
|
||||
return (bool)$binding;
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||
|
||||
|
@ -101,14 +112,28 @@ final class AlmanacInterface
|
|||
'view the interface.'),
|
||||
);
|
||||
|
||||
if ($capability === PhabricatorPolicyCapability::CAN_EDIT) {
|
||||
if ($this->getDevice()->getIsLocked()) {
|
||||
$notes[] = pht(
|
||||
'The device for this interface is locked, so it can not be edited.');
|
||||
}
|
||||
return $notes;
|
||||
}
|
||||
|
||||
return $notes;
|
||||
|
||||
/* -( PhabricatorExtendedPolicyInterface )--------------------------------- */
|
||||
|
||||
|
||||
public function getExtendedPolicy($capability, PhabricatorUser $viewer) {
|
||||
switch ($capability) {
|
||||
case PhabricatorPolicyCapability::CAN_EDIT:
|
||||
if ($this->getDevice()->isClusterDevice()) {
|
||||
return array(
|
||||
array(
|
||||
new PhabricatorAlmanacApplication(),
|
||||
AlmanacManageClusterServicesCapability::CAPABILITY,
|
||||
),
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
|
||||
|
|
223
src/applications/almanac/storage/AlmanacNamespace.php
Normal file
223
src/applications/almanac/storage/AlmanacNamespace.php
Normal file
|
@ -0,0 +1,223 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacNamespace
|
||||
extends AlmanacDAO
|
||||
implements
|
||||
PhabricatorPolicyInterface,
|
||||
PhabricatorApplicationTransactionInterface,
|
||||
PhabricatorProjectInterface,
|
||||
AlmanacPropertyInterface,
|
||||
PhabricatorDestructibleInterface,
|
||||
PhabricatorNgramsInterface {
|
||||
|
||||
protected $name;
|
||||
protected $nameIndex;
|
||||
protected $mailKey;
|
||||
protected $viewPolicy;
|
||||
protected $editPolicy;
|
||||
|
||||
private $almanacProperties = self::ATTACHABLE;
|
||||
|
||||
public static function initializeNewNamespace() {
|
||||
return id(new self())
|
||||
->setViewPolicy(PhabricatorPolicies::POLICY_USER)
|
||||
->setEditPolicy(PhabricatorPolicies::POLICY_ADMIN)
|
||||
->attachAlmanacProperties(array());
|
||||
}
|
||||
|
||||
protected function getConfiguration() {
|
||||
return array(
|
||||
self::CONFIG_AUX_PHID => true,
|
||||
self::CONFIG_COLUMN_SCHEMA => array(
|
||||
'name' => 'text128',
|
||||
'nameIndex' => 'bytes12',
|
||||
'mailKey' => 'bytes20',
|
||||
),
|
||||
self::CONFIG_KEY_SCHEMA => array(
|
||||
'key_nameindex' => array(
|
||||
'columns' => array('nameIndex'),
|
||||
'unique' => true,
|
||||
),
|
||||
'key_name' => array(
|
||||
'columns' => array('name'),
|
||||
),
|
||||
),
|
||||
) + parent::getConfiguration();
|
||||
}
|
||||
|
||||
public function generatePHID() {
|
||||
return PhabricatorPHID::generateNewPHID(
|
||||
AlmanacNamespacePHIDType::TYPECONST);
|
||||
}
|
||||
|
||||
public function save() {
|
||||
AlmanacNames::validateName($this->getName());
|
||||
|
||||
$this->nameIndex = PhabricatorHash::digestForIndex($this->getName());
|
||||
|
||||
if (!$this->mailKey) {
|
||||
$this->mailKey = Filesystem::readRandomCharacters(20);
|
||||
}
|
||||
|
||||
return parent::save();
|
||||
}
|
||||
|
||||
public function getURI() {
|
||||
return '/almanac/namespace/view/'.$this->getName().'/';
|
||||
}
|
||||
|
||||
public function getNameLength() {
|
||||
return strlen($this->getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the namespace which prevents use of an Almanac name, if one exists.
|
||||
*/
|
||||
public static function loadRestrictedNamespace(
|
||||
PhabricatorUser $viewer,
|
||||
$name) {
|
||||
|
||||
// For a name like "x.y.z", produce a list of controlling namespaces like
|
||||
// ("z", "y.x", "x.y.z").
|
||||
$names = array();
|
||||
$parts = explode('.', $name);
|
||||
for ($ii = 0; $ii < count($parts); $ii++) {
|
||||
$names[] = implode('.', array_slice($parts, -($ii + 1)));
|
||||
}
|
||||
|
||||
// Load all the possible controlling namespaces.
|
||||
$namespaces = id(new AlmanacNamespaceQuery())
|
||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||
->withNames($names)
|
||||
->execute();
|
||||
if (!$namespaces) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Find the "nearest" (longest) namespace that exists. If both
|
||||
// "sub.domain.com" and "domain.com" exist, we only care about the policy
|
||||
// on the former.
|
||||
$namespaces = msort($namespaces, 'getNameLength');
|
||||
$namespace = last($namespaces);
|
||||
|
||||
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
||||
$viewer,
|
||||
$namespace,
|
||||
PhabricatorPolicyCapability::CAN_EDIT);
|
||||
if ($can_edit) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $namespace;
|
||||
}
|
||||
|
||||
|
||||
/* -( 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;
|
||||
}
|
||||
}
|
||||
|
||||
public function getAlmanacPropertyFieldSpecifications() {
|
||||
return array();
|
||||
}
|
||||
|
||||
public function newAlmanacPropertyEditEngine() {
|
||||
throw new PhutilMethodNotImplementedException();
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||
|
||||
|
||||
public function getCapabilities() {
|
||||
return array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
);
|
||||
}
|
||||
|
||||
public function getPolicy($capability) {
|
||||
switch ($capability) {
|
||||
case PhabricatorPolicyCapability::CAN_VIEW:
|
||||
return $this->getViewPolicy();
|
||||
case PhabricatorPolicyCapability::CAN_EDIT:
|
||||
return $this->getEditPolicy();
|
||||
}
|
||||
}
|
||||
|
||||
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
|
||||
|
||||
|
||||
public function getApplicationTransactionEditor() {
|
||||
return new AlmanacNamespaceEditor();
|
||||
}
|
||||
|
||||
public function getApplicationTransactionObject() {
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getApplicationTransactionTemplate() {
|
||||
return new AlmanacNamespaceTransaction();
|
||||
}
|
||||
|
||||
public function willRenderTimeline(
|
||||
PhabricatorApplicationTransactionView $timeline,
|
||||
AphrontRequest $request) {
|
||||
return $timeline;
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorDestructibleInterface )----------------------------------- */
|
||||
|
||||
|
||||
public function destroyObjectPermanently(
|
||||
PhabricatorDestructionEngine $engine) {
|
||||
$this->delete();
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorNgramInterface )------------------------------------------ */
|
||||
|
||||
|
||||
public function newNgrams() {
|
||||
return array(
|
||||
id(new AlmanacNamespaceNameNgrams())
|
||||
->setValue($this->getName()),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacNamespaceNameNgrams
|
||||
extends PhabricatorSearchNgrams {
|
||||
|
||||
public function getNgramKey() {
|
||||
return 'namespacename';
|
||||
}
|
||||
|
||||
public function getColumnName() {
|
||||
return 'name';
|
||||
}
|
||||
|
||||
public function getApplicationName() {
|
||||
return 'almanac';
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacNamespaceTransaction
|
||||
extends PhabricatorApplicationTransaction {
|
||||
|
||||
const TYPE_NAME = 'almanac:namespace:name';
|
||||
|
||||
public function getApplicationName() {
|
||||
return 'almanac';
|
||||
}
|
||||
|
||||
public function getApplicationTransactionType() {
|
||||
return AlmanacNamespacePHIDType::TYPECONST;
|
||||
}
|
||||
|
||||
public function getApplicationTransactionCommentObject() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getTitle() {
|
||||
$author_phid = $this->getAuthorPHID();
|
||||
|
||||
$old = $this->getOldValue();
|
||||
$new = $this->getNewValue();
|
||||
|
||||
switch ($this->getTransactionType()) {
|
||||
case PhabricatorTransactions::TYPE_CREATE:
|
||||
return pht(
|
||||
'%s created this namespace.',
|
||||
$this->renderHandleLink($author_phid));
|
||||
break;
|
||||
case self::TYPE_NAME:
|
||||
return pht(
|
||||
'%s renamed this namespace from "%s" to "%s".',
|
||||
$this->renderHandleLink($author_phid),
|
||||
$old,
|
||||
$new);
|
||||
}
|
||||
|
||||
return parent::getTitle();
|
||||
}
|
||||
|
||||
}
|
|
@ -5,7 +5,8 @@ final class AlmanacNetwork
|
|||
implements
|
||||
PhabricatorApplicationTransactionInterface,
|
||||
PhabricatorPolicyInterface,
|
||||
PhabricatorDestructibleInterface {
|
||||
PhabricatorDestructibleInterface,
|
||||
PhabricatorNgramsInterface {
|
||||
|
||||
protected $name;
|
||||
protected $mailKey;
|
||||
|
@ -114,4 +115,15 @@ final class AlmanacNetwork
|
|||
$this->delete();
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorNgramInterface )------------------------------------------ */
|
||||
|
||||
|
||||
public function newNgrams() {
|
||||
return array(
|
||||
id(new AlmanacNetworkNameNgrams())
|
||||
->setValue($this->getName()),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacNetworkNameNgrams
|
||||
extends PhabricatorSearchNgrams {
|
||||
|
||||
public function getNgramKey() {
|
||||
return 'networkname';
|
||||
}
|
||||
|
||||
public function getColumnName() {
|
||||
return 'name';
|
||||
}
|
||||
|
||||
public function getApplicationName() {
|
||||
return 'almanac';
|
||||
}
|
||||
|
||||
}
|
|
@ -24,20 +24,17 @@ final class AlmanacNetworkTransaction
|
|||
$new = $this->getNewValue();
|
||||
|
||||
switch ($this->getTransactionType()) {
|
||||
case self::TYPE_NAME:
|
||||
if ($old === null) {
|
||||
case PhabricatorTransactions::TYPE_CREATE:
|
||||
return pht(
|
||||
'%s created this network.',
|
||||
$this->renderHandleLink($author_phid));
|
||||
} else {
|
||||
case self::TYPE_NAME:
|
||||
return pht(
|
||||
'%s renamed this network from "%s" to "%s".',
|
||||
$this->renderHandleLink($author_phid),
|
||||
$old,
|
||||
$new);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return parent::getTitle();
|
||||
}
|
||||
|
|
|
@ -1,25 +1,33 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacProperty
|
||||
extends PhabricatorCustomFieldStorage
|
||||
extends AlmanacDAO
|
||||
implements PhabricatorPolicyInterface {
|
||||
|
||||
protected $objectPHID;
|
||||
protected $fieldIndex;
|
||||
protected $fieldName;
|
||||
protected $fieldValue;
|
||||
|
||||
private $object = self::ATTACHABLE;
|
||||
|
||||
public function getApplicationName() {
|
||||
return 'almanac';
|
||||
}
|
||||
|
||||
protected function getConfiguration() {
|
||||
$config = parent::getConfiguration();
|
||||
|
||||
$config[self::CONFIG_COLUMN_SCHEMA] += array(
|
||||
return array(
|
||||
self::CONFIG_TIMESTAMPS => false,
|
||||
self::CONFIG_SERIALIZATION => array(
|
||||
'fieldValue' => self::SERIALIZATION_JSON,
|
||||
),
|
||||
self::CONFIG_COLUMN_SCHEMA => array(
|
||||
'fieldIndex' => 'bytes12',
|
||||
'fieldName' => 'text128',
|
||||
);
|
||||
|
||||
return $config;
|
||||
),
|
||||
self::CONFIG_KEY_SCHEMA => array(
|
||||
'objectPHID' => array(
|
||||
'columns' => array('objectPHID', 'fieldIndex'),
|
||||
'unique' => true,
|
||||
),
|
||||
),
|
||||
) + parent::getConfiguration();
|
||||
}
|
||||
|
||||
public function getObject() {
|
||||
|
@ -31,39 +39,53 @@ final class AlmanacProperty
|
|||
return $this;
|
||||
}
|
||||
|
||||
public static function buildTransactions(
|
||||
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();
|
||||
|
||||
$attached_properties = $object->getAlmanacProperties();
|
||||
foreach ($properties as $key => $value) {
|
||||
if (empty($attached_properties[$key])) {
|
||||
$attached_properties[] = id(new AlmanacProperty())
|
||||
->setObjectPHID($object->getPHID())
|
||||
->setFieldName($key);
|
||||
}
|
||||
}
|
||||
$object->attachAlmanacProperties($attached_properties);
|
||||
|
||||
$field_list = PhabricatorCustomField::getObjectFields(
|
||||
$object,
|
||||
PhabricatorCustomField::ROLE_DEFAULT);
|
||||
$fields = $field_list->getFields();
|
||||
|
||||
$xactions = array();
|
||||
foreach ($properties as $name => $property) {
|
||||
foreach ($properties as $property) {
|
||||
$xactions[] = id(clone $template)
|
||||
->setTransactionType(PhabricatorTransactions::TYPE_CUSTOMFIELD)
|
||||
->setMetadataValue('customfield:key', $name)
|
||||
->setOldValue($object->getAlmanacPropertyValue($name))
|
||||
->setNewValue($property);
|
||||
->setTransactionType(AlmanacTransaction::TYPE_PROPERTY_REMOVE)
|
||||
->setMetadataValue('almanac.property', $property)
|
||||
->setNewValue(null);
|
||||
}
|
||||
|
||||
return $xactions;
|
||||
}
|
||||
|
||||
public function save() {
|
||||
$hash = PhabricatorHash::digestForIndex($this->getFieldName());
|
||||
$this->setFieldIndex($hash);
|
||||
|
||||
return parent::save();
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||
|
||||
|
|
|
@ -4,31 +4,42 @@ final class AlmanacService
|
|||
extends AlmanacDAO
|
||||
implements
|
||||
PhabricatorPolicyInterface,
|
||||
PhabricatorCustomFieldInterface,
|
||||
PhabricatorApplicationTransactionInterface,
|
||||
PhabricatorProjectInterface,
|
||||
AlmanacPropertyInterface,
|
||||
PhabricatorDestructibleInterface {
|
||||
PhabricatorDestructibleInterface,
|
||||
PhabricatorNgramsInterface,
|
||||
PhabricatorConduitResultInterface,
|
||||
PhabricatorExtendedPolicyInterface {
|
||||
|
||||
protected $name;
|
||||
protected $nameIndex;
|
||||
protected $mailKey;
|
||||
protected $viewPolicy;
|
||||
protected $editPolicy;
|
||||
protected $serviceClass;
|
||||
protected $isLocked;
|
||||
protected $serviceType;
|
||||
|
||||
private $customFields = self::ATTACHABLE;
|
||||
private $almanacProperties = 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())
|
||||
->setViewPolicy(PhabricatorPolicies::POLICY_USER)
|
||||
->setEditPolicy(PhabricatorPolicies::POLICY_ADMIN)
|
||||
->attachAlmanacProperties(array())
|
||||
->setIsLocked(0);
|
||||
->setServiceType($type)
|
||||
->attachServiceImplementation($implementation);
|
||||
}
|
||||
|
||||
protected function getConfiguration() {
|
||||
|
@ -38,8 +49,7 @@ final class AlmanacService
|
|||
'name' => 'text128',
|
||||
'nameIndex' => 'bytes12',
|
||||
'mailKey' => 'bytes20',
|
||||
'serviceClass' => 'text64',
|
||||
'isLocked' => 'bool',
|
||||
'serviceType' => 'text64',
|
||||
),
|
||||
self::CONFIG_KEY_SCHEMA => array(
|
||||
'key_name' => array(
|
||||
|
@ -49,8 +59,8 @@ final class AlmanacService
|
|||
'key_nametext' => array(
|
||||
'columns' => array('name'),
|
||||
),
|
||||
'key_class' => array(
|
||||
'columns' => array('serviceClass'),
|
||||
'key_servicetype' => array(
|
||||
'columns' => array('serviceType'),
|
||||
),
|
||||
),
|
||||
) + parent::getConfiguration();
|
||||
|
@ -61,7 +71,7 @@ final class AlmanacService
|
|||
}
|
||||
|
||||
public function save() {
|
||||
AlmanacNames::validateServiceOrDeviceName($this->getName());
|
||||
AlmanacNames::validateName($this->getName());
|
||||
|
||||
$this->nameIndex = PhabricatorHash::digestForIndex($this->getName());
|
||||
|
||||
|
@ -80,20 +90,37 @@ final class AlmanacService
|
|||
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) {
|
||||
$this->bindings = $bindings;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getServiceType() {
|
||||
return $this->assertAttached($this->serviceType);
|
||||
public function getServiceImplementation() {
|
||||
return $this->assertAttached($this->serviceImplementation);
|
||||
}
|
||||
|
||||
public function attachServiceType(AlmanacServiceType $type) {
|
||||
$this->serviceType = $type;
|
||||
public function attachServiceImplementation(AlmanacServiceType $type) {
|
||||
$this->serviceImplementation = $type;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isClusterService() {
|
||||
return $this->getServiceImplementation()->isClusterServiceType();
|
||||
}
|
||||
|
||||
|
||||
/* -( AlmanacPropertyInterface )------------------------------------------- */
|
||||
|
||||
|
@ -126,7 +153,11 @@ final class AlmanacService
|
|||
}
|
||||
|
||||
public function getAlmanacPropertyFieldSpecifications() {
|
||||
return $this->getServiceType()->getFieldSpecifications();
|
||||
return $this->getServiceImplementation()->getFieldSpecifications();
|
||||
}
|
||||
|
||||
public function newAlmanacPropertyEditEngine() {
|
||||
return new AlmanacServicePropertyEditEngine();
|
||||
}
|
||||
|
||||
|
||||
|
@ -145,51 +176,39 @@ final class AlmanacService
|
|||
case PhabricatorPolicyCapability::CAN_VIEW:
|
||||
return $this->getViewPolicy();
|
||||
case PhabricatorPolicyCapability::CAN_EDIT:
|
||||
if ($this->getIsLocked()) {
|
||||
return PhabricatorPolicies::POLICY_NOONE;
|
||||
} else {
|
||||
return $this->getEditPolicy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
switch ($capability) {
|
||||
case PhabricatorPolicyCapability::CAN_EDIT:
|
||||
if ($this->getIsLocked()) {
|
||||
return pht('This service is locked and can not be edited.');
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorCustomFieldInterface )------------------------------------ */
|
||||
/* -( PhabricatorExtendedPolicyInterface )--------------------------------- */
|
||||
|
||||
|
||||
public function getCustomFieldSpecificationForRole($role) {
|
||||
public function getExtendedPolicy($capability, PhabricatorUser $viewer) {
|
||||
switch ($capability) {
|
||||
case PhabricatorPolicyCapability::CAN_EDIT:
|
||||
if ($this->isClusterService()) {
|
||||
return array(
|
||||
array(
|
||||
new PhabricatorAlmanacApplication(),
|
||||
AlmanacManageClusterServicesCapability::CAPABILITY,
|
||||
),
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
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 )------------------------- */
|
||||
|
||||
|
@ -231,4 +250,48 @@ final class AlmanacService
|
|||
$this->delete();
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorNgramInterface )------------------------------------------ */
|
||||
|
||||
|
||||
public function newNgrams() {
|
||||
return array(
|
||||
id(new AlmanacServiceNameNgrams())
|
||||
->setValue($this->getName()),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorConduitResultInterface )---------------------------------- */
|
||||
|
||||
|
||||
public function getFieldSpecificationsForConduit() {
|
||||
return array(
|
||||
id(new PhabricatorConduitSearchFieldSpecification())
|
||||
->setKey('name')
|
||||
->setType('string')
|
||||
->setDescription(pht('The name of the service.')),
|
||||
id(new PhabricatorConduitSearchFieldSpecification())
|
||||
->setKey('serviceType')
|
||||
->setType('string')
|
||||
->setDescription(pht('The service type constant.')),
|
||||
);
|
||||
}
|
||||
|
||||
public function getFieldValuesForConduit() {
|
||||
return array(
|
||||
'name' => $this->getName(),
|
||||
'serviceType' => $this->getServiceType(),
|
||||
);
|
||||
}
|
||||
|
||||
public function getConduitSearchAttachments() {
|
||||
return array(
|
||||
id(new AlmanacPropertiesSearchEngineAttachment())
|
||||
->setAttachmentKey('properties'),
|
||||
id(new AlmanacBindingsSearchEngineAttachment())
|
||||
->setAttachmentKey('bindings'),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacServiceNameNgrams
|
||||
extends PhabricatorSearchNgrams {
|
||||
|
||||
public function getNgramKey() {
|
||||
return 'servicename';
|
||||
}
|
||||
|
||||
public function getColumnName() {
|
||||
return 'name';
|
||||
}
|
||||
|
||||
public function getApplicationName() {
|
||||
return 'almanac';
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue