mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-02 11:42:42 +01:00
(stable) Promote 2015 Week 35
This commit is contained in:
commit
5125045738
55 changed files with 1115 additions and 206 deletions
|
@ -11,7 +11,7 @@ return array(
|
||||||
'core.pkg.js' => 'a590b451',
|
'core.pkg.js' => 'a590b451',
|
||||||
'darkconsole.pkg.js' => 'e7393ebb',
|
'darkconsole.pkg.js' => 'e7393ebb',
|
||||||
'differential.pkg.css' => '2de124c9',
|
'differential.pkg.css' => '2de124c9',
|
||||||
'differential.pkg.js' => 'ebef29b1',
|
'differential.pkg.js' => '813c1633',
|
||||||
'diffusion.pkg.css' => '385e85b3',
|
'diffusion.pkg.css' => '385e85b3',
|
||||||
'diffusion.pkg.js' => '0115b37c',
|
'diffusion.pkg.js' => '0115b37c',
|
||||||
'maniphest.pkg.css' => '4845691a',
|
'maniphest.pkg.css' => '4845691a',
|
||||||
|
@ -407,7 +407,7 @@ return array(
|
||||||
'rsrc/js/application/releeph/releeph-preview-branch.js' => 'b2b4fbaf',
|
'rsrc/js/application/releeph/releeph-preview-branch.js' => 'b2b4fbaf',
|
||||||
'rsrc/js/application/releeph/releeph-request-state-change.js' => 'a0b57eb8',
|
'rsrc/js/application/releeph/releeph-request-state-change.js' => 'a0b57eb8',
|
||||||
'rsrc/js/application/releeph/releeph-request-typeahead.js' => 'de2e896f',
|
'rsrc/js/application/releeph/releeph-request-typeahead.js' => 'de2e896f',
|
||||||
'rsrc/js/application/repository/repository-crossreference.js' => 'bea81850',
|
'rsrc/js/application/repository/repository-crossreference.js' => 'e5339c43',
|
||||||
'rsrc/js/application/search/behavior-reorder-queries.js' => 'e9581f08',
|
'rsrc/js/application/search/behavior-reorder-queries.js' => 'e9581f08',
|
||||||
'rsrc/js/application/slowvote/behavior-slowvote-embed.js' => '887ad43f',
|
'rsrc/js/application/slowvote/behavior-slowvote-embed.js' => '887ad43f',
|
||||||
'rsrc/js/application/transactions/behavior-show-older-transactions.js' => 'dbbf48b6',
|
'rsrc/js/application/transactions/behavior-show-older-transactions.js' => 'dbbf48b6',
|
||||||
|
@ -643,7 +643,7 @@ return array(
|
||||||
'javelin-behavior-remarkup-preview' => 'f7379f45',
|
'javelin-behavior-remarkup-preview' => 'f7379f45',
|
||||||
'javelin-behavior-reorder-applications' => '76b9fc3e',
|
'javelin-behavior-reorder-applications' => '76b9fc3e',
|
||||||
'javelin-behavior-reorder-columns' => 'e1d25dfb',
|
'javelin-behavior-reorder-columns' => 'e1d25dfb',
|
||||||
'javelin-behavior-repository-crossreference' => 'bea81850',
|
'javelin-behavior-repository-crossreference' => 'e5339c43',
|
||||||
'javelin-behavior-scrollbar' => '834a1173',
|
'javelin-behavior-scrollbar' => '834a1173',
|
||||||
'javelin-behavior-search-reorder-queries' => 'e9581f08',
|
'javelin-behavior-search-reorder-queries' => 'e9581f08',
|
||||||
'javelin-behavior-select-on-click' => '4e3e79a6',
|
'javelin-behavior-select-on-click' => '4e3e79a6',
|
||||||
|
@ -1745,12 +1745,6 @@ return array(
|
||||||
'javelin-util',
|
'javelin-util',
|
||||||
'phabricator-shaped-request',
|
'phabricator-shaped-request',
|
||||||
),
|
),
|
||||||
'bea81850' => array(
|
|
||||||
'javelin-behavior',
|
|
||||||
'javelin-dom',
|
|
||||||
'javelin-stratcom',
|
|
||||||
'javelin-uri',
|
|
||||||
),
|
|
||||||
'c1700f6f' => array(
|
'c1700f6f' => array(
|
||||||
'javelin-install',
|
'javelin-install',
|
||||||
'javelin-util',
|
'javelin-util',
|
||||||
|
@ -1896,6 +1890,12 @@ return array(
|
||||||
'javelin-behavior',
|
'javelin-behavior',
|
||||||
'javelin-dom',
|
'javelin-dom',
|
||||||
),
|
),
|
||||||
|
'e5339c43' => array(
|
||||||
|
'javelin-behavior',
|
||||||
|
'javelin-dom',
|
||||||
|
'javelin-stratcom',
|
||||||
|
'javelin-uri',
|
||||||
|
),
|
||||||
'e5822781' => array(
|
'e5822781' => array(
|
||||||
'javelin-behavior',
|
'javelin-behavior',
|
||||||
'javelin-dom',
|
'javelin-dom',
|
||||||
|
|
1
resources/sql/autopatches/20150823.nuance.queue.1.sql
Normal file
1
resources/sql/autopatches/20150823.nuance.queue.1.sql
Normal file
|
@ -0,0 +1 @@
|
||||||
|
DROP TABLE {$NAMESPACE}_nuance.nuance_queueitem;
|
2
resources/sql/autopatches/20150823.nuance.queue.2.sql
Normal file
2
resources/sql/autopatches/20150823.nuance.queue.2.sql
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE {$NAMESPACE}_nuance.nuance_item
|
||||||
|
ADD queuePHID VARBINARY(64) NOT NULL;
|
2
resources/sql/autopatches/20150823.nuance.queue.3.sql
Normal file
2
resources/sql/autopatches/20150823.nuance.queue.3.sql
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE {$NAMESPACE}_nuance.nuance_source
|
||||||
|
ADD defaultQueuePHID VARBINARY(64) NOT NULL;
|
2
resources/sql/autopatches/20150823.nuance.queue.4.sql
Normal file
2
resources/sql/autopatches/20150823.nuance.queue.4.sql
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE {$NAMESPACE}_nuance.nuance_item
|
||||||
|
DROP dateNuanced;
|
|
@ -798,6 +798,7 @@ phutil_register_library_map(array(
|
||||||
'DrydockBlueprintCoreCustomField' => 'applications/drydock/customfield/DrydockBlueprintCoreCustomField.php',
|
'DrydockBlueprintCoreCustomField' => 'applications/drydock/customfield/DrydockBlueprintCoreCustomField.php',
|
||||||
'DrydockBlueprintCreateController' => 'applications/drydock/controller/DrydockBlueprintCreateController.php',
|
'DrydockBlueprintCreateController' => 'applications/drydock/controller/DrydockBlueprintCreateController.php',
|
||||||
'DrydockBlueprintCustomField' => 'applications/drydock/customfield/DrydockBlueprintCustomField.php',
|
'DrydockBlueprintCustomField' => 'applications/drydock/customfield/DrydockBlueprintCustomField.php',
|
||||||
|
'DrydockBlueprintDatasource' => 'applications/drydock/typeahead/DrydockBlueprintDatasource.php',
|
||||||
'DrydockBlueprintEditController' => 'applications/drydock/controller/DrydockBlueprintEditController.php',
|
'DrydockBlueprintEditController' => 'applications/drydock/controller/DrydockBlueprintEditController.php',
|
||||||
'DrydockBlueprintEditor' => 'applications/drydock/editor/DrydockBlueprintEditor.php',
|
'DrydockBlueprintEditor' => 'applications/drydock/editor/DrydockBlueprintEditor.php',
|
||||||
'DrydockBlueprintImplementation' => 'applications/drydock/blueprint/DrydockBlueprintImplementation.php',
|
'DrydockBlueprintImplementation' => 'applications/drydock/blueprint/DrydockBlueprintImplementation.php',
|
||||||
|
@ -822,6 +823,7 @@ phutil_register_library_map(array(
|
||||||
'DrydockInterface' => 'applications/drydock/interface/DrydockInterface.php',
|
'DrydockInterface' => 'applications/drydock/interface/DrydockInterface.php',
|
||||||
'DrydockLease' => 'applications/drydock/storage/DrydockLease.php',
|
'DrydockLease' => 'applications/drydock/storage/DrydockLease.php',
|
||||||
'DrydockLeaseController' => 'applications/drydock/controller/DrydockLeaseController.php',
|
'DrydockLeaseController' => 'applications/drydock/controller/DrydockLeaseController.php',
|
||||||
|
'DrydockLeaseDatasource' => 'applications/drydock/typeahead/DrydockLeaseDatasource.php',
|
||||||
'DrydockLeaseListController' => 'applications/drydock/controller/DrydockLeaseListController.php',
|
'DrydockLeaseListController' => 'applications/drydock/controller/DrydockLeaseListController.php',
|
||||||
'DrydockLeaseListView' => 'applications/drydock/view/DrydockLeaseListView.php',
|
'DrydockLeaseListView' => 'applications/drydock/view/DrydockLeaseListView.php',
|
||||||
'DrydockLeasePHIDType' => 'applications/drydock/phid/DrydockLeasePHIDType.php',
|
'DrydockLeasePHIDType' => 'applications/drydock/phid/DrydockLeasePHIDType.php',
|
||||||
|
@ -847,6 +849,7 @@ phutil_register_library_map(array(
|
||||||
'DrydockResource' => 'applications/drydock/storage/DrydockResource.php',
|
'DrydockResource' => 'applications/drydock/storage/DrydockResource.php',
|
||||||
'DrydockResourceCloseController' => 'applications/drydock/controller/DrydockResourceCloseController.php',
|
'DrydockResourceCloseController' => 'applications/drydock/controller/DrydockResourceCloseController.php',
|
||||||
'DrydockResourceController' => 'applications/drydock/controller/DrydockResourceController.php',
|
'DrydockResourceController' => 'applications/drydock/controller/DrydockResourceController.php',
|
||||||
|
'DrydockResourceDatasource' => 'applications/drydock/typeahead/DrydockResourceDatasource.php',
|
||||||
'DrydockResourceListController' => 'applications/drydock/controller/DrydockResourceListController.php',
|
'DrydockResourceListController' => 'applications/drydock/controller/DrydockResourceListController.php',
|
||||||
'DrydockResourceListView' => 'applications/drydock/view/DrydockResourceListView.php',
|
'DrydockResourceListView' => 'applications/drydock/view/DrydockResourceListView.php',
|
||||||
'DrydockResourcePHIDType' => 'applications/drydock/phid/DrydockResourcePHIDType.php',
|
'DrydockResourcePHIDType' => 'applications/drydock/phid/DrydockResourcePHIDType.php',
|
||||||
|
@ -1269,6 +1272,7 @@ phutil_register_library_map(array(
|
||||||
'MultimeterSampleController' => 'applications/multimeter/controller/MultimeterSampleController.php',
|
'MultimeterSampleController' => 'applications/multimeter/controller/MultimeterSampleController.php',
|
||||||
'MultimeterViewer' => 'applications/multimeter/storage/MultimeterViewer.php',
|
'MultimeterViewer' => 'applications/multimeter/storage/MultimeterViewer.php',
|
||||||
'NuanceConduitAPIMethod' => 'applications/nuance/conduit/NuanceConduitAPIMethod.php',
|
'NuanceConduitAPIMethod' => 'applications/nuance/conduit/NuanceConduitAPIMethod.php',
|
||||||
|
'NuanceConsoleController' => 'applications/nuance/controller/NuanceConsoleController.php',
|
||||||
'NuanceController' => 'applications/nuance/controller/NuanceController.php',
|
'NuanceController' => 'applications/nuance/controller/NuanceController.php',
|
||||||
'NuanceCreateItemConduitAPIMethod' => 'applications/nuance/conduit/NuanceCreateItemConduitAPIMethod.php',
|
'NuanceCreateItemConduitAPIMethod' => 'applications/nuance/conduit/NuanceCreateItemConduitAPIMethod.php',
|
||||||
'NuanceDAO' => 'applications/nuance/storage/NuanceDAO.php',
|
'NuanceDAO' => 'applications/nuance/storage/NuanceDAO.php',
|
||||||
|
@ -1284,9 +1288,9 @@ phutil_register_library_map(array(
|
||||||
'NuancePhabricatorFormSourceDefinition' => 'applications/nuance/source/NuancePhabricatorFormSourceDefinition.php',
|
'NuancePhabricatorFormSourceDefinition' => 'applications/nuance/source/NuancePhabricatorFormSourceDefinition.php',
|
||||||
'NuanceQuery' => 'applications/nuance/query/NuanceQuery.php',
|
'NuanceQuery' => 'applications/nuance/query/NuanceQuery.php',
|
||||||
'NuanceQueue' => 'applications/nuance/storage/NuanceQueue.php',
|
'NuanceQueue' => 'applications/nuance/storage/NuanceQueue.php',
|
||||||
|
'NuanceQueueDatasource' => 'applications/nuance/typeahead/NuanceQueueDatasource.php',
|
||||||
'NuanceQueueEditController' => 'applications/nuance/controller/NuanceQueueEditController.php',
|
'NuanceQueueEditController' => 'applications/nuance/controller/NuanceQueueEditController.php',
|
||||||
'NuanceQueueEditor' => 'applications/nuance/editor/NuanceQueueEditor.php',
|
'NuanceQueueEditor' => 'applications/nuance/editor/NuanceQueueEditor.php',
|
||||||
'NuanceQueueItem' => 'applications/nuance/storage/NuanceQueueItem.php',
|
|
||||||
'NuanceQueueListController' => 'applications/nuance/controller/NuanceQueueListController.php',
|
'NuanceQueueListController' => 'applications/nuance/controller/NuanceQueueListController.php',
|
||||||
'NuanceQueuePHIDType' => 'applications/nuance/phid/NuanceQueuePHIDType.php',
|
'NuanceQueuePHIDType' => 'applications/nuance/phid/NuanceQueuePHIDType.php',
|
||||||
'NuanceQueueQuery' => 'applications/nuance/query/NuanceQueueQuery.php',
|
'NuanceQueueQuery' => 'applications/nuance/query/NuanceQueueQuery.php',
|
||||||
|
@ -4478,6 +4482,7 @@ phutil_register_library_map(array(
|
||||||
),
|
),
|
||||||
'DrydockBlueprintCreateController' => 'DrydockBlueprintController',
|
'DrydockBlueprintCreateController' => 'DrydockBlueprintController',
|
||||||
'DrydockBlueprintCustomField' => 'PhabricatorCustomField',
|
'DrydockBlueprintCustomField' => 'PhabricatorCustomField',
|
||||||
|
'DrydockBlueprintDatasource' => 'PhabricatorTypeaheadDatasource',
|
||||||
'DrydockBlueprintEditController' => 'DrydockBlueprintController',
|
'DrydockBlueprintEditController' => 'DrydockBlueprintController',
|
||||||
'DrydockBlueprintEditor' => 'PhabricatorApplicationTransactionEditor',
|
'DrydockBlueprintEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||||
'DrydockBlueprintImplementation' => 'Phobject',
|
'DrydockBlueprintImplementation' => 'Phobject',
|
||||||
|
@ -4505,6 +4510,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorPolicyInterface',
|
'PhabricatorPolicyInterface',
|
||||||
),
|
),
|
||||||
'DrydockLeaseController' => 'DrydockController',
|
'DrydockLeaseController' => 'DrydockController',
|
||||||
|
'DrydockLeaseDatasource' => 'PhabricatorTypeaheadDatasource',
|
||||||
'DrydockLeaseListController' => 'DrydockLeaseController',
|
'DrydockLeaseListController' => 'DrydockLeaseController',
|
||||||
'DrydockLeaseListView' => 'AphrontView',
|
'DrydockLeaseListView' => 'AphrontView',
|
||||||
'DrydockLeasePHIDType' => 'PhabricatorPHIDType',
|
'DrydockLeasePHIDType' => 'PhabricatorPHIDType',
|
||||||
|
@ -4536,6 +4542,7 @@ phutil_register_library_map(array(
|
||||||
),
|
),
|
||||||
'DrydockResourceCloseController' => 'DrydockResourceController',
|
'DrydockResourceCloseController' => 'DrydockResourceController',
|
||||||
'DrydockResourceController' => 'DrydockController',
|
'DrydockResourceController' => 'DrydockController',
|
||||||
|
'DrydockResourceDatasource' => 'PhabricatorTypeaheadDatasource',
|
||||||
'DrydockResourceListController' => 'DrydockResourceController',
|
'DrydockResourceListController' => 'DrydockResourceController',
|
||||||
'DrydockResourceListView' => 'AphrontView',
|
'DrydockResourceListView' => 'AphrontView',
|
||||||
'DrydockResourcePHIDType' => 'PhabricatorPHIDType',
|
'DrydockResourcePHIDType' => 'PhabricatorPHIDType',
|
||||||
|
@ -5049,6 +5056,7 @@ phutil_register_library_map(array(
|
||||||
'MultimeterSampleController' => 'MultimeterController',
|
'MultimeterSampleController' => 'MultimeterController',
|
||||||
'MultimeterViewer' => 'MultimeterDimension',
|
'MultimeterViewer' => 'MultimeterDimension',
|
||||||
'NuanceConduitAPIMethod' => 'ConduitAPIMethod',
|
'NuanceConduitAPIMethod' => 'ConduitAPIMethod',
|
||||||
|
'NuanceConsoleController' => 'NuanceController',
|
||||||
'NuanceController' => 'PhabricatorController',
|
'NuanceController' => 'PhabricatorController',
|
||||||
'NuanceCreateItemConduitAPIMethod' => 'NuanceConduitAPIMethod',
|
'NuanceCreateItemConduitAPIMethod' => 'NuanceConduitAPIMethod',
|
||||||
'NuanceDAO' => 'PhabricatorLiskDAO',
|
'NuanceDAO' => 'PhabricatorLiskDAO',
|
||||||
|
@ -5072,9 +5080,9 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorPolicyInterface',
|
'PhabricatorPolicyInterface',
|
||||||
'PhabricatorApplicationTransactionInterface',
|
'PhabricatorApplicationTransactionInterface',
|
||||||
),
|
),
|
||||||
|
'NuanceQueueDatasource' => 'PhabricatorTypeaheadDatasource',
|
||||||
'NuanceQueueEditController' => 'NuanceController',
|
'NuanceQueueEditController' => 'NuanceController',
|
||||||
'NuanceQueueEditor' => 'PhabricatorApplicationTransactionEditor',
|
'NuanceQueueEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||||
'NuanceQueueItem' => 'NuanceDAO',
|
|
||||||
'NuanceQueueListController' => 'NuanceController',
|
'NuanceQueueListController' => 'NuanceController',
|
||||||
'NuanceQueuePHIDType' => 'PhabricatorPHIDType',
|
'NuanceQueuePHIDType' => 'PhabricatorPHIDType',
|
||||||
'NuanceQueueQuery' => 'NuanceQuery',
|
'NuanceQueueQuery' => 'NuanceQuery',
|
||||||
|
|
|
@ -949,6 +949,12 @@ final class PhabricatorAuditEditor
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getCustomWorkerStateEncoding() {
|
||||||
|
return array(
|
||||||
|
'rawPatch' => self::STORAGE_ENCODING_BINARY,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
protected function loadCustomWorkerState(array $state) {
|
protected function loadCustomWorkerState(array $state) {
|
||||||
$this->rawPatch = idx($state, 'rawPatch');
|
$this->rawPatch = idx($state, 'rawPatch');
|
||||||
$this->affectedFiles = idx($state, 'affectedFiles');
|
$this->affectedFiles = idx($state, 'affectedFiles');
|
||||||
|
|
|
@ -37,11 +37,25 @@ final class PhabricatorDashboardTextPanelType
|
||||||
PhabricatorDashboardPanelRenderingEngine $engine) {
|
PhabricatorDashboardPanelRenderingEngine $engine) {
|
||||||
|
|
||||||
$text = $panel->getProperty('text', '');
|
$text = $panel->getProperty('text', '');
|
||||||
|
$oneoff = id(new PhabricatorMarkupOneOff())->setContent($text);
|
||||||
|
$field = 'default';
|
||||||
|
|
||||||
$text_content = PhabricatorMarkupEngine::renderOneObject(
|
// NOTE: We're taking extra steps here to prevent creation of a text panel
|
||||||
id(new PhabricatorMarkupOneOff())->setContent($text),
|
// which embeds itself using `{Wnnn}`, recursing indefinitely.
|
||||||
'default',
|
|
||||||
$viewer);
|
$parent_key = PhabricatorDashboardRemarkupRule::KEY_PARENT_PANEL_PHIDS;
|
||||||
|
$parent_phids = $engine->getParentPanelPHIDs();
|
||||||
|
$parent_phids[] = $panel->getPHID();
|
||||||
|
|
||||||
|
$markup_engine = id(new PhabricatorMarkupEngine())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->setContextObject($panel)
|
||||||
|
->setAuxiliaryConfig($parent_key, $parent_phids);
|
||||||
|
|
||||||
|
$text_content = $markup_engine
|
||||||
|
->addObject($oneoff, $field)
|
||||||
|
->process()
|
||||||
|
->getOutput($oneoff, $field);
|
||||||
|
|
||||||
return id(new PHUIPropertyListView())
|
return id(new PHUIPropertyListView())
|
||||||
->addTextContent($text_content);
|
->addTextContent($text_content);
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
final class PhabricatorDashboardRemarkupRule
|
final class PhabricatorDashboardRemarkupRule
|
||||||
extends PhabricatorObjectRemarkupRule {
|
extends PhabricatorObjectRemarkupRule {
|
||||||
|
|
||||||
|
const KEY_PARENT_PANEL_PHIDS = 'dashboard.parentPanelPHIDs';
|
||||||
|
|
||||||
protected function getObjectNamePrefix() {
|
protected function getObjectNamePrefix() {
|
||||||
return 'W';
|
return 'W';
|
||||||
}
|
}
|
||||||
|
@ -21,12 +23,16 @@ final class PhabricatorDashboardRemarkupRule
|
||||||
PhabricatorObjectHandle $handle,
|
PhabricatorObjectHandle $handle,
|
||||||
$options) {
|
$options) {
|
||||||
|
|
||||||
$viewer = $this->getEngine()->getConfig('viewer');
|
$engine = $this->getEngine();
|
||||||
|
$viewer = $engine->getConfig('viewer');
|
||||||
|
|
||||||
|
$parent_key = self::KEY_PARENT_PANEL_PHIDS;
|
||||||
|
$parent_phids = $engine->getConfig($parent_key, array());
|
||||||
|
|
||||||
return id(new PhabricatorDashboardPanelRenderingEngine())
|
return id(new PhabricatorDashboardPanelRenderingEngine())
|
||||||
->setViewer($viewer)
|
->setViewer($viewer)
|
||||||
->setPanel($object)
|
->setPanel($object)
|
||||||
->setParentPanelPHIDs(array())
|
->setParentPanelPHIDs($parent_phids)
|
||||||
->renderPanel();
|
->renderPanel();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,9 @@ final class DifferentialCustomFieldRevertsParserTestCase
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
// This tests a degenerate regex behavior, see T9268.
|
||||||
|
'Reverts aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz' => array(),
|
||||||
|
|
||||||
"This doesn't revert anything" => array(),
|
"This doesn't revert anything" => array(),
|
||||||
'nonrevert of r11' => array(),
|
'nonrevert of r11' => array(),
|
||||||
'fixed a bug' => array(),
|
'fixed a bug' => array(),
|
||||||
|
|
|
@ -29,6 +29,9 @@ final class DrydockLeasePHIDType extends PhabricatorPHIDType {
|
||||||
$lease = $objects[$phid];
|
$lease = $objects[$phid];
|
||||||
$id = $lease->getID();
|
$id = $lease->getID();
|
||||||
|
|
||||||
|
$handle->setName(pht(
|
||||||
|
'Lease %d',
|
||||||
|
$id));
|
||||||
$handle->setURI("/drydock/lease/{$id}/");
|
$handle->setURI("/drydock/lease/{$id}/");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ final class DrydockResourcePHIDType extends PhabricatorPHIDType {
|
||||||
$resource = $objects[$phid];
|
$resource = $objects[$phid];
|
||||||
$id = $resource->getID();
|
$id = $resource->getID();
|
||||||
|
|
||||||
|
$handle->setName($resource->getName());
|
||||||
$handle->setURI("/drydock/resource/{$id}/");
|
$handle->setURI("/drydock/resource/{$id}/");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ final class DrydockBlueprintQuery extends DrydockQuery {
|
||||||
|
|
||||||
private $ids;
|
private $ids;
|
||||||
private $phids;
|
private $phids;
|
||||||
|
private $datasourceQuery;
|
||||||
|
|
||||||
public function withIDs(array $ids) {
|
public function withIDs(array $ids) {
|
||||||
$this->ids = $ids;
|
$this->ids = $ids;
|
||||||
|
@ -15,6 +16,11 @@ final class DrydockBlueprintQuery extends DrydockQuery {
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function withDatasourceQuery($query) {
|
||||||
|
$this->datasourceQuery = $query;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
protected function loadPage() {
|
protected function loadPage() {
|
||||||
$table = new DrydockBlueprint();
|
$table = new DrydockBlueprint();
|
||||||
$conn_r = $table->establishConnection('r');
|
$conn_r = $table->establishConnection('r');
|
||||||
|
@ -45,20 +51,27 @@ final class DrydockBlueprintQuery extends DrydockQuery {
|
||||||
protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
|
protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
|
||||||
$where = array();
|
$where = array();
|
||||||
|
|
||||||
if ($this->ids) {
|
if ($this->ids !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn_r,
|
$conn_r,
|
||||||
'id IN (%Ld)',
|
'id IN (%Ld)',
|
||||||
$this->ids);
|
$this->ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->phids) {
|
if ($this->phids !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn_r,
|
$conn_r,
|
||||||
'phid IN (%Ls)',
|
'phid IN (%Ls)',
|
||||||
$this->phids);
|
$this->phids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->datasourceQuery !== null) {
|
||||||
|
$where[] = qsprintf(
|
||||||
|
$conn_r,
|
||||||
|
'blueprintName LIKE %>',
|
||||||
|
$this->datasourceQuery);
|
||||||
|
}
|
||||||
|
|
||||||
return $this->formatWhereClause($where);
|
return $this->formatWhereClause($where);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ final class DrydockLeaseQuery extends DrydockQuery {
|
||||||
private $phids;
|
private $phids;
|
||||||
private $resourceIDs;
|
private $resourceIDs;
|
||||||
private $statuses;
|
private $statuses;
|
||||||
|
private $datasourceQuery;
|
||||||
|
|
||||||
public function withIDs(array $ids) {
|
public function withIDs(array $ids) {
|
||||||
$this->ids = $ids;
|
$this->ids = $ids;
|
||||||
|
@ -31,6 +32,11 @@ final class DrydockLeaseQuery extends DrydockQuery {
|
||||||
return new DrydockLease();
|
return new DrydockLease();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function withDatasourceQuery($query) {
|
||||||
|
$this->datasourceQuery = $query;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
protected function loadPage() {
|
protected function loadPage() {
|
||||||
return $this->loadStandardPage($this->newResultObject());
|
return $this->loadStandardPage($this->newResultObject());
|
||||||
}
|
}
|
||||||
|
@ -41,7 +47,7 @@ final class DrydockLeaseQuery extends DrydockQuery {
|
||||||
$resources = id(new DrydockResourceQuery())
|
$resources = id(new DrydockResourceQuery())
|
||||||
->setParentQuery($this)
|
->setParentQuery($this)
|
||||||
->setViewer($this->getViewer())
|
->setViewer($this->getViewer())
|
||||||
->withIDs($resource_ids)
|
->withIDs(array_unique($resource_ids))
|
||||||
->execute();
|
->execute();
|
||||||
} else {
|
} else {
|
||||||
$resources = array();
|
$resources = array();
|
||||||
|
@ -93,6 +99,13 @@ final class DrydockLeaseQuery extends DrydockQuery {
|
||||||
$this->statuses);
|
$this->statuses);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->datasourceQuery !== null) {
|
||||||
|
$where[] = qsprintf(
|
||||||
|
$conn,
|
||||||
|
'id = %d',
|
||||||
|
(int)$this->datasourceQuery);
|
||||||
|
}
|
||||||
|
|
||||||
return $where;
|
return $where;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ final class DrydockLogQuery extends DrydockQuery {
|
||||||
$resources = id(new DrydockResourceQuery())
|
$resources = id(new DrydockResourceQuery())
|
||||||
->setParentQuery($this)
|
->setParentQuery($this)
|
||||||
->setViewer($this->getViewer())
|
->setViewer($this->getViewer())
|
||||||
->withIDs($resource_ids)
|
->withIDs(array_unique($resource_ids))
|
||||||
->execute();
|
->execute();
|
||||||
} else {
|
} else {
|
||||||
$resources = array();
|
$resources = array();
|
||||||
|
@ -59,7 +59,7 @@ final class DrydockLogQuery extends DrydockQuery {
|
||||||
$leases = id(new DrydockLeaseQuery())
|
$leases = id(new DrydockLeaseQuery())
|
||||||
->setParentQuery($this)
|
->setParentQuery($this)
|
||||||
->setViewer($this->getViewer())
|
->setViewer($this->getViewer())
|
||||||
->withIDs($lease_ids)
|
->withIDs(array_unique($lease_ids))
|
||||||
->execute();
|
->execute();
|
||||||
} else {
|
} else {
|
||||||
$leases = array();
|
$leases = array();
|
||||||
|
@ -91,14 +91,14 @@ final class DrydockLogQuery extends DrydockQuery {
|
||||||
protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
|
protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
|
||||||
$where = array();
|
$where = array();
|
||||||
|
|
||||||
if ($this->resourceIDs) {
|
if ($this->resourceIDs !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn_r,
|
$conn_r,
|
||||||
'resourceID IN (%Ld)',
|
'resourceID IN (%Ld)',
|
||||||
$this->resourceIDs);
|
$this->resourceIDs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->leaseIDs) {
|
if ($this->leaseIDs !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn_r,
|
$conn_r,
|
||||||
'leaseID IN (%Ld)',
|
'leaseID IN (%Ld)',
|
||||||
|
|
|
@ -11,16 +11,71 @@ final class DrydockLogSearchEngine extends PhabricatorApplicationSearchEngine {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildSavedQueryFromRequest(AphrontRequest $request) {
|
public function buildSavedQueryFromRequest(AphrontRequest $request) {
|
||||||
return new PhabricatorSavedQuery();
|
$query = new PhabricatorSavedQuery();
|
||||||
|
|
||||||
|
$query->setParameter(
|
||||||
|
'resourcePHIDs',
|
||||||
|
$this->readListFromRequest($request, 'resources'));
|
||||||
|
$query->setParameter(
|
||||||
|
'leasePHIDs',
|
||||||
|
$this->readListFromRequest($request, 'leases'));
|
||||||
|
|
||||||
|
return $query;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
|
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
|
||||||
return new DrydockLogQuery();
|
$resource_phids = $saved->getParameter('resourcePHIDs', array());
|
||||||
|
$lease_phids = $saved->getParameter('leasePHIDs', array());
|
||||||
|
|
||||||
|
// TODO: Change logs to use PHIDs instead of IDs.
|
||||||
|
$resource_ids = array();
|
||||||
|
$lease_ids = array();
|
||||||
|
|
||||||
|
if ($resource_phids) {
|
||||||
|
$resource_ids = id(new DrydockResourceQuery())
|
||||||
|
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||||
|
->withPHIDs($resource_phids)
|
||||||
|
->execute();
|
||||||
|
$resource_ids = mpull($resource_ids, 'getID');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($lease_phids) {
|
||||||
|
$lease_ids = id(new DrydockLeaseQuery())
|
||||||
|
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||||
|
->withPHIDs($lease_phids)
|
||||||
|
->execute();
|
||||||
|
$lease_ids = mpull($lease_ids, 'getID');
|
||||||
|
}
|
||||||
|
|
||||||
|
$query = new DrydockLogQuery();
|
||||||
|
if ($resource_ids) {
|
||||||
|
$query->withResourceIDs($resource_ids);
|
||||||
|
}
|
||||||
|
if ($lease_ids) {
|
||||||
|
$query->withLeaseIDs($lease_ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $query;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildSearchForm(
|
public function buildSearchForm(
|
||||||
AphrontFormView $form,
|
AphrontFormView $form,
|
||||||
PhabricatorSavedQuery $saved) {}
|
PhabricatorSavedQuery $saved) {
|
||||||
|
|
||||||
|
$form
|
||||||
|
->appendControl(
|
||||||
|
id(new AphrontFormTokenizerControl())
|
||||||
|
->setDatasource(new DrydockResourceDatasource())
|
||||||
|
->setName('resources')
|
||||||
|
->setLabel(pht('Resources'))
|
||||||
|
->setValue($saved->getParameter('resourcePHIDs', array())))
|
||||||
|
->appendControl(
|
||||||
|
id(new AphrontFormTokenizerControl())
|
||||||
|
->setDatasource(new DrydockLeaseDatasource())
|
||||||
|
->setName('leases')
|
||||||
|
->setLabel(pht('Leases'))
|
||||||
|
->setValue($saved->getParameter('leasePHIDs', array())));
|
||||||
|
}
|
||||||
|
|
||||||
protected function getURI($path) {
|
protected function getURI($path) {
|
||||||
return '/drydock/log/'.$path;
|
return '/drydock/log/'.$path;
|
||||||
|
|
|
@ -7,6 +7,7 @@ final class DrydockResourceQuery extends DrydockQuery {
|
||||||
private $statuses;
|
private $statuses;
|
||||||
private $types;
|
private $types;
|
||||||
private $blueprintPHIDs;
|
private $blueprintPHIDs;
|
||||||
|
private $datasourceQuery;
|
||||||
|
|
||||||
public function withIDs(array $ids) {
|
public function withIDs(array $ids) {
|
||||||
$this->ids = $ids;
|
$this->ids = $ids;
|
||||||
|
@ -33,6 +34,11 @@ final class DrydockResourceQuery extends DrydockQuery {
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function withDatasourceQuery($query) {
|
||||||
|
$this->datasourceQuery = $query;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
protected function loadPage() {
|
protected function loadPage() {
|
||||||
$table = new DrydockResource();
|
$table = new DrydockResource();
|
||||||
$conn_r = $table->establishConnection('r');
|
$conn_r = $table->establishConnection('r');
|
||||||
|
@ -53,41 +59,48 @@ final class DrydockResourceQuery extends DrydockQuery {
|
||||||
protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
|
protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
|
||||||
$where = array();
|
$where = array();
|
||||||
|
|
||||||
if ($this->ids) {
|
if ($this->ids !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn_r,
|
$conn_r,
|
||||||
'id IN (%Ld)',
|
'id IN (%Ld)',
|
||||||
$this->ids);
|
$this->ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->phids) {
|
if ($this->phids !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn_r,
|
$conn_r,
|
||||||
'phid IN (%Ls)',
|
'phid IN (%Ls)',
|
||||||
$this->phids);
|
$this->phids);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->types) {
|
if ($this->types !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn_r,
|
$conn_r,
|
||||||
'type IN (%Ls)',
|
'type IN (%Ls)',
|
||||||
$this->types);
|
$this->types);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->statuses) {
|
if ($this->statuses !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn_r,
|
$conn_r,
|
||||||
'status IN (%Ls)',
|
'status IN (%Ls)',
|
||||||
$this->statuses);
|
$this->statuses);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->blueprintPHIDs) {
|
if ($this->blueprintPHIDs !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn_r,
|
$conn_r,
|
||||||
'blueprintPHID IN (%Ls)',
|
'blueprintPHID IN (%Ls)',
|
||||||
$this->blueprintPHIDs);
|
$this->blueprintPHIDs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->datasourceQuery !== null) {
|
||||||
|
$where[] = qsprintf(
|
||||||
|
$conn_r,
|
||||||
|
'name LIKE %>',
|
||||||
|
$this->datasourceQuery);
|
||||||
|
}
|
||||||
|
|
||||||
$where[] = $this->buildPagingClause($conn_r);
|
$where[] = $this->buildPagingClause($conn_r);
|
||||||
|
|
||||||
return $this->formatWhereClause($where);
|
return $this->formatWhereClause($where);
|
||||||
|
|
|
@ -40,7 +40,7 @@ final class DrydockBlueprint extends DrydockDAO
|
||||||
),
|
),
|
||||||
self::CONFIG_COLUMN_SCHEMA => array(
|
self::CONFIG_COLUMN_SCHEMA => array(
|
||||||
'className' => 'text255',
|
'className' => 'text255',
|
||||||
'blueprintName' => 'text255',
|
'blueprintName' => 'sort255',
|
||||||
),
|
),
|
||||||
) + parent::getConfiguration();
|
) + parent::getConfiguration();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class DrydockBlueprintDatasource
|
||||||
|
extends PhabricatorTypeaheadDatasource {
|
||||||
|
|
||||||
|
public function getPlaceholderText() {
|
||||||
|
return pht('Type a blueprint name...');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDatasourceApplicationClass() {
|
||||||
|
return 'PhabricatorDrydockApplication';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function loadResults() {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
$raw_query = $this->getRawQuery();
|
||||||
|
|
||||||
|
$blueprints = id(new DrydockBlueprintQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withDatasourceQuery($raw_query)
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$handles = id(new PhabricatorHandleQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withPHIDs(mpull($blueprints, 'getPHID'))
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$results = array();
|
||||||
|
foreach ($handles as $handle) {
|
||||||
|
$results[] = id(new PhabricatorTypeaheadResult())
|
||||||
|
->setName($handle->getName())
|
||||||
|
->setPHID($handle->getPHID());
|
||||||
|
}
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class DrydockLeaseDatasource
|
||||||
|
extends PhabricatorTypeaheadDatasource {
|
||||||
|
|
||||||
|
public function getPlaceholderText() {
|
||||||
|
return pht('Type a lease ID (exact match)...');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDatasourceApplicationClass() {
|
||||||
|
return 'PhabricatorDrydockApplication';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function loadResults() {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
$raw_query = $this->getRawQuery();
|
||||||
|
|
||||||
|
$leases = id(new DrydockLeaseQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withDatasourceQuery($raw_query)
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$handles = id(new PhabricatorHandleQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withPHIDs(mpull($leases, 'getPHID'))
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$results = array();
|
||||||
|
foreach ($handles as $handle) {
|
||||||
|
$results[] = id(new PhabricatorTypeaheadResult())
|
||||||
|
->setName($handle->getName())
|
||||||
|
->setPHID($handle->getPHID());
|
||||||
|
}
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class DrydockResourceDatasource
|
||||||
|
extends PhabricatorTypeaheadDatasource {
|
||||||
|
|
||||||
|
public function getPlaceholderText() {
|
||||||
|
return pht('Type a resource name...');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDatasourceApplicationClass() {
|
||||||
|
return 'PhabricatorDrydockApplication';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function loadResults() {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
$raw_query = $this->getRawQuery();
|
||||||
|
|
||||||
|
$resources = id(new DrydockResourceQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withDatasourceQuery($raw_query)
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$handles = id(new PhabricatorHandleQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withPHIDs(mpull($resources, 'getPHID'))
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$results = array();
|
||||||
|
foreach ($handles as $handle) {
|
||||||
|
$results[] = id(new PhabricatorTypeaheadResult())
|
||||||
|
->setName($handle->getName())
|
||||||
|
->setPHID($handle->getPHID());
|
||||||
|
}
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,13 +21,18 @@ final class DrydockLogListView extends AphrontView {
|
||||||
$resource_uri = '/drydock/resource/'.$log->getResourceID().'/';
|
$resource_uri = '/drydock/resource/'.$log->getResourceID().'/';
|
||||||
$lease_uri = '/drydock/lease/'.$log->getLeaseID().'/';
|
$lease_uri = '/drydock/lease/'.$log->getLeaseID().'/';
|
||||||
|
|
||||||
|
$resource_name = $log->getResourceID();
|
||||||
|
if ($log->getResourceID() !== null) {
|
||||||
|
$resource_name = $log->getResource()->getName();
|
||||||
|
}
|
||||||
|
|
||||||
$rows[] = array(
|
$rows[] = array(
|
||||||
phutil_tag(
|
phutil_tag(
|
||||||
'a',
|
'a',
|
||||||
array(
|
array(
|
||||||
'href' => $resource_uri,
|
'href' => $resource_uri,
|
||||||
),
|
),
|
||||||
$log->getResourceID()),
|
$resource_name),
|
||||||
phutil_tag(
|
phutil_tag(
|
||||||
'a',
|
'a',
|
||||||
array(
|
array(
|
||||||
|
@ -35,7 +40,7 @@ final class DrydockLogListView extends AphrontView {
|
||||||
),
|
),
|
||||||
$log->getLeaseID()),
|
$log->getLeaseID()),
|
||||||
$log->getMessage(),
|
$log->getMessage(),
|
||||||
phabricator_date($log->getEpoch(), $viewer),
|
phabricator_datetime($log->getEpoch(), $viewer),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ final class HarbormasterLeaseHostBuildStepImplementation
|
||||||
// Create the lease.
|
// Create the lease.
|
||||||
$lease = id(new DrydockLease())
|
$lease = id(new DrydockLease())
|
||||||
->setResourceType('host')
|
->setResourceType('host')
|
||||||
|
->setOwnerPHID($build_target->getPHID())
|
||||||
->setAttributes(
|
->setAttributes(
|
||||||
array(
|
array(
|
||||||
'platform' => $settings['platform'],
|
'platform' => $settings['platform'],
|
||||||
|
|
|
@ -234,11 +234,19 @@ final class LegalpadDocumentSignController extends LegalpadController {
|
||||||
$document,
|
$document,
|
||||||
PhabricatorPolicyCapability::CAN_EDIT);
|
PhabricatorPolicyCapability::CAN_EDIT);
|
||||||
|
|
||||||
|
// Use the last content update as the modified date. We don't want to
|
||||||
|
// show that a document like a TOS was "updated" by an incidental change
|
||||||
|
// to a field like the preamble or privacy settings which does not acutally
|
||||||
|
// affect the content of the agreement.
|
||||||
|
$content_updated = $document_body->getDateCreated();
|
||||||
|
|
||||||
|
// NOTE: We're avoiding `setPolicyObject()` here so we don't pick up
|
||||||
|
// extra UI elements that are unnecessary and clutter the signature page.
|
||||||
|
// These details are available on the "Manage" page.
|
||||||
$header = id(new PHUIHeaderView())
|
$header = id(new PHUIHeaderView())
|
||||||
->setHeader($title)
|
->setHeader($title)
|
||||||
->setUser($viewer)
|
->setUser($viewer)
|
||||||
->setPolicyObject($document)
|
->setEpoch($content_updated)
|
||||||
->setEpoch($document->getDateModified())
|
|
||||||
->addActionLink(
|
->addActionLink(
|
||||||
id(new PHUIButtonView())
|
id(new PHUIButtonView())
|
||||||
->setTag('a')
|
->setTag('a')
|
||||||
|
@ -258,15 +266,16 @@ final class LegalpadDocumentSignController extends LegalpadController {
|
||||||
'default',
|
'default',
|
||||||
$viewer);
|
$viewer);
|
||||||
|
|
||||||
|
// NOTE: We're avoiding `setObject()` here so we don't pick up extra UI
|
||||||
|
// elements like "Subscribers". This information is available on the
|
||||||
|
// "Manage" page, but just clutters up the "Signature" page.
|
||||||
$preamble = id(new PHUIPropertyListView())
|
$preamble = id(new PHUIPropertyListView())
|
||||||
->setUser($viewer)
|
->setUser($viewer)
|
||||||
->setObject($document)
|
|
||||||
->addSectionHeader(pht('Preamble'))
|
->addSectionHeader(pht('Preamble'))
|
||||||
->addTextContent($preamble_text);
|
->addTextContent($preamble_text);
|
||||||
|
|
||||||
$preamble_box = new PHUIPropertyGroupView();
|
$preamble_box = new PHUIPropertyGroupView();
|
||||||
$preamble_box->addPropertyList($preamble);
|
$preamble_box->addPropertyList($preamble);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$content = id(new PHUIDocumentView())
|
$content = id(new PHUIDocumentView())
|
||||||
|
|
|
@ -7,11 +7,18 @@ final class PhabricatorMailManagementVolumeWorkflow
|
||||||
$this
|
$this
|
||||||
->setName('volume')
|
->setName('volume')
|
||||||
->setSynopsis(
|
->setSynopsis(
|
||||||
pht('Show how much mail users have received in the last 30 days.'))
|
pht('Show how much mail users have received recently.'))
|
||||||
->setExamples(
|
->setExamples(
|
||||||
'**volume**')
|
'**volume**')
|
||||||
->setArguments(
|
->setArguments(
|
||||||
array(
|
array(
|
||||||
|
array(
|
||||||
|
'name' => 'days',
|
||||||
|
'param' => 'days',
|
||||||
|
'default' => 30,
|
||||||
|
'help' => pht(
|
||||||
|
'Number of days back (default 30).'),
|
||||||
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +26,16 @@ final class PhabricatorMailManagementVolumeWorkflow
|
||||||
$console = PhutilConsole::getConsole();
|
$console = PhutilConsole::getConsole();
|
||||||
$viewer = $this->getViewer();
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
$since = (PhabricatorTime::getNow() - phutil_units('30 days in seconds'));
|
$days = (int)$args->getArg('days');
|
||||||
|
if ($days < 1) {
|
||||||
|
throw new PhutilArgumentUsageException(
|
||||||
|
pht(
|
||||||
|
'Period specified with --days must be at least 1.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$duration = phutil_units("{$days} days in seconds");
|
||||||
|
|
||||||
|
$since = (PhabricatorTime::getNow() - $duration);
|
||||||
$until = PhabricatorTime::getNow();
|
$until = PhabricatorTime::getNow();
|
||||||
|
|
||||||
$mails = id(new PhabricatorMetaMTAMailQuery())
|
$mails = id(new PhabricatorMetaMTAMailQuery())
|
||||||
|
@ -95,7 +111,9 @@ final class PhabricatorMailManagementVolumeWorkflow
|
||||||
$table->draw();
|
$table->draw();
|
||||||
|
|
||||||
echo "\n";
|
echo "\n";
|
||||||
echo pht('Mail sent in the last 30 days.')."\n";
|
echo pht(
|
||||||
|
'Mail sent in the last %s day(s).',
|
||||||
|
new PhutilNumber($days))."\n";
|
||||||
echo pht(
|
echo pht(
|
||||||
'"Unfiltered" is raw volume before rules applied.')."\n";
|
'"Unfiltered" is raw volume before rules applied.')."\n";
|
||||||
echo pht(
|
echo pht(
|
||||||
|
|
|
@ -10,7 +10,7 @@ final class PhabricatorMetaMTAMail
|
||||||
const RETRY_DELAY = 5;
|
const RETRY_DELAY = 5;
|
||||||
|
|
||||||
protected $actorPHID;
|
protected $actorPHID;
|
||||||
protected $parameters;
|
protected $parameters = array();
|
||||||
protected $status;
|
protected $status;
|
||||||
protected $message;
|
protected $message;
|
||||||
protected $relatedPHID;
|
protected $relatedPHID;
|
||||||
|
@ -69,6 +69,13 @@ final class PhabricatorMetaMTAMail
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getParam($param, $default = null) {
|
protected function getParam($param, $default = null) {
|
||||||
|
// Some old mail was saved without parameters because no parameters were
|
||||||
|
// set or encoding failed. Recover in these cases so we can perform
|
||||||
|
// mail migrations, see T9251.
|
||||||
|
if (!is_array($this->parameters)) {
|
||||||
|
$this->parameters = array();
|
||||||
|
}
|
||||||
|
|
||||||
return idx($this->parameters, $param, $default);
|
return idx($this->parameters, $param, $default);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ final class PhabricatorNuanceApplication extends PhabricatorApplication {
|
||||||
public function getRoutes() {
|
public function getRoutes() {
|
||||||
return array(
|
return array(
|
||||||
'/nuance/' => array(
|
'/nuance/' => array(
|
||||||
|
'' => 'NuanceConsoleController',
|
||||||
'item/' => array(
|
'item/' => array(
|
||||||
'view/(?P<id>[1-9]\d*)/' => 'NuanceItemViewController',
|
'view/(?P<id>[1-9]\d*)/' => 'NuanceItemViewController',
|
||||||
'edit/(?P<id>[1-9]\d*)/' => 'NuanceItemEditController',
|
'edit/(?P<id>[1-9]\d*)/' => 'NuanceItemEditController',
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class NuanceConsoleController extends NuanceController {
|
||||||
|
|
||||||
|
public function shouldAllowPublic() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleRequest(AphrontRequest $request) {
|
||||||
|
$viewer = $request->getViewer();
|
||||||
|
|
||||||
|
$menu = id(new PHUIObjectItemListView())
|
||||||
|
->setUser($viewer);
|
||||||
|
|
||||||
|
$menu->addItem(
|
||||||
|
id(new PHUIObjectItemView())
|
||||||
|
->setHeader(pht('Queues'))
|
||||||
|
->setHref($this->getApplicationURI('queue/'))
|
||||||
|
->setFontIcon('fa-align-left')
|
||||||
|
->addAttribute(pht('Manage Nuance queues.')));
|
||||||
|
|
||||||
|
$menu->addItem(
|
||||||
|
id(new PHUIObjectItemView())
|
||||||
|
->setHeader(pht('Sources'))
|
||||||
|
->setHref($this->getApplicationURI('source/'))
|
||||||
|
->setFontIcon('fa-filter')
|
||||||
|
->addAttribute(pht('Manage Nuance sources.')));
|
||||||
|
|
||||||
|
$crumbs = $this->buildApplicationCrumbs();
|
||||||
|
$crumbs->addTextCrumb(pht('Console'));
|
||||||
|
|
||||||
|
$box = id(new PHUIObjectBoxView())
|
||||||
|
->setHeaderText(pht('Console'))
|
||||||
|
->setObjectList($menu);
|
||||||
|
|
||||||
|
return $this->buildApplicationPage(
|
||||||
|
array(
|
||||||
|
$crumbs,
|
||||||
|
$box,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'title' => pht('Nuance Console'),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -3,30 +3,102 @@
|
||||||
final class NuanceItemEditController extends NuanceController {
|
final class NuanceItemEditController extends NuanceController {
|
||||||
|
|
||||||
public function handleRequest(AphrontRequest $request) {
|
public function handleRequest(AphrontRequest $request) {
|
||||||
$viewer = $request->getViewer();
|
$viewer = $this->getViewer();
|
||||||
$id = $request->getURIData('id');
|
$id = $request->getURIData('id');
|
||||||
|
|
||||||
if (!$id) {
|
|
||||||
$item = new NuanceItem();
|
|
||||||
} else {
|
|
||||||
$item = id(new NuanceItemQuery())
|
$item = id(new NuanceItemQuery())
|
||||||
->setViewer($viewer)
|
->setViewer($viewer)
|
||||||
->withIDs(array($id))
|
->withIDs(array($id))
|
||||||
|
->requireCapabilities(
|
||||||
|
array(
|
||||||
|
PhabricatorPolicyCapability::CAN_VIEW,
|
||||||
|
PhabricatorPolicyCapability::CAN_EDIT,
|
||||||
|
))
|
||||||
->executeOne();
|
->executeOne();
|
||||||
}
|
|
||||||
|
|
||||||
if (!$item) {
|
if (!$item) {
|
||||||
return new Aphront404Response();
|
return new Aphront404Response();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$title = pht('Item %d', $item->getID());
|
||||||
|
|
||||||
$crumbs = $this->buildApplicationCrumbs();
|
$crumbs = $this->buildApplicationCrumbs();
|
||||||
$title = 'TODO';
|
$crumbs->addTextCrumb($title);
|
||||||
|
$crumbs->addTextCrumb(pht('Edit'));
|
||||||
|
|
||||||
|
$properties = $this->buildPropertyView($item);
|
||||||
|
$actions = $this->buildActionView($item);
|
||||||
|
$properties->setActionList($actions);
|
||||||
|
|
||||||
|
$box = id(new PHUIObjectBoxView())
|
||||||
|
->setHeaderText($title)
|
||||||
|
->addPropertyList($properties);
|
||||||
|
|
||||||
|
$timeline = $this->buildTransactionTimeline(
|
||||||
|
$item,
|
||||||
|
new NuanceItemTransactionQuery());
|
||||||
|
|
||||||
|
$timeline->setShouldTerminate(true);
|
||||||
|
|
||||||
return $this->buildApplicationPage(
|
return $this->buildApplicationPage(
|
||||||
|
array(
|
||||||
$crumbs,
|
$crumbs,
|
||||||
|
$box,
|
||||||
|
$timeline,
|
||||||
|
),
|
||||||
array(
|
array(
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function buildPropertyView(NuanceItem $item) {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
|
$properties = id(new PHUIPropertyListView())
|
||||||
|
->setUser($viewer)
|
||||||
|
->setObject($item);
|
||||||
|
|
||||||
|
$properties->addProperty(
|
||||||
|
pht('Date Created'),
|
||||||
|
phabricator_datetime($item->getDateCreated(), $viewer));
|
||||||
|
|
||||||
|
$properties->addProperty(
|
||||||
|
pht('Requestor'),
|
||||||
|
$viewer->renderHandle($item->getRequestorPHID()));
|
||||||
|
|
||||||
|
$properties->addProperty(
|
||||||
|
pht('Source'),
|
||||||
|
$viewer->renderHandle($item->getSourcePHID()));
|
||||||
|
|
||||||
|
$properties->addProperty(
|
||||||
|
pht('Queue'),
|
||||||
|
$viewer->renderHandle($item->getQueuePHID()));
|
||||||
|
|
||||||
|
$source = $item->getSource();
|
||||||
|
$definition = $source->requireDefinition();
|
||||||
|
|
||||||
|
$definition->renderItemEditProperties(
|
||||||
|
$viewer,
|
||||||
|
$item,
|
||||||
|
$properties);
|
||||||
|
|
||||||
|
return $properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildActionView(NuanceItem $item) {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
$id = $item->getID();
|
||||||
|
|
||||||
|
$actions = id(new PhabricatorActionListView())
|
||||||
|
->setUser($viewer);
|
||||||
|
|
||||||
|
$actions->addAction(
|
||||||
|
id(new PhabricatorActionView())
|
||||||
|
->setName(pht('View Item'))
|
||||||
|
->setIcon('fa-eye')
|
||||||
|
->setHref($this->getApplicationURI("item/view/{$id}/")));
|
||||||
|
|
||||||
|
return $actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,25 +3,84 @@
|
||||||
final class NuanceItemViewController extends NuanceController {
|
final class NuanceItemViewController extends NuanceController {
|
||||||
|
|
||||||
public function handleRequest(AphrontRequest $request) {
|
public function handleRequest(AphrontRequest $request) {
|
||||||
$viewer = $request->getViewer();
|
$viewer = $this->getViewer();
|
||||||
$id = $request->getURIData('id');
|
$id = $request->getURIData('id');
|
||||||
|
|
||||||
$item = id(new NuanceItemQuery())
|
$item = id(new NuanceItemQuery())
|
||||||
->setViewer($viewer)
|
->setViewer($viewer)
|
||||||
->withIDs(array($id))
|
->withIDs(array($id))
|
||||||
->executeOne();
|
->executeOne();
|
||||||
|
|
||||||
if (!$item) {
|
if (!$item) {
|
||||||
return new Aphront404Response();
|
return new Aphront404Response();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$title = pht('Item %d', $item->getID());
|
||||||
|
|
||||||
$crumbs = $this->buildApplicationCrumbs();
|
$crumbs = $this->buildApplicationCrumbs();
|
||||||
$title = 'TODO';
|
$crumbs->addTextCrumb($title);
|
||||||
|
|
||||||
|
$properties = $this->buildPropertyView($item);
|
||||||
|
$actions = $this->buildActionView($item);
|
||||||
|
$properties->setActionList($actions);
|
||||||
|
|
||||||
|
$box = id(new PHUIObjectBoxView())
|
||||||
|
->setHeaderText($title)
|
||||||
|
->addPropertyList($properties);
|
||||||
|
|
||||||
return $this->buildApplicationPage(
|
return $this->buildApplicationPage(
|
||||||
|
array(
|
||||||
$crumbs,
|
$crumbs,
|
||||||
|
$box,
|
||||||
|
),
|
||||||
array(
|
array(
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function buildPropertyView(NuanceItem $item) {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
|
$properties = id(new PHUIPropertyListView())
|
||||||
|
->setUser($viewer)
|
||||||
|
->setObject($item);
|
||||||
|
|
||||||
|
$properties->addProperty(
|
||||||
|
pht('Date Created'),
|
||||||
|
phabricator_datetime($item->getDateCreated(), $viewer));
|
||||||
|
|
||||||
|
$source = $item->getSource();
|
||||||
|
$definition = $source->requireDefinition();
|
||||||
|
|
||||||
|
$definition->renderItemViewProperties(
|
||||||
|
$viewer,
|
||||||
|
$item,
|
||||||
|
$properties);
|
||||||
|
|
||||||
|
return $properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildActionView(NuanceItem $item) {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
$id = $item->getID();
|
||||||
|
|
||||||
|
$actions = id(new PhabricatorActionListView())
|
||||||
|
->setUser($viewer);
|
||||||
|
|
||||||
|
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
||||||
|
$viewer,
|
||||||
|
$item,
|
||||||
|
PhabricatorPolicyCapability::CAN_EDIT);
|
||||||
|
|
||||||
|
$actions->addAction(
|
||||||
|
id(new PhabricatorActionView())
|
||||||
|
->setName(pht('Edit Item'))
|
||||||
|
->setIcon('fa-pencil')
|
||||||
|
->setHref($this->getApplicationURI("item/edit/{$id}/"))
|
||||||
|
->setDisabled(!$can_edit)
|
||||||
|
->setWorkflow(!$can_edit));
|
||||||
|
|
||||||
|
return $actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ final class NuanceSourceActionController extends NuanceController {
|
||||||
return new Aphront404Response();
|
return new Aphront404Response();
|
||||||
}
|
}
|
||||||
|
|
||||||
$def = NuanceSourceDefinition::getDefinitionForSource($source);
|
$def = $source->requireDefinition();
|
||||||
$def->setActor($viewer);
|
$def->setActor($viewer);
|
||||||
|
|
||||||
$response = $def->handleActionRequest($request);
|
$response = $def->handleActionRequest($request);
|
||||||
|
|
|
@ -41,7 +41,7 @@ final class NuanceSourceEditController extends NuanceController {
|
||||||
$cancel_uri = $source->getURI();
|
$cancel_uri = $source->getURI();
|
||||||
}
|
}
|
||||||
|
|
||||||
$definition = NuanceSourceDefinition::getDefinitionForSource($source);
|
$definition = $source->requireDefinition();
|
||||||
$definition->setActor($viewer);
|
$definition->setActor($viewer);
|
||||||
|
|
||||||
$response = $definition->buildEditLayout($request);
|
$response = $definition->buildEditLayout($request);
|
||||||
|
|
|
@ -13,7 +13,7 @@ final class NuanceSourceViewController extends NuanceController {
|
||||||
return new Aphront404Response();
|
return new Aphront404Response();
|
||||||
}
|
}
|
||||||
|
|
||||||
$source_phid = $source->getPHID();
|
$source_id = $source->getID();
|
||||||
|
|
||||||
$timeline = $this->buildTransactionTimeline(
|
$timeline = $this->buildTransactionTimeline(
|
||||||
$source,
|
$source,
|
||||||
|
@ -34,10 +34,29 @@ final class NuanceSourceViewController extends NuanceController {
|
||||||
|
|
||||||
$crumbs->addTextCrumb($title);
|
$crumbs->addTextCrumb($title);
|
||||||
|
|
||||||
|
|
||||||
|
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
||||||
|
$viewer,
|
||||||
|
$source,
|
||||||
|
PhabricatorPolicyCapability::CAN_EDIT);
|
||||||
|
|
||||||
|
$routing_list = id(new PHUIPropertyListView())
|
||||||
|
->addProperty(
|
||||||
|
pht('Default Queue'),
|
||||||
|
$viewer->renderHandle($source->getDefaultQueuePHID()));
|
||||||
|
|
||||||
|
$routing_header = id(new PHUIHeaderView())
|
||||||
|
->setHeader(pht('Routing Rules'));
|
||||||
|
|
||||||
|
$routing = id(new PHUIObjectBoxView())
|
||||||
|
->setHeader($routing_header)
|
||||||
|
->addPropertyList($routing_list);
|
||||||
|
|
||||||
return $this->buildApplicationPage(
|
return $this->buildApplicationPage(
|
||||||
array(
|
array(
|
||||||
$crumbs,
|
$crumbs,
|
||||||
$box,
|
$box,
|
||||||
|
$routing,
|
||||||
$timeline,
|
$timeline,
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
|
@ -77,6 +96,13 @@ final class NuanceSourceViewController extends NuanceController {
|
||||||
->setDisabled(!$can_edit)
|
->setDisabled(!$can_edit)
|
||||||
->setWorkflow(!$can_edit));
|
->setWorkflow(!$can_edit));
|
||||||
|
|
||||||
|
$request = $this->getRequest();
|
||||||
|
$definition = $source->requireDefinition();
|
||||||
|
$source_actions = $definition->getSourceViewActions($request);
|
||||||
|
foreach ($source_actions as $source_action) {
|
||||||
|
$actions->addAction($source_action);
|
||||||
|
}
|
||||||
|
|
||||||
return $actions;
|
return $actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +116,7 @@ final class NuanceSourceViewController extends NuanceController {
|
||||||
->setObject($source)
|
->setObject($source)
|
||||||
->setActionList($actions);
|
->setActionList($actions);
|
||||||
|
|
||||||
$definition = NuanceSourceDefinition::getDefinitionForSource($source);
|
$definition = $source->requireDefinition();
|
||||||
$properties->addProperty(
|
$properties->addProperty(
|
||||||
pht('Source Type'),
|
pht('Source Type'),
|
||||||
$definition->getName());
|
$definition->getName());
|
||||||
|
|
|
@ -18,6 +18,7 @@ final class NuanceItemEditor
|
||||||
$types[] = NuanceItemTransaction::TYPE_SOURCE;
|
$types[] = NuanceItemTransaction::TYPE_SOURCE;
|
||||||
$types[] = NuanceItemTransaction::TYPE_REQUESTOR;
|
$types[] = NuanceItemTransaction::TYPE_REQUESTOR;
|
||||||
$types[] = NuanceItemTransaction::TYPE_PROPERTY;
|
$types[] = NuanceItemTransaction::TYPE_PROPERTY;
|
||||||
|
$types[] = NuanceItemTransaction::TYPE_QUEUE;
|
||||||
|
|
||||||
$types[] = PhabricatorTransactions::TYPE_EDGE;
|
$types[] = PhabricatorTransactions::TYPE_EDGE;
|
||||||
$types[] = PhabricatorTransactions::TYPE_COMMENT;
|
$types[] = PhabricatorTransactions::TYPE_COMMENT;
|
||||||
|
@ -38,6 +39,8 @@ final class NuanceItemEditor
|
||||||
return $object->getSourcePHID();
|
return $object->getSourcePHID();
|
||||||
case NuanceItemTransaction::TYPE_OWNER:
|
case NuanceItemTransaction::TYPE_OWNER:
|
||||||
return $object->getOwnerPHID();
|
return $object->getOwnerPHID();
|
||||||
|
case NuanceItemTransaction::TYPE_QUEUE:
|
||||||
|
return $object->getQueuePHID();
|
||||||
case NuanceItemTransaction::TYPE_PROPERTY:
|
case NuanceItemTransaction::TYPE_PROPERTY:
|
||||||
$key = $xaction->getMetadataValue(
|
$key = $xaction->getMetadataValue(
|
||||||
NuanceItemTransaction::PROPERTY_KEY);
|
NuanceItemTransaction::PROPERTY_KEY);
|
||||||
|
@ -56,6 +59,7 @@ final class NuanceItemEditor
|
||||||
case NuanceItemTransaction::TYPE_SOURCE:
|
case NuanceItemTransaction::TYPE_SOURCE:
|
||||||
case NuanceItemTransaction::TYPE_OWNER:
|
case NuanceItemTransaction::TYPE_OWNER:
|
||||||
case NuanceItemTransaction::TYPE_PROPERTY:
|
case NuanceItemTransaction::TYPE_PROPERTY:
|
||||||
|
case NuanceItemTransaction::TYPE_QUEUE:
|
||||||
return $xaction->getNewValue();
|
return $xaction->getNewValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,6 +80,9 @@ final class NuanceItemEditor
|
||||||
case NuanceItemTransaction::TYPE_OWNER:
|
case NuanceItemTransaction::TYPE_OWNER:
|
||||||
$object->setOwnerPHID($xaction->getNewValue());
|
$object->setOwnerPHID($xaction->getNewValue());
|
||||||
break;
|
break;
|
||||||
|
case NuanceItemTransaction::TYPE_QUEUE:
|
||||||
|
$object->setQueuePHID($xaction->getNewValue());
|
||||||
|
break;
|
||||||
case NuanceItemTransaction::TYPE_PROPERTY:
|
case NuanceItemTransaction::TYPE_PROPERTY:
|
||||||
$key = $xaction->getMetadataValue(
|
$key = $xaction->getMetadataValue(
|
||||||
NuanceItemTransaction::PROPERTY_KEY);
|
NuanceItemTransaction::PROPERTY_KEY);
|
||||||
|
@ -93,6 +100,7 @@ final class NuanceItemEditor
|
||||||
case NuanceItemTransaction::TYPE_SOURCE:
|
case NuanceItemTransaction::TYPE_SOURCE:
|
||||||
case NuanceItemTransaction::TYPE_OWNER:
|
case NuanceItemTransaction::TYPE_OWNER:
|
||||||
case NuanceItemTransaction::TYPE_PROPERTY:
|
case NuanceItemTransaction::TYPE_PROPERTY:
|
||||||
|
case NuanceItemTransaction::TYPE_QUEUE:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ final class NuanceSourceEditor
|
||||||
$types = parent::getTransactionTypes();
|
$types = parent::getTransactionTypes();
|
||||||
|
|
||||||
$types[] = NuanceSourceTransaction::TYPE_NAME;
|
$types[] = NuanceSourceTransaction::TYPE_NAME;
|
||||||
|
$types[] = NuanceSourceTransaction::TYPE_DEFAULT_QUEUE;
|
||||||
|
|
||||||
$types[] = PhabricatorTransactions::TYPE_EDGE;
|
$types[] = PhabricatorTransactions::TYPE_EDGE;
|
||||||
$types[] = PhabricatorTransactions::TYPE_COMMENT;
|
$types[] = PhabricatorTransactions::TYPE_COMMENT;
|
||||||
|
@ -31,6 +32,8 @@ final class NuanceSourceEditor
|
||||||
switch ($xaction->getTransactionType()) {
|
switch ($xaction->getTransactionType()) {
|
||||||
case NuanceSourceTransaction::TYPE_NAME:
|
case NuanceSourceTransaction::TYPE_NAME:
|
||||||
return $object->getName();
|
return $object->getName();
|
||||||
|
case NuanceSourceTransaction::TYPE_DEFAULT_QUEUE:
|
||||||
|
return $object->getDefaultQueuePHID();
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::getCustomTransactionOldValue($object, $xaction);
|
return parent::getCustomTransactionOldValue($object, $xaction);
|
||||||
|
@ -42,6 +45,7 @@ final class NuanceSourceEditor
|
||||||
|
|
||||||
switch ($xaction->getTransactionType()) {
|
switch ($xaction->getTransactionType()) {
|
||||||
case NuanceSourceTransaction::TYPE_NAME:
|
case NuanceSourceTransaction::TYPE_NAME:
|
||||||
|
case NuanceSourceTransaction::TYPE_DEFAULT_QUEUE:
|
||||||
return $xaction->getNewValue();
|
return $xaction->getNewValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,6 +60,9 @@ final class NuanceSourceEditor
|
||||||
case NuanceSourceTransaction::TYPE_NAME:
|
case NuanceSourceTransaction::TYPE_NAME:
|
||||||
$object->setName($xaction->getNewValue());
|
$object->setName($xaction->getNewValue());
|
||||||
break;
|
break;
|
||||||
|
case NuanceSourceTransaction::TYPE_DEFAULT_QUEUE:
|
||||||
|
$object->setDefaultQueuePHID($xaction->getNewValue());
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,6 +72,7 @@ final class NuanceSourceEditor
|
||||||
|
|
||||||
switch ($xaction->getTransactionType()) {
|
switch ($xaction->getTransactionType()) {
|
||||||
case NuanceSourceTransaction::TYPE_NAME:
|
case NuanceSourceTransaction::TYPE_NAME:
|
||||||
|
case NuanceSourceTransaction::TYPE_DEFAULT_QUEUE:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,6 +103,19 @@ final class NuanceSourceEditor
|
||||||
$errors[] = $error;
|
$errors[] = $error;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case NuanceSourceTransaction::TYPE_DEFAULT_QUEUE:
|
||||||
|
foreach ($xactions as $xaction) {
|
||||||
|
if (!$xaction->getNewValue()) {
|
||||||
|
$error = new PhabricatorApplicationTransactionValidationError(
|
||||||
|
$type,
|
||||||
|
pht('Required'),
|
||||||
|
pht('Sources must have a default queue.'),
|
||||||
|
$xaction);
|
||||||
|
$error->setIsMissingFieldError(true);
|
||||||
|
$errors[] = $error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $errors;
|
return $errors;
|
||||||
|
|
|
@ -29,7 +29,9 @@ final class NuanceRequestorPHIDType extends PhabricatorPHIDType {
|
||||||
foreach ($handles as $phid => $handle) {
|
foreach ($handles as $phid => $handle) {
|
||||||
$requestor = $objects[$phid];
|
$requestor = $objects[$phid];
|
||||||
|
|
||||||
$handle->setName($requestor->getBestName());
|
// TODO: This is currently useless and should be far more informative.
|
||||||
|
$handle->setName(pht('Requestor %d', $requestor->getID()));
|
||||||
|
|
||||||
$handle->setURI($requestor->getURI());
|
$handle->setURI($requestor->getURI());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,25 +17,42 @@ final class NuanceItemQuery
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function withSourcePHIDs($source_phids) {
|
public function withSourcePHIDs(array $source_phids) {
|
||||||
$this->sourcePHIDs = $source_phids;
|
$this->sourcePHIDs = $source_phids;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function newResultObject() {
|
||||||
|
return new NuanceItem();
|
||||||
|
}
|
||||||
|
|
||||||
protected function loadPage() {
|
protected function loadPage() {
|
||||||
$table = new NuanceItem();
|
return $this->loadStandardPage($this->newResultObject());
|
||||||
$conn = $table->establishConnection('r');
|
}
|
||||||
|
|
||||||
$data = queryfx_all(
|
protected function willFilterPage(array $items) {
|
||||||
$conn,
|
$source_phids = mpull($items, 'getSourcePHID');
|
||||||
'%Q FROM %T %Q %Q %Q',
|
|
||||||
$this->buildSelectClause($conn),
|
|
||||||
$table->getTableName(),
|
|
||||||
$this->buildWhereClause($conn),
|
|
||||||
$this->buildOrderClause($conn),
|
|
||||||
$this->buildLimitClause($conn));
|
|
||||||
|
|
||||||
return $table->loadAllFromArray($data);
|
// NOTE: We always load sources, even if the viewer can't formally see
|
||||||
|
// them. If they can see the item, they're allowed to be aware of the
|
||||||
|
// source in some sense.
|
||||||
|
$sources = id(new NuanceSourceQuery())
|
||||||
|
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||||
|
->withPHIDs($source_phids)
|
||||||
|
->execute();
|
||||||
|
$sources = mpull($sources, null, 'getPHID');
|
||||||
|
|
||||||
|
foreach ($items as $key => $item) {
|
||||||
|
$source = idx($sources, $item->getSourcePHID());
|
||||||
|
if (!$source) {
|
||||||
|
$this->didRejectResult($items[$key]);
|
||||||
|
unset($items[$key]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$item->attachSource($source);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $items;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
|
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
|
||||||
|
|
|
@ -15,6 +15,17 @@ final class NuancePhabricatorFormSourceDefinition
|
||||||
return 'phabricator-form';
|
return 'phabricator-form';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getSourceViewActions(AphrontRequest $request) {
|
||||||
|
$actions = array();
|
||||||
|
|
||||||
|
$actions[] = id(new PhabricatorActionView())
|
||||||
|
->setName(pht('View Form'))
|
||||||
|
->setIcon('fa-align-justify')
|
||||||
|
->setHref($this->getActionURI());
|
||||||
|
|
||||||
|
return $actions;
|
||||||
|
}
|
||||||
|
|
||||||
public function updateItems() {
|
public function updateItems() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -50,7 +61,7 @@ final class NuancePhabricatorFormSourceDefinition
|
||||||
|
|
||||||
if ($request->isFormPost()) {
|
if ($request->isFormPost()) {
|
||||||
$properties = array(
|
$properties = array(
|
||||||
'complaint' => (string)$request->getStr('text'),
|
'complaint' => (string)$request->getStr('complaint'),
|
||||||
);
|
);
|
||||||
|
|
||||||
$content_source = PhabricatorContentSource::newFromRequest($request);
|
$content_source = PhabricatorContentSource::newFromRequest($request);
|
||||||
|
@ -89,4 +100,33 @@ final class NuancePhabricatorFormSourceDefinition
|
||||||
return $box;
|
return $box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function renderItemViewProperties(
|
||||||
|
PhabricatorUser $viewer,
|
||||||
|
NuanceItem $item,
|
||||||
|
PHUIPropertyListView $view) {
|
||||||
|
$this->renderItemCommonProperties($viewer, $item, $view);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function renderItemEditProperties(
|
||||||
|
PhabricatorUser $viewer,
|
||||||
|
NuanceItem $item,
|
||||||
|
PHUIPropertyListView $view) {
|
||||||
|
$this->renderItemCommonProperties($viewer, $item, $view);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function renderItemCommonProperties(
|
||||||
|
PhabricatorUser $viewer,
|
||||||
|
NuanceItem $item,
|
||||||
|
PHUIPropertyListView $view) {
|
||||||
|
|
||||||
|
$complaint = $item->getNuanceProperty('complaint');
|
||||||
|
$complaint = PhabricatorMarkupEngine::renderOneObject(
|
||||||
|
id(new PhabricatorMarkupOneOff())->setContent($complaint),
|
||||||
|
'default',
|
||||||
|
$viewer);
|
||||||
|
|
||||||
|
$view->addSectionHeader(pht('Complaint'));
|
||||||
|
$view->addTextContent($complaint);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,18 +43,8 @@ abstract class NuanceSourceDefinition extends Phobject {
|
||||||
return $source;
|
return $source;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function getSourceViewActions(AphrontRequest $request) {
|
||||||
* Gives a @{class:NuanceSourceDefinition} object for a given
|
return array();
|
||||||
* @{class:NuanceSource}. Note you still need to @{method:setActor}
|
|
||||||
* before the @{class:NuanceSourceDefinition} object will be useful.
|
|
||||||
*/
|
|
||||||
public static function getDefinitionForSource(NuanceSource $source) {
|
|
||||||
$definitions = self::getAllDefinitions();
|
|
||||||
$map = mpull($definitions, null, 'getSourceTypeConstant');
|
|
||||||
$definition = $map[$source->getType()];
|
|
||||||
$definition->setSourceObject($source);
|
|
||||||
|
|
||||||
return $definition;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getAllDefinitions() {
|
public static function getAllDefinitions() {
|
||||||
|
@ -179,7 +169,21 @@ abstract class NuanceSourceDefinition extends Phobject {
|
||||||
|
|
||||||
$form = $this->augmentEditForm($form, $ex);
|
$form = $this->augmentEditForm($form, $ex);
|
||||||
|
|
||||||
|
$default_phid = $source->getDefaultQueuePHID();
|
||||||
|
if ($default_phid) {
|
||||||
|
$default_queues = array($default_phid);
|
||||||
|
} else {
|
||||||
|
$default_queues = array();
|
||||||
|
}
|
||||||
|
|
||||||
$form
|
$form
|
||||||
|
->appendControl(
|
||||||
|
id(new AphrontFormTokenizerControl())
|
||||||
|
->setLabel(pht('Default Queue'))
|
||||||
|
->setName('defaultQueuePHIDs')
|
||||||
|
->setLimit(1)
|
||||||
|
->setDatasource(new NuanceQueueDatasource())
|
||||||
|
->setValue($default_queues))
|
||||||
->appendChild(
|
->appendChild(
|
||||||
id(new AphrontFormPolicyControl())
|
id(new AphrontFormPolicyControl())
|
||||||
->setUser($user)
|
->setUser($user)
|
||||||
|
@ -223,13 +227,19 @@ abstract class NuanceSourceDefinition extends Phobject {
|
||||||
$transactions[] = id(new NuanceSourceTransaction())
|
$transactions[] = id(new NuanceSourceTransaction())
|
||||||
->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY)
|
->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY)
|
||||||
->setNewValue($request->getStr('editPolicy'));
|
->setNewValue($request->getStr('editPolicy'));
|
||||||
|
|
||||||
$transactions[] = id(new NuanceSourceTransaction())
|
$transactions[] = id(new NuanceSourceTransaction())
|
||||||
->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)
|
->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)
|
||||||
->setNewValue($request->getStr('viewPolicy'));
|
->setNewValue($request->getStr('viewPolicy'));
|
||||||
|
|
||||||
$transactions[] = id(new NuanceSourceTransaction())
|
$transactions[] = id(new NuanceSourceTransaction())
|
||||||
->setTransactionType(NuanceSourceTransaction::TYPE_NAME)
|
->setTransactionType(NuanceSourceTransaction::TYPE_NAME)
|
||||||
->setNewvalue($request->getStr('name'));
|
->setNewvalue($request->getStr('name'));
|
||||||
|
|
||||||
|
$transactions[] = id(new NuanceSourceTransaction())
|
||||||
|
->setTransactionType(NuanceSourceTransaction::TYPE_DEFAULT_QUEUE)
|
||||||
|
->setNewvalue(head($request->getArr('defaultQueuePHIDs')));
|
||||||
|
|
||||||
return $transactions;
|
return $transactions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,6 +271,12 @@ abstract class NuanceSourceDefinition extends Phobject {
|
||||||
->setTransactionType(NuanceItemTransaction::TYPE_REQUESTOR)
|
->setTransactionType(NuanceItemTransaction::TYPE_REQUESTOR)
|
||||||
->setNewValue($requestor->getPHID());
|
->setNewValue($requestor->getPHID());
|
||||||
|
|
||||||
|
// TODO: Eventually, apply real routing rules. For now, just put everything
|
||||||
|
// in the default queue for the source.
|
||||||
|
$xactions[] = id(new NuanceItemTransaction())
|
||||||
|
->setTransactionType(NuanceItemTransaction::TYPE_QUEUE)
|
||||||
|
->setNewValue($source->getDefaultQueuePHID());
|
||||||
|
|
||||||
foreach ($properties as $key => $property) {
|
foreach ($properties as $key => $property) {
|
||||||
$xactions[] = id(new NuanceItemTransaction())
|
$xactions[] = id(new NuanceItemTransaction())
|
||||||
->setTransactionType(NuanceItemTransaction::TYPE_PROPERTY)
|
->setTransactionType(NuanceItemTransaction::TYPE_PROPERTY)
|
||||||
|
@ -278,6 +294,20 @@ abstract class NuanceSourceDefinition extends Phobject {
|
||||||
return $item;
|
return $item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function renderItemViewProperties(
|
||||||
|
PhabricatorUser $viewer,
|
||||||
|
NuanceItem $item,
|
||||||
|
PHUIPropertyListView $view) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function renderItemEditProperties(
|
||||||
|
PhabricatorUser $viewer,
|
||||||
|
NuanceItem $item,
|
||||||
|
PHUIPropertyListView $view) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -( Handling Action Requests )------------------------------------------- */
|
/* -( Handling Action Requests )------------------------------------------- */
|
||||||
|
|
||||||
|
@ -286,4 +316,9 @@ abstract class NuanceSourceDefinition extends Phobject {
|
||||||
return new Aphront404Response();
|
return new Aphront404Response();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getActionURI($path = null) {
|
||||||
|
$source_id = $this->getSourceObject()->getID();
|
||||||
|
return '/action/'.$source_id.'/'.ltrim($path, '/');
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,11 +17,12 @@ final class NuanceItem
|
||||||
protected $sourceLabel;
|
protected $sourceLabel;
|
||||||
protected $data = array();
|
protected $data = array();
|
||||||
protected $mailKey;
|
protected $mailKey;
|
||||||
protected $dateNuanced;
|
protected $queuePHID;
|
||||||
|
|
||||||
|
private $source = self::ATTACHABLE;
|
||||||
|
|
||||||
public static function initializeNewItem() {
|
public static function initializeNewItem() {
|
||||||
return id(new NuanceItem())
|
return id(new NuanceItem())
|
||||||
->setDateNuanced(time())
|
|
||||||
->setStatus(self::STATUS_OPEN);
|
->setStatus(self::STATUS_OPEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,17 +37,19 @@ final class NuanceItem
|
||||||
'sourceLabel' => 'text255?',
|
'sourceLabel' => 'text255?',
|
||||||
'status' => 'uint32',
|
'status' => 'uint32',
|
||||||
'mailKey' => 'bytes20',
|
'mailKey' => 'bytes20',
|
||||||
'dateNuanced' => 'epoch',
|
|
||||||
),
|
),
|
||||||
self::CONFIG_KEY_SCHEMA => array(
|
self::CONFIG_KEY_SCHEMA => array(
|
||||||
'key_source' => array(
|
'key_source' => array(
|
||||||
'columns' => array('sourcePHID', 'status', 'dateNuanced', 'id'),
|
'columns' => array('sourcePHID', 'status'),
|
||||||
),
|
),
|
||||||
'key_owner' => array(
|
'key_owner' => array(
|
||||||
'columns' => array('ownerPHID', 'status', 'dateNuanced', 'id'),
|
'columns' => array('ownerPHID', 'status'),
|
||||||
),
|
),
|
||||||
'key_contacter' => array(
|
'key_requestor' => array(
|
||||||
'columns' => array('requestorPHID', 'status', 'dateNuanced', 'id'),
|
'columns' => array('requestorPHID', 'status'),
|
||||||
|
),
|
||||||
|
'key_queue' => array(
|
||||||
|
'columns' => array('queuePHID', 'status'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
) + parent::getConfiguration();
|
) + parent::getConfiguration();
|
||||||
|
@ -142,7 +145,6 @@ final class NuanceItem
|
||||||
'sourceLabel' => $this->getSourceLabel(),
|
'sourceLabel' => $this->getSourceLabel(),
|
||||||
'dateCreated' => $this->getDateCreated(),
|
'dateCreated' => $this->getDateCreated(),
|
||||||
'dateModified' => $this->getDateModified(),
|
'dateModified' => $this->getDateModified(),
|
||||||
'dateNuanced' => $this->getDateNuanced(),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ final class NuanceItemTransaction
|
||||||
const TYPE_REQUESTOR = 'nuance.item.requestor';
|
const TYPE_REQUESTOR = 'nuance.item.requestor';
|
||||||
const TYPE_SOURCE = 'nuance.item.source';
|
const TYPE_SOURCE = 'nuance.item.source';
|
||||||
const TYPE_PROPERTY = 'nuance.item.property';
|
const TYPE_PROPERTY = 'nuance.item.property';
|
||||||
|
const TYPE_QUEUE = 'nuance.item.queue';
|
||||||
|
|
||||||
public function getApplicationTransactionType() {
|
public function getApplicationTransactionType() {
|
||||||
return NuanceItemPHIDType::TYPECONST;
|
return NuanceItemPHIDType::TYPECONST;
|
||||||
|
@ -18,4 +19,55 @@ final class NuanceItemTransaction
|
||||||
return new NuanceItemTransactionComment();
|
return new NuanceItemTransactionComment();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function shouldHide() {
|
||||||
|
$old = $this->getOldValue();
|
||||||
|
$type = $this->getTransactionType();
|
||||||
|
|
||||||
|
switch ($type) {
|
||||||
|
case self::TYPE_REQUESTOR:
|
||||||
|
case self::TYPE_SOURCE:
|
||||||
|
return ($old === null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::shouldHide();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRequiredHandlePHIDs() {
|
||||||
|
$old = $this->getOldValue();
|
||||||
|
$new = $this->getNewValue();
|
||||||
|
$type = $this->getTransactionType();
|
||||||
|
|
||||||
|
$phids = parent::getRequiredHandlePHIDs();
|
||||||
|
switch ($type) {
|
||||||
|
case self::TYPE_QUEUE:
|
||||||
|
if ($old) {
|
||||||
|
$phids[] = $old;
|
||||||
|
}
|
||||||
|
if ($new) {
|
||||||
|
$phids[] = $new;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $phids;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTitle() {
|
||||||
|
$old = $this->getOldValue();
|
||||||
|
$new = $this->getNewValue();
|
||||||
|
$type = $this->getTransactionType();
|
||||||
|
|
||||||
|
$author_phid = $this->getAuthorPHID();
|
||||||
|
|
||||||
|
switch ($type) {
|
||||||
|
case self::TYPE_QUEUE:
|
||||||
|
return pht(
|
||||||
|
'%s routed this item to the %s queue.',
|
||||||
|
$this->renderHandleLink($author_phid),
|
||||||
|
$this->renderHandleLink($new));
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::getTitle();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
final class NuanceQueueItem
|
|
||||||
extends NuanceDAO {
|
|
||||||
|
|
||||||
protected $queuePHID;
|
|
||||||
protected $itemPHID;
|
|
||||||
protected $itemStatus;
|
|
||||||
protected $itemDateNuanced;
|
|
||||||
|
|
||||||
protected function getConfiguration() {
|
|
||||||
return array(
|
|
||||||
self::CONFIG_COLUMN_SCHEMA => array(
|
|
||||||
'itemStatus' => 'uint32',
|
|
||||||
'itemDateNuanced' => 'epoch',
|
|
||||||
),
|
|
||||||
self::CONFIG_KEY_SCHEMA => array(
|
|
||||||
'key_one_per_queue' => array(
|
|
||||||
'columns' => array('itemPHID', 'queuePHID'),
|
|
||||||
'unique' => true,
|
|
||||||
),
|
|
||||||
'key_queue' => array(
|
|
||||||
'columns' => array(
|
|
||||||
'queuePHID',
|
|
||||||
'itemStatus',
|
|
||||||
'itemDateNuanced',
|
|
||||||
'id',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
) + parent::getConfiguration();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -12,4 +12,34 @@ final class NuanceQueueTransaction extends NuanceTransaction {
|
||||||
return new NuanceQueueTransactionComment();
|
return new NuanceQueueTransactionComment();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function shouldHide() {
|
||||||
|
$old = $this->getOldValue();
|
||||||
|
$type = $this->getTransactionType();
|
||||||
|
|
||||||
|
switch ($type) {
|
||||||
|
case self::TYPE_NAME:
|
||||||
|
return ($old === null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::shouldHide();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTitle() {
|
||||||
|
$old = $this->getOldValue();
|
||||||
|
$new = $this->getNewValue();
|
||||||
|
$type = $this->getTransactionType();
|
||||||
|
|
||||||
|
$author_phid = $this->getAuthorPHID();
|
||||||
|
|
||||||
|
switch ($type) {
|
||||||
|
case self::TYPE_NAME:
|
||||||
|
return pht(
|
||||||
|
'%s renamed this queue from "%s" to "%s".',
|
||||||
|
$this->renderHandleLink($author_phid),
|
||||||
|
$old,
|
||||||
|
$new);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::getTitle();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,9 @@ final class NuanceSource extends NuanceDAO
|
||||||
protected $mailKey;
|
protected $mailKey;
|
||||||
protected $viewPolicy;
|
protected $viewPolicy;
|
||||||
protected $editPolicy;
|
protected $editPolicy;
|
||||||
|
protected $defaultQueuePHID;
|
||||||
|
|
||||||
|
private $definition;
|
||||||
|
|
||||||
protected function getConfiguration() {
|
protected function getConfiguration() {
|
||||||
return array(
|
return array(
|
||||||
|
@ -62,6 +65,31 @@ final class NuanceSource extends NuanceDAO
|
||||||
->setEditPolicy($edit_policy);
|
->setEditPolicy($edit_policy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getDefinition() {
|
||||||
|
if ($this->definition === null) {
|
||||||
|
$definitions = NuanceSourceDefinition::getAllDefinitions();
|
||||||
|
if (isset($definitions[$this->getType()])) {
|
||||||
|
$definition = clone $definitions[$this->getType()];
|
||||||
|
$definition->setSourceObject($this);
|
||||||
|
$this->definition = $definition;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->definition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function requireDefinition() {
|
||||||
|
$definition = $this->getDefinition();
|
||||||
|
if (!$definition) {
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'Unable to load source definition implementation for source '.
|
||||||
|
'type "%s".',
|
||||||
|
$this->getType()));
|
||||||
|
}
|
||||||
|
return $definition;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
|
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
final class NuanceSourceTransaction
|
final class NuanceSourceTransaction
|
||||||
extends NuanceTransaction {
|
extends NuanceTransaction {
|
||||||
|
|
||||||
const TYPE_NAME = 'name-source';
|
const TYPE_NAME = 'source.name';
|
||||||
|
const TYPE_DEFAULT_QUEUE = 'source.queue.default';
|
||||||
|
|
||||||
public function getApplicationTransactionType() {
|
public function getApplicationTransactionType() {
|
||||||
return NuanceSourcePHIDType::TYPECONST;
|
return NuanceSourcePHIDType::TYPECONST;
|
||||||
|
@ -13,27 +14,63 @@ final class NuanceSourceTransaction
|
||||||
return new NuanceSourceTransactionComment();
|
return new NuanceSourceTransactionComment();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function shouldHide() {
|
||||||
|
$old = $this->getOldValue();
|
||||||
|
$new = $this->getNewValue();
|
||||||
|
$type = $this->getTransactionType();
|
||||||
|
|
||||||
|
switch ($type) {
|
||||||
|
case self::TYPE_DEFAULT_QUEUE:
|
||||||
|
return !$old;
|
||||||
|
case self::TYPE_NAME:
|
||||||
|
return ($old === null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::shouldHide();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRequiredHandlePHIDs() {
|
||||||
|
$old = $this->getOldValue();
|
||||||
|
$new = $this->getNewValue();
|
||||||
|
$type = $this->getTransactionType();
|
||||||
|
|
||||||
|
$phids = parent::getRequiredHandlePHIDs();
|
||||||
|
switch ($type) {
|
||||||
|
case self::TYPE_DEFAULT_QUEUE:
|
||||||
|
if ($old) {
|
||||||
|
$phids[] = $old;
|
||||||
|
}
|
||||||
|
if ($new) {
|
||||||
|
$phids[] = $new;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $phids;
|
||||||
|
}
|
||||||
|
|
||||||
public function getTitle() {
|
public function getTitle() {
|
||||||
$old = $this->getOldValue();
|
$old = $this->getOldValue();
|
||||||
$new = $this->getNewValue();
|
$new = $this->getNewValue();
|
||||||
|
$type = $this->getTransactionType();
|
||||||
$author_phid = $this->getAuthorPHID();
|
$author_phid = $this->getAuthorPHID();
|
||||||
|
|
||||||
switch ($this->getTransactionType()) {
|
switch ($type) {
|
||||||
case self::TYPE_NAME:
|
case self::TYPE_DEFAULT_QUEUE:
|
||||||
if ($old === null) {
|
|
||||||
return pht(
|
return pht(
|
||||||
'%s created this source.',
|
'%s changed the default queue from %s to %s.',
|
||||||
$this->renderHandleLink($author_phid));
|
$this->renderHandleLink($author_phid),
|
||||||
} else {
|
$this->renderHandleLink($old),
|
||||||
|
$this->renderHandleLink($new));
|
||||||
|
case self::TYPE_NAME:
|
||||||
return pht(
|
return pht(
|
||||||
'%s renamed this source from "%s" to "%s".',
|
'%s renamed this source from "%s" to "%s".',
|
||||||
$this->renderHandleLink($author_phid),
|
$this->renderHandleLink($author_phid),
|
||||||
$old,
|
$old,
|
||||||
$new);
|
$new);
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return parent::getTitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
38
src/applications/nuance/typeahead/NuanceQueueDatasource.php
Normal file
38
src/applications/nuance/typeahead/NuanceQueueDatasource.php
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class NuanceQueueDatasource
|
||||||
|
extends PhabricatorTypeaheadDatasource {
|
||||||
|
|
||||||
|
public function getBrowseTitle() {
|
||||||
|
return pht('Browse Queues');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPlaceholderText() {
|
||||||
|
return pht('Type a queue name...');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDatasourceApplicationClass() {
|
||||||
|
return 'PhabricatorNuanceApplication';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function loadResults() {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
$raw_query = $this->getRawQuery();
|
||||||
|
|
||||||
|
$results = array();
|
||||||
|
|
||||||
|
// TODO: Make this use real typeahead logic.
|
||||||
|
$query = new NuanceQueueQuery();
|
||||||
|
$queues = $this->executeQuery($query);
|
||||||
|
|
||||||
|
foreach ($queues as $queue) {
|
||||||
|
$results[] = id(new PhabricatorTypeaheadResult())
|
||||||
|
->setName($queue->getName())
|
||||||
|
->setURI('/nuance/queue/'.$queue->getID().'/')
|
||||||
|
->setPHID($queue->getPHID());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->filterResultsAgainstTokens($results);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -28,19 +28,12 @@ final class PhabricatorProjectColumnQuery
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function newResultObject() {
|
||||||
|
return new PhabricatorProjectColumn();
|
||||||
|
}
|
||||||
|
|
||||||
protected function loadPage() {
|
protected function loadPage() {
|
||||||
$table = new PhabricatorProjectColumn();
|
return $this->loadStandardPage($this->newResultObject());
|
||||||
$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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function willFilterPage(array $page) {
|
protected function willFilterPage(array $page) {
|
||||||
|
@ -60,6 +53,7 @@ final class PhabricatorProjectColumnQuery
|
||||||
$phid = $column->getProjectPHID();
|
$phid = $column->getProjectPHID();
|
||||||
$project = idx($projects, $phid);
|
$project = idx($projects, $phid);
|
||||||
if (!$project) {
|
if (!$project) {
|
||||||
|
$this->didRejectResult($page[$key]);
|
||||||
unset($page[$key]);
|
unset($page[$key]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -69,40 +63,38 @@ final class PhabricatorProjectColumnQuery
|
||||||
return $page;
|
return $page;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
|
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
|
||||||
$where = array();
|
$where = parent::buildWhereClauseParts($conn);
|
||||||
|
|
||||||
if ($this->ids) {
|
if ($this->ids !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn_r,
|
$conn,
|
||||||
'id IN (%Ld)',
|
'id IN (%Ld)',
|
||||||
$this->ids);
|
$this->ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->phids) {
|
if ($this->phids !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn_r,
|
$conn,
|
||||||
'phid IN (%Ls)',
|
'phid IN (%Ls)',
|
||||||
$this->phids);
|
$this->phids);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->projectPHIDs) {
|
if ($this->projectPHIDs !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn_r,
|
$conn,
|
||||||
'projectPHID IN (%Ls)',
|
'projectPHID IN (%Ls)',
|
||||||
$this->projectPHIDs);
|
$this->projectPHIDs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->statuses !== null) {
|
if ($this->statuses !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn_r,
|
$conn,
|
||||||
'status IN (%Ld)',
|
'status IN (%Ld)',
|
||||||
$this->statuses);
|
$this->statuses);
|
||||||
}
|
}
|
||||||
|
|
||||||
$where[] = $this->buildPagingClause($conn_r);
|
return $where;
|
||||||
|
|
||||||
return $this->formatWhereClause($where);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getQueryApplicationClass() {
|
public function getQueryApplicationClass() {
|
||||||
|
|
|
@ -69,6 +69,8 @@ abstract class PhabricatorApplicationTransactionEditor
|
||||||
private $feedNotifyPHIDs = array();
|
private $feedNotifyPHIDs = array();
|
||||||
private $feedRelatedPHIDs = array();
|
private $feedRelatedPHIDs = array();
|
||||||
|
|
||||||
|
const STORAGE_ENCODING_BINARY = 'binary';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the class name for the application this editor is a part of.
|
* Get the class name for the application this editor is a part of.
|
||||||
*
|
*
|
||||||
|
@ -2637,6 +2639,21 @@ abstract class PhabricatorApplicationTransactionEditor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @task mail
|
||||||
|
*/
|
||||||
|
private function runHeraldMailRules(array $messages) {
|
||||||
|
foreach ($messages as $message) {
|
||||||
|
$engine = new HeraldEngine();
|
||||||
|
$adapter = id(new PhabricatorMailOutboundMailHeraldAdapter())
|
||||||
|
->setObject($message);
|
||||||
|
|
||||||
|
$rules = $engine->loadRulesForAdapter($adapter);
|
||||||
|
$effects = $engine->applyRules($rules, $adapter);
|
||||||
|
$engine->applyEffects($effects, $adapter, $rules);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -( Publishing Feed Stories )-------------------------------------------- */
|
/* -( Publishing Feed Stories )-------------------------------------------- */
|
||||||
|
|
||||||
|
@ -3060,9 +3077,13 @@ abstract class PhabricatorApplicationTransactionEditor
|
||||||
$state[$property] = $this->$property;
|
$state[$property] = $this->$property;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$custom_state = $this->getCustomWorkerState();
|
||||||
|
$custom_encoding = $this->getCustomWorkerStateEncoding();
|
||||||
|
|
||||||
$state += array(
|
$state += array(
|
||||||
'excludeMailRecipientPHIDs' => $this->getExcludeMailRecipientPHIDs(),
|
'excludeMailRecipientPHIDs' => $this->getExcludeMailRecipientPHIDs(),
|
||||||
'custom' => $this->getCustomWorkerState(),
|
'custom' => $this->encodeStateForStorage($custom_state, $custom_encoding),
|
||||||
|
'custom.encoding' => $custom_encoding,
|
||||||
);
|
);
|
||||||
|
|
||||||
return $state;
|
return $state;
|
||||||
|
@ -3080,6 +3101,21 @@ abstract class PhabricatorApplicationTransactionEditor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook; return storage encoding for custom properties which need to be
|
||||||
|
* passed to workers.
|
||||||
|
*
|
||||||
|
* This primarily allows binary data to be passed to workers and survive
|
||||||
|
* JSON encoding.
|
||||||
|
*
|
||||||
|
* @return dict<string, string> Property encodings.
|
||||||
|
* @task workers
|
||||||
|
*/
|
||||||
|
protected function getCustomWorkerStateEncoding() {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load editor state using a dictionary emitted by @{method:getWorkerState}.
|
* Load editor state using a dictionary emitted by @{method:getWorkerState}.
|
||||||
*
|
*
|
||||||
|
@ -3097,7 +3133,10 @@ abstract class PhabricatorApplicationTransactionEditor
|
||||||
$exclude = idx($state, 'excludeMailRecipientPHIDs', array());
|
$exclude = idx($state, 'excludeMailRecipientPHIDs', array());
|
||||||
$this->setExcludeMailRecipientPHIDs($exclude);
|
$this->setExcludeMailRecipientPHIDs($exclude);
|
||||||
|
|
||||||
$custom = idx($state, 'custom', array());
|
$custom_state = idx($state, 'custom', array());
|
||||||
|
$custom_encodings = idx($state, 'custom.encoding', array());
|
||||||
|
$custom = $this->decodeStateFromStorage($custom_state, $custom_encodings);
|
||||||
|
|
||||||
$this->loadCustomWorkerState($custom);
|
$this->loadCustomWorkerState($custom);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
|
@ -3143,16 +3182,85 @@ abstract class PhabricatorApplicationTransactionEditor
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function runHeraldMailRules(array $messages) {
|
/**
|
||||||
foreach ($messages as $message) {
|
* Apply encodings prior to storage.
|
||||||
$engine = new HeraldEngine();
|
*
|
||||||
$adapter = id(new PhabricatorMailOutboundMailHeraldAdapter())
|
* See @{method:getCustomWorkerStateEncoding}.
|
||||||
->setObject($message);
|
*
|
||||||
|
* @param map<string, wild> Map of values to encode.
|
||||||
|
* @param map<string, string> Map of encodings to apply.
|
||||||
|
* @return map<string, wild> Map of encoded values.
|
||||||
|
* @task workers
|
||||||
|
*/
|
||||||
|
final private function encodeStateForStorage(
|
||||||
|
array $state,
|
||||||
|
array $encodings) {
|
||||||
|
|
||||||
$rules = $engine->loadRulesForAdapter($adapter);
|
foreach ($state as $key => $value) {
|
||||||
$effects = $engine->applyRules($rules, $adapter);
|
$encoding = idx($encodings, $key);
|
||||||
$engine->applyEffects($effects, $adapter, $rules);
|
switch ($encoding) {
|
||||||
|
case self::STORAGE_ENCODING_BINARY:
|
||||||
|
// The mechanics of this encoding (serialize + base64) are a little
|
||||||
|
// awkward, but it allows us encode arrays and still be JSON-safe
|
||||||
|
// with binary data.
|
||||||
|
|
||||||
|
$value = @serialize($value);
|
||||||
|
if ($value === false) {
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'Failed to serialize() value for key "%s".',
|
||||||
|
$key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$value = base64_encode($value);
|
||||||
|
if ($value === false) {
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'Failed to base64 encode value for key "%s".',
|
||||||
|
$key));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$state[$key] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $state;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Undo storage encoding applied when storing state.
|
||||||
|
*
|
||||||
|
* See @{method:getCustomWorkerStateEncoding}.
|
||||||
|
*
|
||||||
|
* @param map<string, wild> Map of encoded values.
|
||||||
|
* @param map<string, string> Map of encodings.
|
||||||
|
* @return map<string, wild> Map of decoded values.
|
||||||
|
* @task workers
|
||||||
|
*/
|
||||||
|
final private function decodeStateFromStorage(
|
||||||
|
array $state,
|
||||||
|
array $encodings) {
|
||||||
|
|
||||||
|
foreach ($state as $key => $value) {
|
||||||
|
$encoding = idx($encodings, $key);
|
||||||
|
switch ($encoding) {
|
||||||
|
case self::STORAGE_ENCODING_BINARY:
|
||||||
|
$value = base64_decode($value);
|
||||||
|
if ($value === false) {
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'Failed to base64_decode() value for key "%s".',
|
||||||
|
$key));
|
||||||
|
}
|
||||||
|
|
||||||
|
$value = unserialize($value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$state[$key] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $state;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,9 +26,14 @@ final class PhabricatorApplicationTransactionPublishWorker
|
||||||
* Load the object the transactions affect.
|
* Load the object the transactions affect.
|
||||||
*/
|
*/
|
||||||
private function loadObject() {
|
private function loadObject() {
|
||||||
$data = $this->getTaskData();
|
|
||||||
$viewer = PhabricatorUser::getOmnipotentUser();
|
$viewer = PhabricatorUser::getOmnipotentUser();
|
||||||
|
|
||||||
|
$data = $this->getTaskData();
|
||||||
|
if (!is_array($data)) {
|
||||||
|
throw new PhabricatorWorkerPermanentFailureException(
|
||||||
|
pht('Task has invalid task data.'));
|
||||||
|
}
|
||||||
|
|
||||||
$phid = idx($data, 'objectPHID');
|
$phid = idx($data, 'objectPHID');
|
||||||
if (!$phid) {
|
if (!$phid) {
|
||||||
throw new PhabricatorWorkerPermanentFailureException(
|
throw new PhabricatorWorkerPermanentFailureException(
|
||||||
|
|
|
@ -65,7 +65,7 @@ write such a script, and run this command to see its output:
|
||||||
To actually build the symbol index, pipe this data to the
|
To actually build the symbol index, pipe this data to the
|
||||||
`import_repository_symbols.php` script, providing the repository callsign:
|
`import_repository_symbols.php` script, providing the repository callsign:
|
||||||
|
|
||||||
$ ./scripts/symbols/import_repository_symbols.php rREPO < symbols_data
|
$ ./scripts/symbols/import_repository_symbols.php REPO < symbols_data
|
||||||
|
|
||||||
Then just set up a cronjob to run that however often you like.
|
Then just set up a cronjob to run that however often you like.
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,8 @@ abstract class PhabricatorCustomFieldMonogramParser
|
||||||
'(?:^|\b)'.
|
'(?:^|\b)'.
|
||||||
$prefix_regex.
|
$prefix_regex.
|
||||||
$infix_regex.
|
$infix_regex.
|
||||||
'((?:'.$monogram_pattern.'[,\s]*)+)'.
|
'((?:'.$monogram_pattern.'(?:\b|$)[,\s]*)+)'.
|
||||||
'(?:\band\s+('.$monogram_pattern.'))?'.
|
'(?:\band\s+('.$monogram_pattern.'(?:\b|$)))?'.
|
||||||
$suffix_regex.
|
$suffix_regex.
|
||||||
'(?:$|\b)'.
|
'(?:$|\b)'.
|
||||||
'/';
|
'/';
|
||||||
|
|
|
@ -1369,6 +1369,11 @@ final class PhabricatorUSEnglishTranslation
|
||||||
'This action has no effect on targets: %2$s.',
|
'This action has no effect on targets: %2$s.',
|
||||||
),
|
),
|
||||||
|
|
||||||
|
'Mail sent in the last %s day(s).' => array(
|
||||||
|
'Mail sent in the last day.',
|
||||||
|
'Mail sent in the last %s days.',
|
||||||
|
),
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,7 @@ final class PhabricatorMarkupEngine extends Phobject {
|
||||||
private $contextObject;
|
private $contextObject;
|
||||||
private $version = 15;
|
private $version = 15;
|
||||||
private $engineCaches = array();
|
private $engineCaches = array();
|
||||||
|
private $auxiliaryConfig = array();
|
||||||
|
|
||||||
|
|
||||||
/* -( Markup Pipeline )---------------------------------------------------- */
|
/* -( Markup Pipeline )---------------------------------------------------- */
|
||||||
|
@ -122,6 +123,10 @@ final class PhabricatorMarkupEngine extends Phobject {
|
||||||
$engines[$key] = $info['object']->newMarkupEngine($info['field']);
|
$engines[$key] = $info['object']->newMarkupEngine($info['field']);
|
||||||
$engines[$key]->setConfig('viewer', $this->viewer);
|
$engines[$key]->setConfig('viewer', $this->viewer);
|
||||||
$engines[$key]->setConfig('contextObject', $this->contextObject);
|
$engines[$key]->setConfig('contextObject', $this->contextObject);
|
||||||
|
|
||||||
|
foreach ($this->auxiliaryConfig as $aux_key => $aux_value) {
|
||||||
|
$engines[$key]->setConfig($aux_key, $aux_value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load or build the preprocessor caches.
|
// Load or build the preprocessor caches.
|
||||||
|
@ -310,6 +315,12 @@ final class PhabricatorMarkupEngine extends Phobject {
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setAuxiliaryConfig($key, $value) {
|
||||||
|
// TODO: This is gross and should be removed. Avoid use.
|
||||||
|
$this->auxiliaryConfig[$key] = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -( Engine Construction )------------------------------------------------ */
|
/* -( Engine Construction )------------------------------------------------ */
|
||||||
|
|
||||||
|
|
|
@ -1651,7 +1651,7 @@ abstract class LiskDAO extends Phobject {
|
||||||
if ($deserialize) {
|
if ($deserialize) {
|
||||||
$data[$col] = json_decode($data[$col], true);
|
$data[$col] = json_decode($data[$col], true);
|
||||||
} else {
|
} else {
|
||||||
$data[$col] = json_encode($data[$col]);
|
$data[$col] = phutil_json_encode($data[$col]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -40,8 +40,7 @@ JX.behavior('repository-crossreference', function(config, statics) {
|
||||||
'tag:span',
|
'tag:span',
|
||||||
function(e) {
|
function(e) {
|
||||||
if (e.getType() === 'mouseout') {
|
if (e.getType() === 'mouseout') {
|
||||||
highlighted && JX.DOM.alterClass(highlighted, classHighlight, false);
|
unhighlight();
|
||||||
highlighted = null;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!isSignalkey(e)) {
|
if (!isSignalkey(e)) {
|
||||||
|
@ -59,10 +58,14 @@ JX.behavior('repository-crossreference', function(config, statics) {
|
||||||
target = target.parentNode;
|
target = target.parentNode;
|
||||||
}
|
}
|
||||||
} else if (e.getType() === 'click') {
|
} else if (e.getType() === 'click') {
|
||||||
openSearch(highlighted, lang);
|
openSearch(e.getTarget(), lang);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
function unhighlight() {
|
||||||
|
highlighted && JX.DOM.alterClass(highlighted, classHighlight, false);
|
||||||
|
highlighted = null;
|
||||||
|
}
|
||||||
|
|
||||||
function openSearch(target, lang) {
|
function openSearch(target, lang) {
|
||||||
var symbol = target.textContent || target.innerText;
|
var symbol = target.textContent || target.innerText;
|
||||||
|
@ -110,6 +113,7 @@ JX.behavior('repository-crossreference', function(config, statics) {
|
||||||
linkAll(e.getData().container);
|
linkAll(e.getData().container);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
JX.Stratcom.listen(
|
JX.Stratcom.listen(
|
||||||
['keydown', 'keyup'],
|
['keydown', 'keyup'],
|
||||||
null,
|
null,
|
||||||
|
@ -117,14 +121,28 @@ JX.behavior('repository-crossreference', function(config, statics) {
|
||||||
if (e.getRawEvent().keyCode !== signalKey) {
|
if (e.getRawEvent().keyCode !== signalKey) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
statics.active = (e.getType() === 'keydown');
|
setCursorMode(e.getType() === 'keydown');
|
||||||
|
|
||||||
|
if (!statics.active) {
|
||||||
|
unhighlight();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
JX.Stratcom.listen(
|
||||||
|
'blur',
|
||||||
|
null,
|
||||||
|
function(e) {
|
||||||
|
if (e.getTarget()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
unhighlight();
|
||||||
|
setCursorMode(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
function setCursorMode(active) {
|
||||||
|
statics.active = active;
|
||||||
linked.forEach(function(element) {
|
linked.forEach(function(element) {
|
||||||
JX.DOM.alterClass(element, classMouseCursor, statics.active);
|
JX.DOM.alterClass(element, classMouseCursor, statics.active);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!statics.active) {
|
|
||||||
highlighted && JX.DOM.alterClass(highlighted, classHighlight, false);
|
|
||||||
highlighted = null;
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue