1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-15 18:10:53 +01:00

(stable) Promote 2017 Week 21

This commit is contained in:
epriestley 2017-05-26 16:03:32 -07:00
commit c7eae8f031
175 changed files with 3504 additions and 1757 deletions

View file

@ -1,30 +1,3 @@
<?php <?php
// Destroy duplicate drafts before storage adjustment adds a unique key to this // This table has been removed; see T12104 for details.
// table. See T1191. We retain the newest draft.
// (We can't easily do this in a single SQL statement because MySQL won't let us
// modify a table that's joined in a subquery.)
$table = new DifferentialDraft();
$conn_w = $table->establishConnection('w');
$duplicates = queryfx_all(
$conn_w,
'SELECT DISTINCT u.id id FROM %T u
JOIN %T v
ON u.objectPHID = v.objectPHID
AND u.authorPHID = v.authorPHID
AND u.draftKey = v.draftKey
AND u.id < v.id',
$table->getTableName(),
$table->getTableName());
$duplicates = ipull($duplicates, 'id');
foreach (PhabricatorLiskDAO::chunkSQL($duplicates) as $chunk) {
queryfx(
$conn_w,
'DELETE FROM %T WHERE id IN (%Q)',
$table->getTableName(),
$chunk);
}

View file

@ -0,0 +1,2 @@
ALTER TABLE {$NAMESPACE}_nuance.nuance_item
MODIFY itemKey VARCHAR(64) COLLATE {$COLLATE_TEXT};

View file

@ -0,0 +1,8 @@
ALTER TABLE {$NAMESPACE}_nuance.nuance_itemcommand
ADD dateCreated INT UNSIGNED NOT NULL;
ALTER TABLE {$NAMESPACE}_nuance.nuance_itemcommand
ADD dateModified INT UNSIGNED NOT NULL;
ALTER TABLE {$NAMESPACE}_nuance.nuance_itemcommand
ADD queuePHID VARBINARY(64);

View file

@ -0,0 +1,5 @@
ALTER TABLE {$NAMESPACE}_nuance.nuance_itemcommand
ADD status VARCHAR(64) NOT NULL;
UPDATE {$NAMESPACE}_nuance.nuance_itemcommand
SET status = 'done' WHERE status = '';

View file

@ -0,0 +1 @@
DROP TABLE {$NAMESPACE}_differential.differential_draft;

View file

@ -0,0 +1,11 @@
<?php
$table = new PhabricatorProject();
foreach (new LiskMigrationIterator($table) as $project) {
PhabricatorSearchWorker::queueDocumentForIndexing(
$project->getPHID(),
array(
'force' => true,
));
}

View file

@ -441,7 +441,6 @@ phutil_register_library_map(array(
'DifferentialDiffTransactionQuery' => 'applications/differential/query/DifferentialDiffTransactionQuery.php', 'DifferentialDiffTransactionQuery' => 'applications/differential/query/DifferentialDiffTransactionQuery.php',
'DifferentialDiffViewController' => 'applications/differential/controller/DifferentialDiffViewController.php', 'DifferentialDiffViewController' => 'applications/differential/controller/DifferentialDiffViewController.php',
'DifferentialDoorkeeperRevisionFeedStoryPublisher' => 'applications/differential/doorkeeper/DifferentialDoorkeeperRevisionFeedStoryPublisher.php', 'DifferentialDoorkeeperRevisionFeedStoryPublisher' => 'applications/differential/doorkeeper/DifferentialDoorkeeperRevisionFeedStoryPublisher.php',
'DifferentialDraft' => 'applications/differential/storage/DifferentialDraft.php',
'DifferentialExactUserFunctionDatasource' => 'applications/differential/typeahead/DifferentialExactUserFunctionDatasource.php', 'DifferentialExactUserFunctionDatasource' => 'applications/differential/typeahead/DifferentialExactUserFunctionDatasource.php',
'DifferentialFieldParseException' => 'applications/differential/exception/DifferentialFieldParseException.php', 'DifferentialFieldParseException' => 'applications/differential/exception/DifferentialFieldParseException.php',
'DifferentialFieldValidationException' => 'applications/differential/exception/DifferentialFieldValidationException.php', 'DifferentialFieldValidationException' => 'applications/differential/exception/DifferentialFieldValidationException.php',
@ -661,6 +660,7 @@ phutil_register_library_map(array(
'DiffusionCommitHookEngine' => 'applications/diffusion/engine/DiffusionCommitHookEngine.php', 'DiffusionCommitHookEngine' => 'applications/diffusion/engine/DiffusionCommitHookEngine.php',
'DiffusionCommitHookRejectException' => 'applications/diffusion/exception/DiffusionCommitHookRejectException.php', 'DiffusionCommitHookRejectException' => 'applications/diffusion/exception/DiffusionCommitHookRejectException.php',
'DiffusionCommitListController' => 'applications/diffusion/controller/DiffusionCommitListController.php', 'DiffusionCommitListController' => 'applications/diffusion/controller/DiffusionCommitListController.php',
'DiffusionCommitListView' => 'applications/diffusion/view/DiffusionCommitListView.php',
'DiffusionCommitMergeHeraldField' => 'applications/diffusion/herald/DiffusionCommitMergeHeraldField.php', 'DiffusionCommitMergeHeraldField' => 'applications/diffusion/herald/DiffusionCommitMergeHeraldField.php',
'DiffusionCommitMessageHeraldField' => 'applications/diffusion/herald/DiffusionCommitMessageHeraldField.php', 'DiffusionCommitMessageHeraldField' => 'applications/diffusion/herald/DiffusionCommitMessageHeraldField.php',
'DiffusionCommitPackageAuditHeraldField' => 'applications/diffusion/herald/DiffusionCommitPackageAuditHeraldField.php', 'DiffusionCommitPackageAuditHeraldField' => 'applications/diffusion/herald/DiffusionCommitPackageAuditHeraldField.php',
@ -1494,6 +1494,7 @@ phutil_register_library_map(array(
'ManiphestPointsConfigOptionType' => 'applications/maniphest/config/ManiphestPointsConfigOptionType.php', 'ManiphestPointsConfigOptionType' => 'applications/maniphest/config/ManiphestPointsConfigOptionType.php',
'ManiphestPriorityConfigOptionType' => 'applications/maniphest/config/ManiphestPriorityConfigOptionType.php', 'ManiphestPriorityConfigOptionType' => 'applications/maniphest/config/ManiphestPriorityConfigOptionType.php',
'ManiphestPriorityEmailCommand' => 'applications/maniphest/command/ManiphestPriorityEmailCommand.php', 'ManiphestPriorityEmailCommand' => 'applications/maniphest/command/ManiphestPriorityEmailCommand.php',
'ManiphestPrioritySearchConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestPrioritySearchConduitAPIMethod.php',
'ManiphestProjectNameFulltextEngineExtension' => 'applications/maniphest/engineextension/ManiphestProjectNameFulltextEngineExtension.php', 'ManiphestProjectNameFulltextEngineExtension' => 'applications/maniphest/engineextension/ManiphestProjectNameFulltextEngineExtension.php',
'ManiphestQueryConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestQueryConduitAPIMethod.php', 'ManiphestQueryConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestQueryConduitAPIMethod.php',
'ManiphestQueryStatusesConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestQueryStatusesConduitAPIMethod.php', 'ManiphestQueryStatusesConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestQueryStatusesConduitAPIMethod.php',
@ -1600,11 +1601,13 @@ phutil_register_library_map(array(
'MultimeterLabel' => 'applications/multimeter/storage/MultimeterLabel.php', 'MultimeterLabel' => 'applications/multimeter/storage/MultimeterLabel.php',
'MultimeterSampleController' => 'applications/multimeter/controller/MultimeterSampleController.php', 'MultimeterSampleController' => 'applications/multimeter/controller/MultimeterSampleController.php',
'MultimeterViewer' => 'applications/multimeter/storage/MultimeterViewer.php', 'MultimeterViewer' => 'applications/multimeter/storage/MultimeterViewer.php',
'NuanceCommandImplementation' => 'applications/nuance/command/NuanceCommandImplementation.php',
'NuanceConduitAPIMethod' => 'applications/nuance/conduit/NuanceConduitAPIMethod.php', 'NuanceConduitAPIMethod' => 'applications/nuance/conduit/NuanceConduitAPIMethod.php',
'NuanceConsoleController' => 'applications/nuance/controller/NuanceConsoleController.php', 'NuanceConsoleController' => 'applications/nuance/controller/NuanceConsoleController.php',
'NuanceContentSource' => 'applications/nuance/contentsource/NuanceContentSource.php', 'NuanceContentSource' => 'applications/nuance/contentsource/NuanceContentSource.php',
'NuanceController' => 'applications/nuance/controller/NuanceController.php', 'NuanceController' => 'applications/nuance/controller/NuanceController.php',
'NuanceDAO' => 'applications/nuance/storage/NuanceDAO.php', 'NuanceDAO' => 'applications/nuance/storage/NuanceDAO.php',
'NuanceFormItemType' => 'applications/nuance/item/NuanceFormItemType.php',
'NuanceGitHubEventItemType' => 'applications/nuance/item/NuanceGitHubEventItemType.php', 'NuanceGitHubEventItemType' => 'applications/nuance/item/NuanceGitHubEventItemType.php',
'NuanceGitHubImportCursor' => 'applications/nuance/cursor/NuanceGitHubImportCursor.php', 'NuanceGitHubImportCursor' => 'applications/nuance/cursor/NuanceGitHubImportCursor.php',
'NuanceGitHubIssuesImportCursor' => 'applications/nuance/cursor/NuanceGitHubIssuesImportCursor.php', 'NuanceGitHubIssuesImportCursor' => 'applications/nuance/cursor/NuanceGitHubIssuesImportCursor.php',
@ -1620,16 +1623,25 @@ phutil_register_library_map(array(
'NuanceItemActionController' => 'applications/nuance/controller/NuanceItemActionController.php', 'NuanceItemActionController' => 'applications/nuance/controller/NuanceItemActionController.php',
'NuanceItemCommand' => 'applications/nuance/storage/NuanceItemCommand.php', 'NuanceItemCommand' => 'applications/nuance/storage/NuanceItemCommand.php',
'NuanceItemCommandQuery' => 'applications/nuance/query/NuanceItemCommandQuery.php', 'NuanceItemCommandQuery' => 'applications/nuance/query/NuanceItemCommandQuery.php',
'NuanceItemCommandSpec' => 'applications/nuance/command/NuanceItemCommandSpec.php',
'NuanceItemCommandTransaction' => 'applications/nuance/xaction/NuanceItemCommandTransaction.php',
'NuanceItemController' => 'applications/nuance/controller/NuanceItemController.php', 'NuanceItemController' => 'applications/nuance/controller/NuanceItemController.php',
'NuanceItemEditor' => 'applications/nuance/editor/NuanceItemEditor.php', 'NuanceItemEditor' => 'applications/nuance/editor/NuanceItemEditor.php',
'NuanceItemListController' => 'applications/nuance/controller/NuanceItemListController.php', 'NuanceItemListController' => 'applications/nuance/controller/NuanceItemListController.php',
'NuanceItemManageController' => 'applications/nuance/controller/NuanceItemManageController.php', 'NuanceItemManageController' => 'applications/nuance/controller/NuanceItemManageController.php',
'NuanceItemOwnerTransaction' => 'applications/nuance/xaction/NuanceItemOwnerTransaction.php',
'NuanceItemPHIDType' => 'applications/nuance/phid/NuanceItemPHIDType.php', 'NuanceItemPHIDType' => 'applications/nuance/phid/NuanceItemPHIDType.php',
'NuanceItemPropertyTransaction' => 'applications/nuance/xaction/NuanceItemPropertyTransaction.php',
'NuanceItemQuery' => 'applications/nuance/query/NuanceItemQuery.php', 'NuanceItemQuery' => 'applications/nuance/query/NuanceItemQuery.php',
'NuanceItemQueueTransaction' => 'applications/nuance/xaction/NuanceItemQueueTransaction.php',
'NuanceItemRequestorTransaction' => 'applications/nuance/xaction/NuanceItemRequestorTransaction.php',
'NuanceItemSearchEngine' => 'applications/nuance/query/NuanceItemSearchEngine.php', 'NuanceItemSearchEngine' => 'applications/nuance/query/NuanceItemSearchEngine.php',
'NuanceItemSourceTransaction' => 'applications/nuance/xaction/NuanceItemSourceTransaction.php',
'NuanceItemStatusTransaction' => 'applications/nuance/xaction/NuanceItemStatusTransaction.php',
'NuanceItemTransaction' => 'applications/nuance/storage/NuanceItemTransaction.php', 'NuanceItemTransaction' => 'applications/nuance/storage/NuanceItemTransaction.php',
'NuanceItemTransactionComment' => 'applications/nuance/storage/NuanceItemTransactionComment.php', 'NuanceItemTransactionComment' => 'applications/nuance/storage/NuanceItemTransactionComment.php',
'NuanceItemTransactionQuery' => 'applications/nuance/query/NuanceItemTransactionQuery.php', 'NuanceItemTransactionQuery' => 'applications/nuance/query/NuanceItemTransactionQuery.php',
'NuanceItemTransactionType' => 'applications/nuance/xaction/NuanceItemTransactionType.php',
'NuanceItemType' => 'applications/nuance/item/NuanceItemType.php', 'NuanceItemType' => 'applications/nuance/item/NuanceItemType.php',
'NuanceItemUpdateWorker' => 'applications/nuance/worker/NuanceItemUpdateWorker.php', 'NuanceItemUpdateWorker' => 'applications/nuance/worker/NuanceItemUpdateWorker.php',
'NuanceItemViewController' => 'applications/nuance/controller/NuanceItemViewController.php', 'NuanceItemViewController' => 'applications/nuance/controller/NuanceItemViewController.php',
@ -1645,18 +1657,22 @@ phutil_register_library_map(array(
'NuanceQueueEditEngine' => 'applications/nuance/editor/NuanceQueueEditEngine.php', 'NuanceQueueEditEngine' => 'applications/nuance/editor/NuanceQueueEditEngine.php',
'NuanceQueueEditor' => 'applications/nuance/editor/NuanceQueueEditor.php', 'NuanceQueueEditor' => 'applications/nuance/editor/NuanceQueueEditor.php',
'NuanceQueueListController' => 'applications/nuance/controller/NuanceQueueListController.php', 'NuanceQueueListController' => 'applications/nuance/controller/NuanceQueueListController.php',
'NuanceQueueNameTransaction' => 'applications/nuance/xaction/NuanceQueueNameTransaction.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',
'NuanceQueueSearchEngine' => 'applications/nuance/query/NuanceQueueSearchEngine.php', 'NuanceQueueSearchEngine' => 'applications/nuance/query/NuanceQueueSearchEngine.php',
'NuanceQueueTransaction' => 'applications/nuance/storage/NuanceQueueTransaction.php', 'NuanceQueueTransaction' => 'applications/nuance/storage/NuanceQueueTransaction.php',
'NuanceQueueTransactionComment' => 'applications/nuance/storage/NuanceQueueTransactionComment.php', 'NuanceQueueTransactionComment' => 'applications/nuance/storage/NuanceQueueTransactionComment.php',
'NuanceQueueTransactionQuery' => 'applications/nuance/query/NuanceQueueTransactionQuery.php', 'NuanceQueueTransactionQuery' => 'applications/nuance/query/NuanceQueueTransactionQuery.php',
'NuanceQueueTransactionType' => 'applications/nuance/xaction/NuanceQueueTransactionType.php',
'NuanceQueueViewController' => 'applications/nuance/controller/NuanceQueueViewController.php', 'NuanceQueueViewController' => 'applications/nuance/controller/NuanceQueueViewController.php',
'NuanceQueueWorkController' => 'applications/nuance/controller/NuanceQueueWorkController.php',
'NuanceSchemaSpec' => 'applications/nuance/storage/NuanceSchemaSpec.php', 'NuanceSchemaSpec' => 'applications/nuance/storage/NuanceSchemaSpec.php',
'NuanceSource' => 'applications/nuance/storage/NuanceSource.php', 'NuanceSource' => 'applications/nuance/storage/NuanceSource.php',
'NuanceSourceActionController' => 'applications/nuance/controller/NuanceSourceActionController.php', 'NuanceSourceActionController' => 'applications/nuance/controller/NuanceSourceActionController.php',
'NuanceSourceController' => 'applications/nuance/controller/NuanceSourceController.php', 'NuanceSourceController' => 'applications/nuance/controller/NuanceSourceController.php',
'NuanceSourceDefaultEditCapability' => 'applications/nuance/capability/NuanceSourceDefaultEditCapability.php', 'NuanceSourceDefaultEditCapability' => 'applications/nuance/capability/NuanceSourceDefaultEditCapability.php',
'NuanceSourceDefaultQueueTransaction' => 'applications/nuance/xaction/NuanceSourceDefaultQueueTransaction.php',
'NuanceSourceDefaultViewCapability' => 'applications/nuance/capability/NuanceSourceDefaultViewCapability.php', 'NuanceSourceDefaultViewCapability' => 'applications/nuance/capability/NuanceSourceDefaultViewCapability.php',
'NuanceSourceDefinition' => 'applications/nuance/source/NuanceSourceDefinition.php', 'NuanceSourceDefinition' => 'applications/nuance/source/NuanceSourceDefinition.php',
'NuanceSourceDefinitionTestCase' => 'applications/nuance/source/__tests__/NuanceSourceDefinitionTestCase.php', 'NuanceSourceDefinitionTestCase' => 'applications/nuance/source/__tests__/NuanceSourceDefinitionTestCase.php',
@ -1666,14 +1682,17 @@ phutil_register_library_map(array(
'NuanceSourceListController' => 'applications/nuance/controller/NuanceSourceListController.php', 'NuanceSourceListController' => 'applications/nuance/controller/NuanceSourceListController.php',
'NuanceSourceManageCapability' => 'applications/nuance/capability/NuanceSourceManageCapability.php', 'NuanceSourceManageCapability' => 'applications/nuance/capability/NuanceSourceManageCapability.php',
'NuanceSourceNameNgrams' => 'applications/nuance/storage/NuanceSourceNameNgrams.php', 'NuanceSourceNameNgrams' => 'applications/nuance/storage/NuanceSourceNameNgrams.php',
'NuanceSourceNameTransaction' => 'applications/nuance/xaction/NuanceSourceNameTransaction.php',
'NuanceSourcePHIDType' => 'applications/nuance/phid/NuanceSourcePHIDType.php', 'NuanceSourcePHIDType' => 'applications/nuance/phid/NuanceSourcePHIDType.php',
'NuanceSourceQuery' => 'applications/nuance/query/NuanceSourceQuery.php', 'NuanceSourceQuery' => 'applications/nuance/query/NuanceSourceQuery.php',
'NuanceSourceSearchEngine' => 'applications/nuance/query/NuanceSourceSearchEngine.php', 'NuanceSourceSearchEngine' => 'applications/nuance/query/NuanceSourceSearchEngine.php',
'NuanceSourceTransaction' => 'applications/nuance/storage/NuanceSourceTransaction.php', 'NuanceSourceTransaction' => 'applications/nuance/storage/NuanceSourceTransaction.php',
'NuanceSourceTransactionComment' => 'applications/nuance/storage/NuanceSourceTransactionComment.php', 'NuanceSourceTransactionComment' => 'applications/nuance/storage/NuanceSourceTransactionComment.php',
'NuanceSourceTransactionQuery' => 'applications/nuance/query/NuanceSourceTransactionQuery.php', 'NuanceSourceTransactionQuery' => 'applications/nuance/query/NuanceSourceTransactionQuery.php',
'NuanceSourceTransactionType' => 'applications/nuance/xaction/NuanceSourceTransactionType.php',
'NuanceSourceViewController' => 'applications/nuance/controller/NuanceSourceViewController.php', 'NuanceSourceViewController' => 'applications/nuance/controller/NuanceSourceViewController.php',
'NuanceTransaction' => 'applications/nuance/storage/NuanceTransaction.php', 'NuanceTransaction' => 'applications/nuance/storage/NuanceTransaction.php',
'NuanceTrashCommand' => 'applications/nuance/command/NuanceTrashCommand.php',
'NuanceWorker' => 'applications/nuance/worker/NuanceWorker.php', 'NuanceWorker' => 'applications/nuance/worker/NuanceWorker.php',
'OwnersConduitAPIMethod' => 'applications/owners/conduit/OwnersConduitAPIMethod.php', 'OwnersConduitAPIMethod' => 'applications/owners/conduit/OwnersConduitAPIMethod.php',
'OwnersEditConduitAPIMethod' => 'applications/owners/conduit/OwnersEditConduitAPIMethod.php', 'OwnersEditConduitAPIMethod' => 'applications/owners/conduit/OwnersEditConduitAPIMethod.php',
@ -3457,10 +3476,12 @@ phutil_register_library_map(array(
'PhabricatorPeopleProfileManageController' => 'applications/people/controller/PhabricatorPeopleProfileManageController.php', 'PhabricatorPeopleProfileManageController' => 'applications/people/controller/PhabricatorPeopleProfileManageController.php',
'PhabricatorPeopleProfileMenuEngine' => 'applications/people/engine/PhabricatorPeopleProfileMenuEngine.php', 'PhabricatorPeopleProfileMenuEngine' => 'applications/people/engine/PhabricatorPeopleProfileMenuEngine.php',
'PhabricatorPeopleProfilePictureController' => 'applications/people/controller/PhabricatorPeopleProfilePictureController.php', 'PhabricatorPeopleProfilePictureController' => 'applications/people/controller/PhabricatorPeopleProfilePictureController.php',
'PhabricatorPeopleProfileRevisionsController' => 'applications/people/controller/PhabricatorPeopleProfileRevisionsController.php',
'PhabricatorPeopleProfileTasksController' => 'applications/people/controller/PhabricatorPeopleProfileTasksController.php', 'PhabricatorPeopleProfileTasksController' => 'applications/people/controller/PhabricatorPeopleProfileTasksController.php',
'PhabricatorPeopleProfileViewController' => 'applications/people/controller/PhabricatorPeopleProfileViewController.php', 'PhabricatorPeopleProfileViewController' => 'applications/people/controller/PhabricatorPeopleProfileViewController.php',
'PhabricatorPeopleQuery' => 'applications/people/query/PhabricatorPeopleQuery.php', 'PhabricatorPeopleQuery' => 'applications/people/query/PhabricatorPeopleQuery.php',
'PhabricatorPeopleRenameController' => 'applications/people/controller/PhabricatorPeopleRenameController.php', 'PhabricatorPeopleRenameController' => 'applications/people/controller/PhabricatorPeopleRenameController.php',
'PhabricatorPeopleRevisionsProfileMenuItem' => 'applications/people/menuitem/PhabricatorPeopleRevisionsProfileMenuItem.php',
'PhabricatorPeopleSearchEngine' => 'applications/people/query/PhabricatorPeopleSearchEngine.php', 'PhabricatorPeopleSearchEngine' => 'applications/people/query/PhabricatorPeopleSearchEngine.php',
'PhabricatorPeopleTasksProfileMenuItem' => 'applications/people/menuitem/PhabricatorPeopleTasksProfileMenuItem.php', 'PhabricatorPeopleTasksProfileMenuItem' => 'applications/people/menuitem/PhabricatorPeopleTasksProfileMenuItem.php',
'PhabricatorPeopleTestDataGenerator' => 'applications/people/lipsum/PhabricatorPeopleTestDataGenerator.php', 'PhabricatorPeopleTestDataGenerator' => 'applications/people/lipsum/PhabricatorPeopleTestDataGenerator.php',
@ -3615,6 +3636,7 @@ phutil_register_library_map(array(
'PhabricatorProjectEditController' => 'applications/project/controller/PhabricatorProjectEditController.php', 'PhabricatorProjectEditController' => 'applications/project/controller/PhabricatorProjectEditController.php',
'PhabricatorProjectEditEngine' => 'applications/project/engine/PhabricatorProjectEditEngine.php', 'PhabricatorProjectEditEngine' => 'applications/project/engine/PhabricatorProjectEditEngine.php',
'PhabricatorProjectEditPictureController' => 'applications/project/controller/PhabricatorProjectEditPictureController.php', 'PhabricatorProjectEditPictureController' => 'applications/project/controller/PhabricatorProjectEditPictureController.php',
'PhabricatorProjectFilterTransaction' => 'applications/project/xaction/PhabricatorProjectFilterTransaction.php',
'PhabricatorProjectFulltextEngine' => 'applications/project/search/PhabricatorProjectFulltextEngine.php', 'PhabricatorProjectFulltextEngine' => 'applications/project/search/PhabricatorProjectFulltextEngine.php',
'PhabricatorProjectHeraldAction' => 'applications/project/herald/PhabricatorProjectHeraldAction.php', 'PhabricatorProjectHeraldAction' => 'applications/project/herald/PhabricatorProjectHeraldAction.php',
'PhabricatorProjectHeraldAdapter' => 'applications/project/herald/PhabricatorProjectHeraldAdapter.php', 'PhabricatorProjectHeraldAdapter' => 'applications/project/herald/PhabricatorProjectHeraldAdapter.php',
@ -3628,6 +3650,7 @@ phutil_register_library_map(array(
'PhabricatorProjectListController' => 'applications/project/controller/PhabricatorProjectListController.php', 'PhabricatorProjectListController' => 'applications/project/controller/PhabricatorProjectListController.php',
'PhabricatorProjectListView' => 'applications/project/view/PhabricatorProjectListView.php', 'PhabricatorProjectListView' => 'applications/project/view/PhabricatorProjectListView.php',
'PhabricatorProjectLockController' => 'applications/project/controller/PhabricatorProjectLockController.php', 'PhabricatorProjectLockController' => 'applications/project/controller/PhabricatorProjectLockController.php',
'PhabricatorProjectLockTransaction' => 'applications/project/xaction/PhabricatorProjectLockTransaction.php',
'PhabricatorProjectLogicalAncestorDatasource' => 'applications/project/typeahead/PhabricatorProjectLogicalAncestorDatasource.php', 'PhabricatorProjectLogicalAncestorDatasource' => 'applications/project/typeahead/PhabricatorProjectLogicalAncestorDatasource.php',
'PhabricatorProjectLogicalDatasource' => 'applications/project/typeahead/PhabricatorProjectLogicalDatasource.php', 'PhabricatorProjectLogicalDatasource' => 'applications/project/typeahead/PhabricatorProjectLogicalDatasource.php',
'PhabricatorProjectLogicalOrNotDatasource' => 'applications/project/typeahead/PhabricatorProjectLogicalOrNotDatasource.php', 'PhabricatorProjectLogicalOrNotDatasource' => 'applications/project/typeahead/PhabricatorProjectLogicalOrNotDatasource.php',
@ -3645,6 +3668,7 @@ phutil_register_library_map(array(
'PhabricatorProjectMembersRemoveController' => 'applications/project/controller/PhabricatorProjectMembersRemoveController.php', 'PhabricatorProjectMembersRemoveController' => 'applications/project/controller/PhabricatorProjectMembersRemoveController.php',
'PhabricatorProjectMembersViewController' => 'applications/project/controller/PhabricatorProjectMembersViewController.php', 'PhabricatorProjectMembersViewController' => 'applications/project/controller/PhabricatorProjectMembersViewController.php',
'PhabricatorProjectMenuItemController' => 'applications/project/controller/PhabricatorProjectMenuItemController.php', 'PhabricatorProjectMenuItemController' => 'applications/project/controller/PhabricatorProjectMenuItemController.php',
'PhabricatorProjectMilestoneTransaction' => 'applications/project/xaction/PhabricatorProjectMilestoneTransaction.php',
'PhabricatorProjectMoveController' => 'applications/project/controller/PhabricatorProjectMoveController.php', 'PhabricatorProjectMoveController' => 'applications/project/controller/PhabricatorProjectMoveController.php',
'PhabricatorProjectNameContextFreeGrammar' => 'applications/project/lipsum/PhabricatorProjectNameContextFreeGrammar.php', 'PhabricatorProjectNameContextFreeGrammar' => 'applications/project/lipsum/PhabricatorProjectNameContextFreeGrammar.php',
'PhabricatorProjectNameTransaction' => 'applications/project/xaction/PhabricatorProjectNameTransaction.php', 'PhabricatorProjectNameTransaction' => 'applications/project/xaction/PhabricatorProjectNameTransaction.php',
@ -3653,6 +3677,7 @@ phutil_register_library_map(array(
'PhabricatorProjectOrUserDatasource' => 'applications/project/typeahead/PhabricatorProjectOrUserDatasource.php', 'PhabricatorProjectOrUserDatasource' => 'applications/project/typeahead/PhabricatorProjectOrUserDatasource.php',
'PhabricatorProjectOrUserFunctionDatasource' => 'applications/project/typeahead/PhabricatorProjectOrUserFunctionDatasource.php', 'PhabricatorProjectOrUserFunctionDatasource' => 'applications/project/typeahead/PhabricatorProjectOrUserFunctionDatasource.php',
'PhabricatorProjectPHIDResolver' => 'applications/phid/resolver/PhabricatorProjectPHIDResolver.php', 'PhabricatorProjectPHIDResolver' => 'applications/phid/resolver/PhabricatorProjectPHIDResolver.php',
'PhabricatorProjectParentTransaction' => 'applications/project/xaction/PhabricatorProjectParentTransaction.php',
'PhabricatorProjectPictureProfileMenuItem' => 'applications/project/menuitem/PhabricatorProjectPictureProfileMenuItem.php', 'PhabricatorProjectPictureProfileMenuItem' => 'applications/project/menuitem/PhabricatorProjectPictureProfileMenuItem.php',
'PhabricatorProjectPointsProfileMenuItem' => 'applications/project/menuitem/PhabricatorProjectPointsProfileMenuItem.php', 'PhabricatorProjectPointsProfileMenuItem' => 'applications/project/menuitem/PhabricatorProjectPointsProfileMenuItem.php',
'PhabricatorProjectProfileController' => 'applications/project/controller/PhabricatorProjectProfileController.php', 'PhabricatorProjectProfileController' => 'applications/project/controller/PhabricatorProjectProfileController.php',
@ -3670,6 +3695,7 @@ phutil_register_library_map(array(
'PhabricatorProjectSilencedEdgeType' => 'applications/project/edge/PhabricatorProjectSilencedEdgeType.php', 'PhabricatorProjectSilencedEdgeType' => 'applications/project/edge/PhabricatorProjectSilencedEdgeType.php',
'PhabricatorProjectSlug' => 'applications/project/storage/PhabricatorProjectSlug.php', 'PhabricatorProjectSlug' => 'applications/project/storage/PhabricatorProjectSlug.php',
'PhabricatorProjectSlugsTransaction' => 'applications/project/xaction/PhabricatorProjectSlugsTransaction.php', 'PhabricatorProjectSlugsTransaction' => 'applications/project/xaction/PhabricatorProjectSlugsTransaction.php',
'PhabricatorProjectSortTransaction' => 'applications/project/xaction/PhabricatorProjectSortTransaction.php',
'PhabricatorProjectStandardCustomField' => 'applications/project/customfield/PhabricatorProjectStandardCustomField.php', 'PhabricatorProjectStandardCustomField' => 'applications/project/customfield/PhabricatorProjectStandardCustomField.php',
'PhabricatorProjectStatus' => 'applications/project/constants/PhabricatorProjectStatus.php', 'PhabricatorProjectStatus' => 'applications/project/constants/PhabricatorProjectStatus.php',
'PhabricatorProjectStatusTransaction' => 'applications/project/xaction/PhabricatorProjectStatusTransaction.php', 'PhabricatorProjectStatusTransaction' => 'applications/project/xaction/PhabricatorProjectStatusTransaction.php',
@ -3681,6 +3707,7 @@ phutil_register_library_map(array(
'PhabricatorProjectTransactionEditor' => 'applications/project/editor/PhabricatorProjectTransactionEditor.php', 'PhabricatorProjectTransactionEditor' => 'applications/project/editor/PhabricatorProjectTransactionEditor.php',
'PhabricatorProjectTransactionQuery' => 'applications/project/query/PhabricatorProjectTransactionQuery.php', 'PhabricatorProjectTransactionQuery' => 'applications/project/query/PhabricatorProjectTransactionQuery.php',
'PhabricatorProjectTransactionType' => 'applications/project/xaction/PhabricatorProjectTransactionType.php', 'PhabricatorProjectTransactionType' => 'applications/project/xaction/PhabricatorProjectTransactionType.php',
'PhabricatorProjectTypeTransaction' => 'applications/project/xaction/PhabricatorProjectTypeTransaction.php',
'PhabricatorProjectUIEventListener' => 'applications/project/events/PhabricatorProjectUIEventListener.php', 'PhabricatorProjectUIEventListener' => 'applications/project/events/PhabricatorProjectUIEventListener.php',
'PhabricatorProjectUpdateController' => 'applications/project/controller/PhabricatorProjectUpdateController.php', 'PhabricatorProjectUpdateController' => 'applications/project/controller/PhabricatorProjectUpdateController.php',
'PhabricatorProjectUserFunctionDatasource' => 'applications/project/typeahead/PhabricatorProjectUserFunctionDatasource.php', 'PhabricatorProjectUserFunctionDatasource' => 'applications/project/typeahead/PhabricatorProjectUserFunctionDatasource.php',
@ -3689,7 +3716,9 @@ phutil_register_library_map(array(
'PhabricatorProjectWatchController' => 'applications/project/controller/PhabricatorProjectWatchController.php', 'PhabricatorProjectWatchController' => 'applications/project/controller/PhabricatorProjectWatchController.php',
'PhabricatorProjectWatcherListView' => 'applications/project/view/PhabricatorProjectWatcherListView.php', 'PhabricatorProjectWatcherListView' => 'applications/project/view/PhabricatorProjectWatcherListView.php',
'PhabricatorProjectWorkboardBackgroundColor' => 'applications/project/constants/PhabricatorProjectWorkboardBackgroundColor.php', 'PhabricatorProjectWorkboardBackgroundColor' => 'applications/project/constants/PhabricatorProjectWorkboardBackgroundColor.php',
'PhabricatorProjectWorkboardBackgroundTransaction' => 'applications/project/xaction/PhabricatorProjectWorkboardBackgroundTransaction.php',
'PhabricatorProjectWorkboardProfileMenuItem' => 'applications/project/menuitem/PhabricatorProjectWorkboardProfileMenuItem.php', 'PhabricatorProjectWorkboardProfileMenuItem' => 'applications/project/menuitem/PhabricatorProjectWorkboardProfileMenuItem.php',
'PhabricatorProjectWorkboardTransaction' => 'applications/project/xaction/PhabricatorProjectWorkboardTransaction.php',
'PhabricatorProjectsAncestorsSearchEngineAttachment' => 'applications/project/engineextension/PhabricatorProjectsAncestorsSearchEngineAttachment.php', 'PhabricatorProjectsAncestorsSearchEngineAttachment' => 'applications/project/engineextension/PhabricatorProjectsAncestorsSearchEngineAttachment.php',
'PhabricatorProjectsCurtainExtension' => 'applications/project/engineextension/PhabricatorProjectsCurtainExtension.php', 'PhabricatorProjectsCurtainExtension' => 'applications/project/engineextension/PhabricatorProjectsCurtainExtension.php',
'PhabricatorProjectsEditEngineExtension' => 'applications/project/engineextension/PhabricatorProjectsEditEngineExtension.php', 'PhabricatorProjectsEditEngineExtension' => 'applications/project/engineextension/PhabricatorProjectsEditEngineExtension.php',
@ -4619,11 +4648,14 @@ phutil_register_library_map(array(
'PhrictionDocument' => 'applications/phriction/storage/PhrictionDocument.php', 'PhrictionDocument' => 'applications/phriction/storage/PhrictionDocument.php',
'PhrictionDocumentAuthorHeraldField' => 'applications/phriction/herald/PhrictionDocumentAuthorHeraldField.php', 'PhrictionDocumentAuthorHeraldField' => 'applications/phriction/herald/PhrictionDocumentAuthorHeraldField.php',
'PhrictionDocumentContentHeraldField' => 'applications/phriction/herald/PhrictionDocumentContentHeraldField.php', 'PhrictionDocumentContentHeraldField' => 'applications/phriction/herald/PhrictionDocumentContentHeraldField.php',
'PhrictionDocumentContentTransaction' => 'applications/phriction/xaction/PhrictionDocumentContentTransaction.php',
'PhrictionDocumentController' => 'applications/phriction/controller/PhrictionDocumentController.php', 'PhrictionDocumentController' => 'applications/phriction/controller/PhrictionDocumentController.php',
'PhrictionDocumentDeleteTransaction' => 'applications/phriction/xaction/PhrictionDocumentDeleteTransaction.php',
'PhrictionDocumentFulltextEngine' => 'applications/phriction/search/PhrictionDocumentFulltextEngine.php', 'PhrictionDocumentFulltextEngine' => 'applications/phriction/search/PhrictionDocumentFulltextEngine.php',
'PhrictionDocumentHeraldAdapter' => 'applications/phriction/herald/PhrictionDocumentHeraldAdapter.php', 'PhrictionDocumentHeraldAdapter' => 'applications/phriction/herald/PhrictionDocumentHeraldAdapter.php',
'PhrictionDocumentHeraldField' => 'applications/phriction/herald/PhrictionDocumentHeraldField.php', 'PhrictionDocumentHeraldField' => 'applications/phriction/herald/PhrictionDocumentHeraldField.php',
'PhrictionDocumentHeraldFieldGroup' => 'applications/phriction/herald/PhrictionDocumentHeraldFieldGroup.php', 'PhrictionDocumentHeraldFieldGroup' => 'applications/phriction/herald/PhrictionDocumentHeraldFieldGroup.php',
'PhrictionDocumentMoveAwayTransaction' => 'applications/phriction/xaction/PhrictionDocumentMoveAwayTransaction.php',
'PhrictionDocumentMoveToTransaction' => 'applications/phriction/xaction/PhrictionDocumentMoveToTransaction.php', 'PhrictionDocumentMoveToTransaction' => 'applications/phriction/xaction/PhrictionDocumentMoveToTransaction.php',
'PhrictionDocumentPHIDType' => 'applications/phriction/phid/PhrictionDocumentPHIDType.php', 'PhrictionDocumentPHIDType' => 'applications/phriction/phid/PhrictionDocumentPHIDType.php',
'PhrictionDocumentPathHeraldField' => 'applications/phriction/herald/PhrictionDocumentPathHeraldField.php', 'PhrictionDocumentPathHeraldField' => 'applications/phriction/herald/PhrictionDocumentPathHeraldField.php',
@ -5359,7 +5391,6 @@ phutil_register_library_map(array(
'DifferentialDiffTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'DifferentialDiffTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'DifferentialDiffViewController' => 'DifferentialController', 'DifferentialDiffViewController' => 'DifferentialController',
'DifferentialDoorkeeperRevisionFeedStoryPublisher' => 'DoorkeeperFeedStoryPublisher', 'DifferentialDoorkeeperRevisionFeedStoryPublisher' => 'DoorkeeperFeedStoryPublisher',
'DifferentialDraft' => 'DifferentialDAO',
'DifferentialExactUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'DifferentialExactUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
'DifferentialFieldParseException' => 'Exception', 'DifferentialFieldParseException' => 'Exception',
'DifferentialFieldValidationException' => 'Exception', 'DifferentialFieldValidationException' => 'Exception',
@ -5602,6 +5633,7 @@ phutil_register_library_map(array(
'DiffusionCommitHookEngine' => 'Phobject', 'DiffusionCommitHookEngine' => 'Phobject',
'DiffusionCommitHookRejectException' => 'Exception', 'DiffusionCommitHookRejectException' => 'Exception',
'DiffusionCommitListController' => 'DiffusionController', 'DiffusionCommitListController' => 'DiffusionController',
'DiffusionCommitListView' => 'AphrontView',
'DiffusionCommitMergeHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitMergeHeraldField' => 'DiffusionCommitHeraldField',
'DiffusionCommitMessageHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitMessageHeraldField' => 'DiffusionCommitHeraldField',
'DiffusionCommitPackageAuditHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitPackageAuditHeraldField' => 'DiffusionCommitHeraldField',
@ -6562,6 +6594,7 @@ phutil_register_library_map(array(
'ManiphestPointsConfigOptionType' => 'PhabricatorConfigJSONOptionType', 'ManiphestPointsConfigOptionType' => 'PhabricatorConfigJSONOptionType',
'ManiphestPriorityConfigOptionType' => 'PhabricatorConfigJSONOptionType', 'ManiphestPriorityConfigOptionType' => 'PhabricatorConfigJSONOptionType',
'ManiphestPriorityEmailCommand' => 'ManiphestEmailCommand', 'ManiphestPriorityEmailCommand' => 'ManiphestEmailCommand',
'ManiphestPrioritySearchConduitAPIMethod' => 'ManiphestConduitAPIMethod',
'ManiphestProjectNameFulltextEngineExtension' => 'PhabricatorFulltextEngineExtension', 'ManiphestProjectNameFulltextEngineExtension' => 'PhabricatorFulltextEngineExtension',
'ManiphestQueryConduitAPIMethod' => 'ManiphestConduitAPIMethod', 'ManiphestQueryConduitAPIMethod' => 'ManiphestConduitAPIMethod',
'ManiphestQueryStatusesConduitAPIMethod' => 'ManiphestConduitAPIMethod', 'ManiphestQueryStatusesConduitAPIMethod' => 'ManiphestConduitAPIMethod',
@ -6687,11 +6720,13 @@ phutil_register_library_map(array(
'MultimeterLabel' => 'MultimeterDimension', 'MultimeterLabel' => 'MultimeterDimension',
'MultimeterSampleController' => 'MultimeterController', 'MultimeterSampleController' => 'MultimeterController',
'MultimeterViewer' => 'MultimeterDimension', 'MultimeterViewer' => 'MultimeterDimension',
'NuanceCommandImplementation' => 'Phobject',
'NuanceConduitAPIMethod' => 'ConduitAPIMethod', 'NuanceConduitAPIMethod' => 'ConduitAPIMethod',
'NuanceConsoleController' => 'NuanceController', 'NuanceConsoleController' => 'NuanceController',
'NuanceContentSource' => 'PhabricatorContentSource', 'NuanceContentSource' => 'PhabricatorContentSource',
'NuanceController' => 'PhabricatorController', 'NuanceController' => 'PhabricatorController',
'NuanceDAO' => 'PhabricatorLiskDAO', 'NuanceDAO' => 'PhabricatorLiskDAO',
'NuanceFormItemType' => 'NuanceItemType',
'NuanceGitHubEventItemType' => 'NuanceItemType', 'NuanceGitHubEventItemType' => 'NuanceItemType',
'NuanceGitHubImportCursor' => 'NuanceImportCursor', 'NuanceGitHubImportCursor' => 'NuanceImportCursor',
'NuanceGitHubIssuesImportCursor' => 'NuanceGitHubImportCursor', 'NuanceGitHubIssuesImportCursor' => 'NuanceGitHubImportCursor',
@ -6717,16 +6752,25 @@ phutil_register_library_map(array(
'PhabricatorPolicyInterface', 'PhabricatorPolicyInterface',
), ),
'NuanceItemCommandQuery' => 'NuanceQuery', 'NuanceItemCommandQuery' => 'NuanceQuery',
'NuanceItemCommandSpec' => 'Phobject',
'NuanceItemCommandTransaction' => 'NuanceItemTransactionType',
'NuanceItemController' => 'NuanceController', 'NuanceItemController' => 'NuanceController',
'NuanceItemEditor' => 'PhabricatorApplicationTransactionEditor', 'NuanceItemEditor' => 'PhabricatorApplicationTransactionEditor',
'NuanceItemListController' => 'NuanceItemController', 'NuanceItemListController' => 'NuanceItemController',
'NuanceItemManageController' => 'NuanceController', 'NuanceItemManageController' => 'NuanceController',
'NuanceItemOwnerTransaction' => 'NuanceItemTransactionType',
'NuanceItemPHIDType' => 'PhabricatorPHIDType', 'NuanceItemPHIDType' => 'PhabricatorPHIDType',
'NuanceItemPropertyTransaction' => 'NuanceItemTransactionType',
'NuanceItemQuery' => 'NuanceQuery', 'NuanceItemQuery' => 'NuanceQuery',
'NuanceItemQueueTransaction' => 'NuanceItemTransactionType',
'NuanceItemRequestorTransaction' => 'NuanceItemTransactionType',
'NuanceItemSearchEngine' => 'PhabricatorApplicationSearchEngine', 'NuanceItemSearchEngine' => 'PhabricatorApplicationSearchEngine',
'NuanceItemSourceTransaction' => 'NuanceItemTransactionType',
'NuanceItemStatusTransaction' => 'NuanceItemTransactionType',
'NuanceItemTransaction' => 'NuanceTransaction', 'NuanceItemTransaction' => 'NuanceTransaction',
'NuanceItemTransactionComment' => 'PhabricatorApplicationTransactionComment', 'NuanceItemTransactionComment' => 'PhabricatorApplicationTransactionComment',
'NuanceItemTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'NuanceItemTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'NuanceItemTransactionType' => 'PhabricatorModularTransactionType',
'NuanceItemType' => 'Phobject', 'NuanceItemType' => 'Phobject',
'NuanceItemUpdateWorker' => 'NuanceWorker', 'NuanceItemUpdateWorker' => 'NuanceWorker',
'NuanceItemViewController' => 'NuanceController', 'NuanceItemViewController' => 'NuanceController',
@ -6746,13 +6790,16 @@ phutil_register_library_map(array(
'NuanceQueueEditEngine' => 'PhabricatorEditEngine', 'NuanceQueueEditEngine' => 'PhabricatorEditEngine',
'NuanceQueueEditor' => 'PhabricatorApplicationTransactionEditor', 'NuanceQueueEditor' => 'PhabricatorApplicationTransactionEditor',
'NuanceQueueListController' => 'NuanceQueueController', 'NuanceQueueListController' => 'NuanceQueueController',
'NuanceQueueNameTransaction' => 'NuanceQueueTransactionType',
'NuanceQueuePHIDType' => 'PhabricatorPHIDType', 'NuanceQueuePHIDType' => 'PhabricatorPHIDType',
'NuanceQueueQuery' => 'NuanceQuery', 'NuanceQueueQuery' => 'NuanceQuery',
'NuanceQueueSearchEngine' => 'PhabricatorApplicationSearchEngine', 'NuanceQueueSearchEngine' => 'PhabricatorApplicationSearchEngine',
'NuanceQueueTransaction' => 'NuanceTransaction', 'NuanceQueueTransaction' => 'NuanceTransaction',
'NuanceQueueTransactionComment' => 'PhabricatorApplicationTransactionComment', 'NuanceQueueTransactionComment' => 'PhabricatorApplicationTransactionComment',
'NuanceQueueTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'NuanceQueueTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'NuanceQueueTransactionType' => 'PhabricatorModularTransactionType',
'NuanceQueueViewController' => 'NuanceQueueController', 'NuanceQueueViewController' => 'NuanceQueueController',
'NuanceQueueWorkController' => 'NuanceQueueController',
'NuanceSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'NuanceSchemaSpec' => 'PhabricatorConfigSchemaSpec',
'NuanceSource' => array( 'NuanceSource' => array(
'NuanceDAO', 'NuanceDAO',
@ -6763,6 +6810,7 @@ phutil_register_library_map(array(
'NuanceSourceActionController' => 'NuanceController', 'NuanceSourceActionController' => 'NuanceController',
'NuanceSourceController' => 'NuanceController', 'NuanceSourceController' => 'NuanceController',
'NuanceSourceDefaultEditCapability' => 'PhabricatorPolicyCapability', 'NuanceSourceDefaultEditCapability' => 'PhabricatorPolicyCapability',
'NuanceSourceDefaultQueueTransaction' => 'NuanceSourceTransactionType',
'NuanceSourceDefaultViewCapability' => 'PhabricatorPolicyCapability', 'NuanceSourceDefaultViewCapability' => 'PhabricatorPolicyCapability',
'NuanceSourceDefinition' => 'Phobject', 'NuanceSourceDefinition' => 'Phobject',
'NuanceSourceDefinitionTestCase' => 'PhabricatorTestCase', 'NuanceSourceDefinitionTestCase' => 'PhabricatorTestCase',
@ -6772,14 +6820,17 @@ phutil_register_library_map(array(
'NuanceSourceListController' => 'NuanceSourceController', 'NuanceSourceListController' => 'NuanceSourceController',
'NuanceSourceManageCapability' => 'PhabricatorPolicyCapability', 'NuanceSourceManageCapability' => 'PhabricatorPolicyCapability',
'NuanceSourceNameNgrams' => 'PhabricatorSearchNgrams', 'NuanceSourceNameNgrams' => 'PhabricatorSearchNgrams',
'NuanceSourceNameTransaction' => 'NuanceSourceTransactionType',
'NuanceSourcePHIDType' => 'PhabricatorPHIDType', 'NuanceSourcePHIDType' => 'PhabricatorPHIDType',
'NuanceSourceQuery' => 'NuanceQuery', 'NuanceSourceQuery' => 'NuanceQuery',
'NuanceSourceSearchEngine' => 'PhabricatorApplicationSearchEngine', 'NuanceSourceSearchEngine' => 'PhabricatorApplicationSearchEngine',
'NuanceSourceTransaction' => 'NuanceTransaction', 'NuanceSourceTransaction' => 'NuanceTransaction',
'NuanceSourceTransactionComment' => 'PhabricatorApplicationTransactionComment', 'NuanceSourceTransactionComment' => 'PhabricatorApplicationTransactionComment',
'NuanceSourceTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'NuanceSourceTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'NuanceSourceTransactionType' => 'PhabricatorModularTransactionType',
'NuanceSourceViewController' => 'NuanceSourceController', 'NuanceSourceViewController' => 'NuanceSourceController',
'NuanceTransaction' => 'PhabricatorApplicationTransaction', 'NuanceTransaction' => 'PhabricatorModularTransaction',
'NuanceTrashCommand' => 'NuanceCommandImplementation',
'NuanceWorker' => 'PhabricatorWorker', 'NuanceWorker' => 'PhabricatorWorker',
'OwnersConduitAPIMethod' => 'ConduitAPIMethod', 'OwnersConduitAPIMethod' => 'ConduitAPIMethod',
'OwnersEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'OwnersEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod',
@ -8825,10 +8876,12 @@ phutil_register_library_map(array(
'PhabricatorPeopleProfileManageController' => 'PhabricatorPeopleProfileController', 'PhabricatorPeopleProfileManageController' => 'PhabricatorPeopleProfileController',
'PhabricatorPeopleProfileMenuEngine' => 'PhabricatorProfileMenuEngine', 'PhabricatorPeopleProfileMenuEngine' => 'PhabricatorProfileMenuEngine',
'PhabricatorPeopleProfilePictureController' => 'PhabricatorPeopleProfileController', 'PhabricatorPeopleProfilePictureController' => 'PhabricatorPeopleProfileController',
'PhabricatorPeopleProfileRevisionsController' => 'PhabricatorPeopleProfileController',
'PhabricatorPeopleProfileTasksController' => 'PhabricatorPeopleProfileController', 'PhabricatorPeopleProfileTasksController' => 'PhabricatorPeopleProfileController',
'PhabricatorPeopleProfileViewController' => 'PhabricatorPeopleProfileController', 'PhabricatorPeopleProfileViewController' => 'PhabricatorPeopleProfileController',
'PhabricatorPeopleQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorPeopleQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorPeopleRenameController' => 'PhabricatorPeopleController', 'PhabricatorPeopleRenameController' => 'PhabricatorPeopleController',
'PhabricatorPeopleRevisionsProfileMenuItem' => 'PhabricatorProfileMenuItem',
'PhabricatorPeopleSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorPeopleSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorPeopleTasksProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorPeopleTasksProfileMenuItem' => 'PhabricatorProfileMenuItem',
'PhabricatorPeopleTestDataGenerator' => 'PhabricatorTestDataGenerator', 'PhabricatorPeopleTestDataGenerator' => 'PhabricatorTestDataGenerator',
@ -9032,6 +9085,7 @@ phutil_register_library_map(array(
'PhabricatorProjectEditController' => 'PhabricatorProjectController', 'PhabricatorProjectEditController' => 'PhabricatorProjectController',
'PhabricatorProjectEditEngine' => 'PhabricatorEditEngine', 'PhabricatorProjectEditEngine' => 'PhabricatorEditEngine',
'PhabricatorProjectEditPictureController' => 'PhabricatorProjectController', 'PhabricatorProjectEditPictureController' => 'PhabricatorProjectController',
'PhabricatorProjectFilterTransaction' => 'PhabricatorProjectTransactionType',
'PhabricatorProjectFulltextEngine' => 'PhabricatorFulltextEngine', 'PhabricatorProjectFulltextEngine' => 'PhabricatorFulltextEngine',
'PhabricatorProjectHeraldAction' => 'HeraldAction', 'PhabricatorProjectHeraldAction' => 'HeraldAction',
'PhabricatorProjectHeraldAdapter' => 'HeraldAdapter', 'PhabricatorProjectHeraldAdapter' => 'HeraldAdapter',
@ -9044,6 +9098,7 @@ phutil_register_library_map(array(
'PhabricatorProjectListController' => 'PhabricatorProjectController', 'PhabricatorProjectListController' => 'PhabricatorProjectController',
'PhabricatorProjectListView' => 'AphrontView', 'PhabricatorProjectListView' => 'AphrontView',
'PhabricatorProjectLockController' => 'PhabricatorProjectController', 'PhabricatorProjectLockController' => 'PhabricatorProjectController',
'PhabricatorProjectLockTransaction' => 'PhabricatorProjectTransactionType',
'PhabricatorProjectLogicalAncestorDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorProjectLogicalAncestorDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
'PhabricatorProjectLogicalDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorProjectLogicalDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
'PhabricatorProjectLogicalOrNotDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorProjectLogicalOrNotDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
@ -9061,6 +9116,7 @@ phutil_register_library_map(array(
'PhabricatorProjectMembersRemoveController' => 'PhabricatorProjectController', 'PhabricatorProjectMembersRemoveController' => 'PhabricatorProjectController',
'PhabricatorProjectMembersViewController' => 'PhabricatorProjectController', 'PhabricatorProjectMembersViewController' => 'PhabricatorProjectController',
'PhabricatorProjectMenuItemController' => 'PhabricatorProjectController', 'PhabricatorProjectMenuItemController' => 'PhabricatorProjectController',
'PhabricatorProjectMilestoneTransaction' => 'PhabricatorProjectTypeTransaction',
'PhabricatorProjectMoveController' => 'PhabricatorProjectController', 'PhabricatorProjectMoveController' => 'PhabricatorProjectController',
'PhabricatorProjectNameContextFreeGrammar' => 'PhutilContextFreeGrammar', 'PhabricatorProjectNameContextFreeGrammar' => 'PhutilContextFreeGrammar',
'PhabricatorProjectNameTransaction' => 'PhabricatorProjectTransactionType', 'PhabricatorProjectNameTransaction' => 'PhabricatorProjectTransactionType',
@ -9069,6 +9125,7 @@ phutil_register_library_map(array(
'PhabricatorProjectOrUserDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorProjectOrUserDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
'PhabricatorProjectOrUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorProjectOrUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
'PhabricatorProjectPHIDResolver' => 'PhabricatorPHIDResolver', 'PhabricatorProjectPHIDResolver' => 'PhabricatorPHIDResolver',
'PhabricatorProjectParentTransaction' => 'PhabricatorProjectTypeTransaction',
'PhabricatorProjectPictureProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorProjectPictureProfileMenuItem' => 'PhabricatorProfileMenuItem',
'PhabricatorProjectPointsProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorProjectPointsProfileMenuItem' => 'PhabricatorProfileMenuItem',
'PhabricatorProjectProfileController' => 'PhabricatorProjectController', 'PhabricatorProjectProfileController' => 'PhabricatorProjectController',
@ -9086,6 +9143,7 @@ phutil_register_library_map(array(
'PhabricatorProjectSilencedEdgeType' => 'PhabricatorEdgeType', 'PhabricatorProjectSilencedEdgeType' => 'PhabricatorEdgeType',
'PhabricatorProjectSlug' => 'PhabricatorProjectDAO', 'PhabricatorProjectSlug' => 'PhabricatorProjectDAO',
'PhabricatorProjectSlugsTransaction' => 'PhabricatorProjectTransactionType', 'PhabricatorProjectSlugsTransaction' => 'PhabricatorProjectTransactionType',
'PhabricatorProjectSortTransaction' => 'PhabricatorProjectTransactionType',
'PhabricatorProjectStandardCustomField' => array( 'PhabricatorProjectStandardCustomField' => array(
'PhabricatorProjectCustomField', 'PhabricatorProjectCustomField',
'PhabricatorStandardCustomFieldInterface', 'PhabricatorStandardCustomFieldInterface',
@ -9100,6 +9158,7 @@ phutil_register_library_map(array(
'PhabricatorProjectTransactionEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorProjectTransactionEditor' => 'PhabricatorApplicationTransactionEditor',
'PhabricatorProjectTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorProjectTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorProjectTransactionType' => 'PhabricatorModularTransactionType', 'PhabricatorProjectTransactionType' => 'PhabricatorModularTransactionType',
'PhabricatorProjectTypeTransaction' => 'PhabricatorProjectTransactionType',
'PhabricatorProjectUIEventListener' => 'PhabricatorEventListener', 'PhabricatorProjectUIEventListener' => 'PhabricatorEventListener',
'PhabricatorProjectUpdateController' => 'PhabricatorProjectController', 'PhabricatorProjectUpdateController' => 'PhabricatorProjectController',
'PhabricatorProjectUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorProjectUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
@ -9108,7 +9167,9 @@ phutil_register_library_map(array(
'PhabricatorProjectWatchController' => 'PhabricatorProjectController', 'PhabricatorProjectWatchController' => 'PhabricatorProjectController',
'PhabricatorProjectWatcherListView' => 'PhabricatorProjectUserListView', 'PhabricatorProjectWatcherListView' => 'PhabricatorProjectUserListView',
'PhabricatorProjectWorkboardBackgroundColor' => 'Phobject', 'PhabricatorProjectWorkboardBackgroundColor' => 'Phobject',
'PhabricatorProjectWorkboardBackgroundTransaction' => 'PhabricatorProjectTransactionType',
'PhabricatorProjectWorkboardProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorProjectWorkboardProfileMenuItem' => 'PhabricatorProfileMenuItem',
'PhabricatorProjectWorkboardTransaction' => 'PhabricatorProjectTransactionType',
'PhabricatorProjectsAncestorsSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment', 'PhabricatorProjectsAncestorsSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment',
'PhabricatorProjectsCurtainExtension' => 'PHUICurtainExtension', 'PhabricatorProjectsCurtainExtension' => 'PHUICurtainExtension',
'PhabricatorProjectsEditEngineExtension' => 'PhabricatorEditEngineExtension', 'PhabricatorProjectsEditEngineExtension' => 'PhabricatorEditEngineExtension',
@ -10266,11 +10327,14 @@ phutil_register_library_map(array(
), ),
'PhrictionDocumentAuthorHeraldField' => 'PhrictionDocumentHeraldField', 'PhrictionDocumentAuthorHeraldField' => 'PhrictionDocumentHeraldField',
'PhrictionDocumentContentHeraldField' => 'PhrictionDocumentHeraldField', 'PhrictionDocumentContentHeraldField' => 'PhrictionDocumentHeraldField',
'PhrictionDocumentContentTransaction' => 'PhrictionDocumentTransactionType',
'PhrictionDocumentController' => 'PhrictionController', 'PhrictionDocumentController' => 'PhrictionController',
'PhrictionDocumentDeleteTransaction' => 'PhrictionDocumentTransactionType',
'PhrictionDocumentFulltextEngine' => 'PhabricatorFulltextEngine', 'PhrictionDocumentFulltextEngine' => 'PhabricatorFulltextEngine',
'PhrictionDocumentHeraldAdapter' => 'HeraldAdapter', 'PhrictionDocumentHeraldAdapter' => 'HeraldAdapter',
'PhrictionDocumentHeraldField' => 'HeraldField', 'PhrictionDocumentHeraldField' => 'HeraldField',
'PhrictionDocumentHeraldFieldGroup' => 'HeraldFieldGroup', 'PhrictionDocumentHeraldFieldGroup' => 'HeraldFieldGroup',
'PhrictionDocumentMoveAwayTransaction' => 'PhrictionDocumentTransactionType',
'PhrictionDocumentMoveToTransaction' => 'PhrictionDocumentTransactionType', 'PhrictionDocumentMoveToTransaction' => 'PhrictionDocumentTransactionType',
'PhrictionDocumentPHIDType' => 'PhabricatorPHIDType', 'PhrictionDocumentPHIDType' => 'PhabricatorPHIDType',
'PhrictionDocumentPathHeraldField' => 'PhrictionDocumentHeraldField', 'PhrictionDocumentPathHeraldField' => 'PhrictionDocumentHeraldField',

View file

@ -125,7 +125,7 @@ final class PhabricatorCalendarEventViewController
->setName(pht('Imported')) ->setName(pht('Imported'))
->setIcon('fa-download') ->setIcon('fa-download')
->setHref($event->getImportSource()->getURI()) ->setHref($event->getImportSource()->getURI())
->setShade('orange')); ->setColor(PHUITagView::COLOR_ORANGE));
} }
foreach ($this->buildRSVPActions($event) as $action) { foreach ($this->buildRSVPActions($event) as $action) {

View file

@ -29,7 +29,7 @@ final class PHUIUserAvailabilityView
$away_tag = id(new PHUITagView()) $away_tag = id(new PHUITagView())
->setType(PHUITagView::TYPE_SHADE) ->setType(PHUITagView::TYPE_SHADE)
->setShade($color) ->setColor($color)
->setName($name) ->setName($name)
->setDotColor($color); ->setDotColor($color);

View file

@ -71,7 +71,7 @@ abstract class ConpherenceController extends PhabricatorController {
if (strlen($data['topic'])) { if (strlen($data['topic'])) {
$topic = id(new PHUITagView()) $topic = id(new PHUITagView())
->setName($data['topic']) ->setName($data['topic'])
->setShade(PHUITagView::COLOR_VIOLET) ->setColor(PHUITagView::COLOR_VIOLET)
->setType(PHUITagView::TYPE_SHADE) ->setType(PHUITagView::TYPE_SHADE)
->addClass('conpherence-header-topic'); ->addClass('conpherence-header-topic');
$header->addTag($topic); $header->addTag($topic);

View file

@ -19,10 +19,9 @@ final class PhabricatorDaemonLogGarbageCollector
queryfx( queryfx(
$conn_w, $conn_w,
'DELETE FROM %T WHERE dateCreated < %d AND status != %s LIMIT 100', 'DELETE FROM %T WHERE dateModified < %d LIMIT 100',
$table->getTableName(), $table->getTableName(),
$this->getGarbageEpoch(), $this->getGarbageEpoch());
PhabricatorDaemonLog::STATUS_RUNNING);
return ($conn_w->getAffectedRows() == 100); return ($conn_w->getAffectedRows() == 100);
} }

View file

@ -37,13 +37,13 @@ final class PhabricatorDaemonLog extends PhabricatorDaemonDAO
'status' => array( 'status' => array(
'columns' => array('status'), 'columns' => array('status'),
), ),
'dateCreated' => array(
'columns' => array('dateCreated'),
),
'key_daemonID' => array( 'key_daemonID' => array(
'columns' => array('daemonID'), 'columns' => array('daemonID'),
'unique' => true, 'unique' => true,
), ),
'key_modified' => array(
'columns' => array('dateModified'),
),
), ),
) + parent::getConfiguration(); ) + parent::getConfiguration();
} }

View file

@ -47,6 +47,7 @@ final class PhabricatorDashboardViewController
->setTag('a') ->setTag('a')
->setText('Install Dashboard') ->setText('Install Dashboard')
->setIcon('fa-plus') ->setIcon('fa-plus')
->setColor(PHUIButtonView::GREEN)
->setWorkflow(true) ->setWorkflow(true)
->setHref($this->getApplicationURI("/install/{$id}/")); ->setHref($this->getApplicationURI("/install/{$id}/"));
$header->addActionLink($install_button); $header->addActionLink($install_button);

View file

@ -65,7 +65,7 @@ final class DifferentialRevisionStatus extends Phobject {
$tag = id(new PHUITagView()) $tag = id(new PHUITagView())
->setName($status_name) ->setName($status_name)
->setIcon(self::getRevisionStatusIcon($status)) ->setIcon(self::getRevisionStatusIcon($status))
->setShade(self::getRevisionStatusColor($status)) ->setColor(self::getRevisionStatusColor($status))
->setType(PHUITagView::TYPE_SHADE); ->setType(PHUITagView::TYPE_SHADE);
return $tag; return $tag;

View file

@ -1,23 +0,0 @@
<?php
final class DifferentialDraft extends DifferentialDAO {
protected $objectPHID;
protected $authorPHID;
protected $draftKey;
protected function getConfiguration() {
return array(
self::CONFIG_COLUMN_SCHEMA => array(
'draftKey' => 'text64',
),
self::CONFIG_KEY_SCHEMA => array(
'key_unique' => array(
'columns' => array('objectPHID', 'authorPHID', 'draftKey'),
'unique' => true,
),
),
) + parent::getConfiguration();
}
}

View file

@ -50,7 +50,8 @@ final class DifferentialRevisionAcceptTransaction
protected function getActionOptions( protected function getActionOptions(
PhabricatorUser $viewer, PhabricatorUser $viewer,
DifferentialRevision $revision) { DifferentialRevision $revision,
$include_accepted = false) {
$reviewers = $revision->getReviewers(); $reviewers = $revision->getReviewers();
@ -98,10 +99,13 @@ final class DifferentialRevisionAcceptTransaction
} }
} }
if ($reviewer->isAccepted($diff_phid)) { if (!$include_accepted) {
// If a reviewer is already in a full "accepted" state, don't if ($reviewer->isAccepted($diff_phid)) {
// include that reviewer as an option. // If a reviewer is already in a full "accepted" state, don't
continue; // include that reviewer as an option unless we're listing all
// reviwers, including reviewers who have already accepted.
continue;
}
} }
$reviewer_phids[$reviewer_phid] = $reviewer_phid; $reviewer_phids[$reviewer_phid] = $reviewer_phid;
@ -185,7 +189,12 @@ final class DifferentialRevisionAcceptTransaction
'least one reviewer.')); 'least one reviewer.'));
} }
list($options) = $this->getActionOptions($actor, $object); // NOTE: We're including reviewers who have already been accepted in this
// check. Legitimate users may race one another to accept on behalf of
// packages. If we get a form submission which includes a reviewer which
// someone has already accepted, that's fine. See T12757.
list($options) = $this->getActionOptions($actor, $object, true);
foreach ($value as $phid) { foreach ($value as $phid) {
if (!isset($options[$phid])) { if (!isset($options[$phid])) {
throw new Exception( throw new Exception(

View file

@ -17,6 +17,16 @@ abstract class DifferentialRevisionReviewTransaction
$viewer = $this->getActor(); $viewer = $this->getActor();
list($options, $default) = $this->getActionOptions($viewer, $object); list($options, $default) = $this->getActionOptions($viewer, $object);
// Remove reviewers which aren't actionable. In the case of "Accept", we
// may allow the transaction to proceed with some reviewers who have
// already accepted, to avoid race conditions where two reviewers fill
// out the form at the same time and accept on behalf of the same package.
// It's okay for these reviewers to survive validation, but they should
// not survive beyond this point.
$value = array_fuse($value);
$value = array_intersect($value, array_keys($options));
$value = array_values($value);
sort($default); sort($default);
sort($value); sort($value);

View file

@ -332,7 +332,7 @@ abstract class DiffusionController extends PhabricatorController {
$tag = id(new PHUITagView()) $tag = id(new PHUITagView())
->setName($commit) ->setName($commit)
->setShade('indigo') ->setColor(PHUITagView::COLOR_INDIGO)
->setType(PHUITagView::TYPE_SHADE); ->setType(PHUITagView::TYPE_SHADE);
return $tag; return $tag;

View file

@ -83,11 +83,11 @@ final class DiffusionRepositoryManagePanelsController
->setTag('a') ->setTag('a')
->setText(pht('View Repository')) ->setText(pht('View Repository'))
->setHref($repository->getURI()) ->setHref($repository->getURI())
->setIcon('fa-code')); ->setIcon('fa-code')
->setColor(PHUIButtonView::GREEN));
$view = id(new PHUITwoColumnView()) $view = id(new PHUITwoColumnView())
->setHeader($header) ->setHeader($header)
->setNavigation($nav)
->setMainColumn($content); ->setMainColumn($content);
$curtain = $panel->buildManagementPanelCurtain(); $curtain = $panel->buildManagementPanelCurtain();
@ -98,6 +98,7 @@ final class DiffusionRepositoryManagePanelsController
return $this->newPage() return $this->newPage()
->setTitle($title) ->setTitle($title)
->setCrumbs($crumbs) ->setCrumbs($crumbs)
->setNavigation($nav)
->appendChild($view); ->appendChild($view);
} }
@ -112,6 +113,12 @@ final class DiffusionRepositoryManagePanelsController
$nav = id(new AphrontSideNavFilterView()) $nav = id(new AphrontSideNavFilterView())
->setBaseURI($base_uri); ->setBaseURI($base_uri);
$item = id(new PHUIListItemView())
->setName(pht('manage'))
->setType(PHUIListItemView::TYPE_LABEL);
$nav->addMenuItem($item);
foreach ($panels as $panel) { foreach ($panels as $panel) {
$key = $panel->getManagementPanelKey(); $key = $panel->getManagementPanelKey();
$label = $panel->getManagementPanelLabel(); $label = $panel->getManagementPanelLabel();

View file

@ -37,9 +37,10 @@ final class DiffusionRepositoryActionsManagementPanel
); );
} }
protected function buildManagementPanelActions() { public function buildManagementPanelCurtain() {
$repository = $this->getRepository(); $repository = $this->getRepository();
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$action_list = $this->getNewActionList();
$can_edit = PhabricatorPolicyFilter::hasCapability( $can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer, $viewer,
@ -48,14 +49,15 @@ final class DiffusionRepositoryActionsManagementPanel
$actions_uri = $this->getEditPageURI(); $actions_uri = $this->getEditPageURI();
return array( $action_list->addAction(
id(new PhabricatorActionView()) id(new PhabricatorActionView())
->setIcon('fa-pencil') ->setIcon('fa-pencil')
->setName(pht('Edit Actions')) ->setName(pht('Edit Actions'))
->setHref($actions_uri) ->setHref($actions_uri)
->setDisabled(!$can_edit) ->setDisabled(!$can_edit)
->setWorkflow(!$can_edit), ->setWorkflow(!$can_edit));
);
return $this->getNewCurtainView($action_list);
} }
public function buildManagementPanelContent() { public function buildManagementPanelContent() {
@ -63,8 +65,7 @@ final class DiffusionRepositoryActionsManagementPanel
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$view = id(new PHUIPropertyListView()) $view = id(new PHUIPropertyListView())
->setViewer($viewer) ->setViewer($viewer);
->setActionList($this->newActions());
$notify = $repository->getDetail('herald-disabled') $notify = $repository->getDetail('herald-disabled')
? pht('Off') ? pht('Off')

View file

@ -46,9 +46,10 @@ final class DiffusionRepositoryAutomationManagementPanel
return 'fa-truck'; return 'fa-truck';
} }
protected function buildManagementPanelActions() { public function buildManagementPanelCurtain() {
$repository = $this->getRepository(); $repository = $this->getRepository();
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$action_list = $this->getNewActionList();
$can_edit = PhabricatorPolicyFilter::hasCapability( $can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer, $viewer,
@ -60,20 +61,23 @@ final class DiffusionRepositoryAutomationManagementPanel
$automation_uri = $this->getEditPageURI(); $automation_uri = $this->getEditPageURI();
$test_uri = $repository->getPathURI('edit/testautomation/'); $test_uri = $repository->getPathURI('edit/testautomation/');
return array( $action_list->addAction(
id(new PhabricatorActionView()) id(new PhabricatorActionView())
->setIcon('fa-pencil') ->setIcon('fa-pencil')
->setName(pht('Edit Automation')) ->setName(pht('Edit Automation'))
->setHref($automation_uri) ->setHref($automation_uri)
->setDisabled(!$can_edit) ->setDisabled(!$can_edit)
->setWorkflow(!$can_edit), ->setWorkflow(!$can_edit));
$action_list->addAction(
id(new PhabricatorActionView()) id(new PhabricatorActionView())
->setIcon('fa-gamepad') ->setIcon('fa-gamepad')
->setName(pht('Test Configuration')) ->setName(pht('Test Configuration'))
->setWorkflow(true) ->setWorkflow(true)
->setDisabled(!$can_test) ->setDisabled(!$can_test)
->setHref($test_uri), ->setHref($test_uri));
);
return $this->getNewCurtainView($action_list);
} }
public function buildManagementPanelContent() { public function buildManagementPanelContent() {
@ -81,8 +85,7 @@ final class DiffusionRepositoryAutomationManagementPanel
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$view = id(new PHUIPropertyListView()) $view = id(new PHUIPropertyListView())
->setViewer($viewer) ->setViewer($viewer);
->setActionList($this->newActions());
$blueprint_phids = $repository->getAutomationBlueprintPHIDs(); $blueprint_phids = $repository->getAutomationBlueprintPHIDs();
if (!$blueprint_phids) { if (!$blueprint_phids) {

View file

@ -33,9 +33,10 @@ final class DiffusionRepositoryBasicsManagementPanel
); );
} }
protected function buildManagementPanelActions() { public function buildManagementPanelCurtain() {
$repository = $this->getRepository(); $repository = $this->getRepository();
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$action_list = $this->getNewActionList();
$can_edit = PhabricatorPolicyFilter::hasCapability( $can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer, $viewer,
@ -67,38 +68,47 @@ final class DiffusionRepositoryBasicsManagementPanel
$can_dangerous = ($can_edit && $repository->canAllowDangerousChanges()); $can_dangerous = ($can_edit && $repository->canAllowDangerousChanges());
} }
return array( $action_list->addAction(
id(new PhabricatorActionView()) id(new PhabricatorActionView())
->setIcon('fa-pencil') ->setIcon('fa-pencil')
->setName(pht('Edit Basic Information')) ->setName(pht('Edit Basic Information'))
->setHref($edit_uri) ->setHref($edit_uri)
->setDisabled(!$can_edit) ->setDisabled(!$can_edit)
->setWorkflow(!$can_edit), ->setWorkflow(!$can_edit));
$action_list->addAction(
id(new PhabricatorActionView()) id(new PhabricatorActionView())
->setIcon('fa-text-width') ->setIcon('fa-text-width')
->setName(pht('Edit Text Encoding')) ->setName(pht('Edit Text Encoding'))
->setHref($encoding_uri) ->setHref($encoding_uri)
->setDisabled(!$can_edit) ->setDisabled(!$can_edit)
->setWorkflow(!$can_edit), ->setWorkflow(!$can_edit));
$action_list->addAction(
id(new PhabricatorActionView()) id(new PhabricatorActionView())
->setIcon($dangerous_icon) ->setIcon($dangerous_icon)
->setName($dangerous_name) ->setName($dangerous_name)
->setHref($dangerous_uri) ->setHref($dangerous_uri)
->setDisabled(!$can_dangerous) ->setDisabled(!$can_dangerous)
->setWorkflow(true), ->setWorkflow(true));
$action_list->addAction(
id(new PhabricatorActionView()) id(new PhabricatorActionView())
->setHref($activate_uri) ->setHref($activate_uri)
->setIcon($activate_icon) ->setIcon($activate_icon)
->setName($activate_label) ->setName($activate_label)
->setDisabled(!$can_edit) ->setDisabled(!$can_edit)
->setWorkflow(true), ->setWorkflow(true));
$action_list->addAction(
id(new PhabricatorActionView()) id(new PhabricatorActionView())
->setName(pht('Delete Repository')) ->setName(pht('Delete Repository'))
->setIcon('fa-times') ->setIcon('fa-times')
->setHref($delete_uri) ->setHref($delete_uri)
->setDisabled(true) ->setDisabled(true)
->setWorkflow(true), ->setWorkflow(true));
);
return $this->getNewCurtainView($action_list);
} }
public function buildManagementPanelContent() { public function buildManagementPanelContent() {
@ -108,6 +118,7 @@ final class DiffusionRepositoryBasicsManagementPanel
$repository = $this->getRepository(); $repository = $this->getRepository();
$is_new = $repository->isNewlyInitialized(); $is_new = $repository->isNewlyInitialized();
$info_view = null;
if ($is_new) { if ($is_new) {
$messages = array(); $messages = array();
@ -131,8 +142,6 @@ final class DiffusionRepositoryBasicsManagementPanel
$info_view = id(new PHUIInfoView()) $info_view = id(new PHUIInfoView())
->setSeverity(PHUIInfoView::SEVERITY_NOTICE) ->setSeverity(PHUIInfoView::SEVERITY_NOTICE)
->setErrors($messages); ->setErrors($messages);
$basics->setInfoView($info_view);
} }
$result[] = $basics; $result[] = $basics;
@ -142,7 +151,7 @@ final class DiffusionRepositoryBasicsManagementPanel
$result[] = $this->newBox(pht('Description'), $description); $result[] = $this->newBox(pht('Description'), $description);
} }
return $result; return array($info_view, $result);
} }
private function buildBasics() { private function buildBasics() {
@ -150,8 +159,7 @@ final class DiffusionRepositoryBasicsManagementPanel
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$view = id(new PHUIPropertyListView()) $view = id(new PHUIPropertyListView())
->setViewer($viewer) ->setViewer($viewer);
->setActionList($this->newActions());
$name = $repository->getName(); $name = $repository->getName();
$view->addProperty(pht('Name'), $name); $view->addProperty(pht('Name'), $name);

View file

@ -41,9 +41,10 @@ final class DiffusionRepositoryBranchesManagementPanel
); );
} }
protected function buildManagementPanelActions() { public function buildManagementPanelCurtain() {
$repository = $this->getRepository(); $repository = $this->getRepository();
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$action_list = $this->getNewActionList();
$can_edit = PhabricatorPolicyFilter::hasCapability( $can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer, $viewer,
@ -52,14 +53,15 @@ final class DiffusionRepositoryBranchesManagementPanel
$branches_uri = $this->getEditPageURI(); $branches_uri = $this->getEditPageURI();
return array( $action_list->addAction(
id(new PhabricatorActionView()) id(new PhabricatorActionView())
->setIcon('fa-pencil') ->setIcon('fa-pencil')
->setName(pht('Edit Branches')) ->setName(pht('Edit Branches'))
->setHref($branches_uri) ->setHref($branches_uri)
->setDisabled(!$can_edit) ->setDisabled(!$can_edit)
->setWorkflow(!$can_edit), ->setWorkflow(!$can_edit));
);
return $this->getNewCurtainView($action_list);
} }
public function buildManagementPanelContent() { public function buildManagementPanelContent() {
@ -67,8 +69,7 @@ final class DiffusionRepositoryBranchesManagementPanel
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$view = id(new PHUIPropertyListView()) $view = id(new PHUIPropertyListView())
->setViewer($viewer) ->setViewer($viewer);
->setActionList($this->newActions());
$default_branch = nonempty( $default_branch = nonempty(
$repository->getHumanReadableDetail('default-branch'), $repository->getHumanReadableDetail('default-branch'),

View file

@ -21,6 +21,10 @@ final class DiffusionRepositoryDocumentationManagementPanel
return null; return null;
} }
public function buildManagementPanelCurtain() {
return null;
}
public function getPanelNavigationURI() { public function getPanelNavigationURI() {
return PhabricatorEnv::getDoclink( return PhabricatorEnv::getDoclink(
'Diffusion User Guide: Managing Repositories'); 'Diffusion User Guide: Managing Repositories');

View file

@ -21,5 +21,8 @@ final class DiffusionRepositoryHistoryManagementPanel
return $this->newTimeline(); return $this->newTimeline();
} }
public function buildManagementPanelCurtain() {
return null;
}
} }

View file

@ -37,6 +37,7 @@ abstract class DiffusionRepositoryManagementPanel
abstract public function getManagementPanelLabel(); abstract public function getManagementPanelLabel();
abstract public function getManagementPanelOrder(); abstract public function getManagementPanelOrder();
abstract public function buildManagementPanelContent(); abstract public function buildManagementPanelContent();
abstract public function buildManagementPanelCurtain();
public function getManagementPanelIcon() { public function getManagementPanelIcon() {
return 'fa-pencil'; return 'fa-pencil';
@ -51,41 +52,20 @@ abstract class DiffusionRepositoryManagementPanel
return true; return true;
} }
final protected function newActions() { public function getNewActionList() {
$actions = $this->buildManagementPanelActions();
if (!$actions) {
return null;
}
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$action_id = celerity_generate_unique_node_id();
$action_list = id(new PhabricatorActionListView()) return id(new PhabricatorActionListView())
->setViewer($viewer); ->setViewer($viewer)
->setID($action_id);
foreach ($actions as $action) {
$action_list->addAction($action);
}
return $action_list;
} }
public function buildManagementPanelCurtain() { public function getNewCurtainView(PhabricatorActionListView $action_list) {
// TODO: Delete or fix this, curtains always render in the left gutter
// at the moment.
return null;
$actions = $this->newActions();
if (!$actions) {
return null;
}
$viewer = $this->getViewer(); $viewer = $this->getViewer();
return id(new PHUICurtainView())
$curtain = id(new PHUICurtainView())
->setViewer($viewer) ->setViewer($viewer)
->setActionList($actions); ->setActionList($action_list);
return $curtain;
} }
public static function getAllPanels() { public static function getAllPanels() {

View file

@ -54,9 +54,10 @@ final class DiffusionRepositoryPoliciesManagementPanel
); );
} }
protected function buildManagementPanelActions() { public function buildManagementPanelCurtain() {
$repository = $this->getRepository(); $repository = $this->getRepository();
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$action_list = $this->getNewActionList();
$can_edit = PhabricatorPolicyFilter::hasCapability( $can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer, $viewer,
@ -65,14 +66,15 @@ final class DiffusionRepositoryPoliciesManagementPanel
$edit_uri = $this->getEditPageURI(); $edit_uri = $this->getEditPageURI();
return array( $action_list->addAction(
id(new PhabricatorActionView()) id(new PhabricatorActionView())
->setIcon('fa-pencil') ->setIcon('fa-pencil')
->setName(pht('Edit Policies')) ->setName(pht('Edit Policies'))
->setHref($edit_uri) ->setHref($edit_uri)
->setDisabled(!$can_edit) ->setDisabled(!$can_edit)
->setWorkflow(!$can_edit), ->setWorkflow(!$can_edit));
);
return $this->getNewCurtainView($action_list);
} }
public function buildManagementPanelContent() { public function buildManagementPanelContent() {
@ -80,8 +82,7 @@ final class DiffusionRepositoryPoliciesManagementPanel
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$view = id(new PHUIPropertyListView()) $view = id(new PHUIPropertyListView())
->setViewer($viewer) ->setViewer($viewer);
->setActionList($this->newActions());
$descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions( $descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions(
$viewer, $viewer,

View file

@ -37,9 +37,10 @@ final class DiffusionRepositoryStagingManagementPanel
); );
} }
protected function buildManagementPanelActions() { public function buildManagementPanelCurtain() {
$repository = $this->getRepository(); $repository = $this->getRepository();
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$action_list = $this->getNewActionList();
$can_edit = PhabricatorPolicyFilter::hasCapability( $can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer, $viewer,
@ -48,14 +49,15 @@ final class DiffusionRepositoryStagingManagementPanel
$staging_uri = $this->getEditPageURI(); $staging_uri = $this->getEditPageURI();
return array( $action_list->addAction(
id(new PhabricatorActionView()) id(new PhabricatorActionView())
->setIcon('fa-pencil') ->setIcon('fa-pencil')
->setName(pht('Edit Staging')) ->setName(pht('Edit Staging'))
->setHref($staging_uri) ->setHref($staging_uri)
->setDisabled(!$can_edit) ->setDisabled(!$can_edit)
->setWorkflow(!$can_edit), ->setWorkflow(!$can_edit));
);
return $this->getNewCurtainView($action_list);
} }
public function buildManagementPanelContent() { public function buildManagementPanelContent() {
@ -63,8 +65,7 @@ final class DiffusionRepositoryStagingManagementPanel
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$view = id(new PHUIPropertyListView()) $view = id(new PHUIPropertyListView())
->setViewer($viewer) ->setViewer($viewer);
->setActionList($this->newActions());
$staging_uri = $repository->getStagingURI(); $staging_uri = $repository->getStagingURI();
if (!$staging_uri) { if (!$staging_uri) {

View file

@ -28,9 +28,10 @@ final class DiffusionRepositoryStatusManagementPanel
return 'fa-check grey'; return 'fa-check grey';
} }
protected function buildManagementPanelActions() { public function buildManagementPanelCurtain() {
$repository = $this->getRepository(); $repository = $this->getRepository();
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$action_list = $this->getNewActionList();
$can_edit = PhabricatorPolicyFilter::hasCapability( $can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer, $viewer,
@ -39,14 +40,15 @@ final class DiffusionRepositoryStatusManagementPanel
$update_uri = $repository->getPathURI('edit/update/'); $update_uri = $repository->getPathURI('edit/update/');
return array( $action_list->addAction(
id(new PhabricatorActionView()) id(new PhabricatorActionView())
->setIcon('fa-refresh') ->setIcon('fa-refresh')
->setName(pht('Update Now')) ->setName(pht('Update Now'))
->setWorkflow(true) ->setWorkflow(true)
->setDisabled(!$can_edit) ->setDisabled(!$can_edit)
->setHref($update_uri), ->setHref($update_uri));
);
return $this->getNewCurtainView($action_list);
} }
public function buildManagementPanelContent() { public function buildManagementPanelContent() {
@ -54,8 +56,7 @@ final class DiffusionRepositoryStatusManagementPanel
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$view = id(new PHUIPropertyListView()) $view = id(new PHUIPropertyListView())
->setViewer($viewer) ->setViewer($viewer);
->setActionList($this->newActions());
$view->addProperty( $view->addProperty(
pht('Update Frequency'), pht('Update Frequency'),

View file

@ -25,6 +25,22 @@ final class DiffusionRepositoryStorageManagementPanel
} }
} }
public function buildManagementPanelCurtain() {
$repository = $this->getRepository();
$viewer = $this->getViewer();
$action_list = $this->getNewActionList();
$doc_href = PhabricatorEnv::getDoclink('Cluster: Repositories');
$action_list->addAction(
id(new PhabricatorActionView())
->setIcon('fa-book')
->setHref($doc_href)
->setName(pht('Cluster Documentation')));
return $this->getNewCurtainView($action_list);
}
public function buildManagementPanelContent() { public function buildManagementPanelContent() {
return array( return array(
$this->buildStorageStatusPanel(), $this->buildStorageStatusPanel(),
@ -55,13 +71,9 @@ final class DiffusionRepositoryStorageManagementPanel
$view->addProperty(pht('Storage Path'), $storage_path); $view->addProperty(pht('Storage Path'), $storage_path);
$view->addProperty(pht('Storage Cluster'), $storage_service); $view->addProperty(pht('Storage Cluster'), $storage_service);
$header = id(new PHUIHeaderView()) $box = $this->newBox(pht('Storage'), null);
->setHeader(pht('Storage')); $box->addPropertyList($view);
return $box;
return id(new PHUIObjectBoxView())
->setHeader($header)
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->addPropertyList($view);
} }
private function buildClusterStatusPanel() { private function buildClusterStatusPanel() {
@ -231,21 +243,9 @@ final class DiffusionRepositoryStorageManagementPanel
'date', 'date',
)); ));
$doc_href = PhabricatorEnv::getDoclink('Cluster: Repositories'); $box = $this->newBox(pht('Cluster Status'), null);
$box->setTable($table);
$header = id(new PHUIHeaderView()) return $box;
->setHeader(pht('Cluster Status'))
->addActionLink(
id(new PHUIButtonView())
->setIcon('fa-book')
->setHref($doc_href)
->setTag('a')
->setText(pht('Documentation')));
return id(new PHUIObjectBoxView())
->setHeader($header)
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($table);
} }
} }

View file

@ -36,9 +36,10 @@ final class DiffusionRepositorySubversionManagementPanel
); );
} }
protected function buildManagementPanelActions() { public function buildManagementPanelCurtain() {
$repository = $this->getRepository(); $repository = $this->getRepository();
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$action_list = $this->getNewActionList();
$can_edit = PhabricatorPolicyFilter::hasCapability( $can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer, $viewer,
@ -47,14 +48,15 @@ final class DiffusionRepositorySubversionManagementPanel
$subversion_uri = $this->getEditPageURI(); $subversion_uri = $this->getEditPageURI();
return array( $action_list->addAction(
id(new PhabricatorActionView()) id(new PhabricatorActionView())
->setIcon('fa-pencil') ->setIcon('fa-pencil')
->setName(pht('Edit Properties')) ->setName(pht('Edit Properties'))
->setHref($subversion_uri) ->setHref($subversion_uri)
->setDisabled(!$can_edit) ->setDisabled(!$can_edit)
->setWorkflow(!$can_edit), ->setWorkflow(!$can_edit));
);
return $this->getNewCurtainView($action_list);
} }
public function buildManagementPanelContent() { public function buildManagementPanelContent() {
@ -62,8 +64,7 @@ final class DiffusionRepositorySubversionManagementPanel
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$view = id(new PHUIPropertyListView()) $view = id(new PHUIPropertyListView())
->setViewer($viewer) ->setViewer($viewer);
->setActionList($this->newActions());
$default_branch = nonempty( $default_branch = nonempty(
$repository->getHumanReadableDetail('svn-subpath'), $repository->getHumanReadableDetail('svn-subpath'),

View file

@ -34,9 +34,10 @@ final class DiffusionRepositorySymbolsManagementPanel
); );
} }
protected function buildManagementPanelActions() { public function buildManagementPanelCurtain() {
$repository = $this->getRepository(); $repository = $this->getRepository();
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$action_list = $this->getNewActionList();
$can_edit = PhabricatorPolicyFilter::hasCapability( $can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer, $viewer,
@ -45,14 +46,15 @@ final class DiffusionRepositorySymbolsManagementPanel
$symbols_uri = $this->getEditPageURI(); $symbols_uri = $this->getEditPageURI();
return array( $action_list->addAction(
id(new PhabricatorActionView()) id(new PhabricatorActionView())
->setIcon('fa-pencil') ->setIcon('fa-pencil')
->setName(pht('Edit Symbols')) ->setName(pht('Edit Symbols'))
->setHref($symbols_uri) ->setHref($symbols_uri)
->setDisabled(!$can_edit) ->setDisabled(!$can_edit)
->setWorkflow(!$can_edit), ->setWorkflow(!$can_edit));
);
return $this->getNewCurtainView($action_list);
} }
public function buildManagementPanelContent() { public function buildManagementPanelContent() {
@ -60,8 +62,7 @@ final class DiffusionRepositorySymbolsManagementPanel
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$view = id(new PHUIPropertyListView()) $view = id(new PHUIPropertyListView())
->setViewer($viewer) ->setViewer($viewer);
->setActionList($this->newActions());
$languages = $repository->getSymbolLanguages(); $languages = $repository->getSymbolLanguages();
if ($languages) { if ($languages) {

View file

@ -17,6 +17,35 @@ final class DiffusionRepositoryURIsManagementPanel
return 400; return 400;
} }
public function buildManagementPanelCurtain() {
$repository = $this->getRepository();
$viewer = $this->getViewer();
$action_list = $this->getNewActionList();
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$repository,
PhabricatorPolicyCapability::CAN_EDIT);
$doc_href = PhabricatorEnv::getDoclink('Diffusion User Guide: URIs');
$add_href = $repository->getPathURI('uri/edit/');
$action_list->addAction(
id(new PhabricatorActionView())
->setIcon('fa-plus')
->setHref($add_href)
->setDisabled(!$can_edit)
->setName(pht('Add New URI')));
$action_list->addAction(
id(new PhabricatorActionView())
->setIcon('fa-book')
->setHref($doc_href)
->setName(pht('URI Documentation')));
return $this->getNewCurtainView($action_list);
}
public function buildManagementPanelContent() { public function buildManagementPanelContent() {
$repository = $this->getRepository(); $repository = $this->getRepository();
$viewer = $this->getViewer(); $viewer = $this->getViewer();
@ -95,24 +124,6 @@ final class DiffusionRepositoryURIsManagementPanel
null, null,
)); ));
$doc_href = PhabricatorEnv::getDoclink('Diffusion User Guide: URIs');
$add_href = $repository->getPathURI('uri/edit/');
$header = id(new PHUIHeaderView())
->setHeader(pht('Repository URIs'))
->addActionLink(
id(new PHUIButtonView())
->setIcon('fa-plus')
->setHref($add_href)
->setTag('a')
->setText(pht('Add New URI')))
->addActionLink(
id(new PHUIButtonView())
->setIcon('fa-book')
->setHref($doc_href)
->setTag('a')
->setText(pht('Documentation')));
$is_new = $repository->isNewlyInitialized(); $is_new = $repository->isNewlyInitialized();
$messages = array(); $messages = array();
@ -123,11 +134,7 @@ final class DiffusionRepositoryURIsManagementPanel
$host_message = pht('Phabricator is hosting this repository.'); $host_message = pht('Phabricator is hosting this repository.');
} }
$messages[] = array( $messages[] = $host_message;
id(new PHUIIconView())->setIcon('fa-folder'),
' ',
$host_message,
);
} else { } else {
if ($is_new) { if ($is_new) {
$observe_message = pht( $observe_message = pht(
@ -137,22 +144,17 @@ final class DiffusionRepositoryURIsManagementPanel
'This repository is hosted remotely. Phabricator is observing it.'); 'This repository is hosted remotely. Phabricator is observing it.');
} }
$messages[] = array( $messages[] = $observe_message;
id(new PHUIIconView())->setIcon('fa-download'),
' ',
$observe_message,
);
} }
$info_view = id(new PHUIInfoView()) $info_view = id(new PHUIInfoView())
->setSeverity(PHUIInfoView::SEVERITY_NOTICE) ->setSeverity(PHUIInfoView::SEVERITY_NOTICE)
->setErrors($messages); ->setErrors($messages);
return id(new PHUIObjectBoxView()) $box = $this->newBox(pht('Repository URIs'), null);
->setHeader($header) $box->setTable($table);
->setInfoView($info_view)
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) return array($info_view, $box);
->setTable($table);
} }
} }

View file

@ -0,0 +1,160 @@
<?php
final class DiffusionCommitListView extends AphrontView {
private $commits = array();
private $noDataString;
public function setNoDataString($no_data_string) {
$this->noDataString = $no_data_string;
return $this;
}
public function setHeader($header) {
$this->header = $header;
return $this;
}
public function setCommits(array $commits) {
assert_instances_of($commits, 'PhabricatorRepositoryCommit');
$this->commits = mpull($commits, null, 'getPHID');
return $this;
}
public function getCommits() {
return $this->commits;
}
private function getCommitDescription($phid) {
if ($this->commits === null) {
return pht('(Unknown Commit)');
}
$commit = idx($this->commits, $phid);
if (!$commit) {
return pht('(Unknown Commit)');
}
$summary = $commit->getCommitData()->getSummary();
if (strlen($summary)) {
return $summary;
}
// No summary, so either this is still importing or just has an empty
// commit message.
if (!$commit->isImported()) {
return pht('(Importing Commit...)');
} else {
return pht('(Untitled Commit)');
}
}
public function render() {
require_celerity_resource('diffusion-history-css');
return $this->buildList();
}
public function buildList() {
$viewer = $this->getViewer();
$rowc = array();
$phids = array();
foreach ($this->getCommits() as $commit) {
$phids[] = $commit->getPHID();
$author_phid = $commit->getAuthorPHID();
if ($author_phid) {
$phids[] = $author_phid;
}
}
$handles = $viewer->loadHandles($phids);
$cur_date = 0;
$list = null;
$header = null;
$view = array();
foreach ($this->commits as $commit) {
$new_date = date('Ymd', $commit->getEpoch());
if ($cur_date != $new_date) {
if ($list) {
$view[] = id(new PHUIObjectBoxView())
->setHeader($header)
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setObjectList($list);
}
$date = ucfirst(
phabricator_relative_date($commit->getEpoch(), $viewer));
$header = id(new PHUIHeaderView())
->setHeader($date);
$list = id(new PHUIObjectItemListView())
->setFlush(true)
->addClass('diffusion-history-list');
}
$commit_phid = $commit->getPHID();
$commit_handle = $handles[$commit_phid];
$committed = null;
$commit_name = $commit_handle->getName();
$commit_link = $commit_handle->getURI();
$commit_desc = $this->getCommitDescription($commit_phid);
$committed = phabricator_datetime($commit->getEpoch(), $viewer);
$engine = PhabricatorMarkupEngine::newDifferentialMarkupEngine();
$engine->setConfig('viewer', $viewer);
$commit_data = $commit->getCommitData();
$message = $commit_data->getCommitMessage();
$message = $engine->markupText($message);
$message = phutil_tag_div(
'diffusion-history-message phabricator-remarkup', $message);
$author_phid = $commit->getAuthorPHID();
if ($author_phid) {
$author_name = $handles[$author_phid]->renderLink();
$author_image_uri = $handles[$author_phid]->getImageURI();
$author_image_href = $handles[$author_phid]->getURI();
} else {
$author_name = $commit->getCommitData()->getAuthorName();
$author_image_uri =
celerity_get_resource_uri('/rsrc/image/people/user0.png');
$author_image_href = null;
}
$commit_tag = id(new PHUITagView())
->setName($commit_name)
->setType(PHUITagView::TYPE_SHADE)
->setColor(PHUITagView::COLOR_INDIGO)
->setSlimShady(true);
$item = id(new PHUIObjectItemView())
->setHeader($commit_desc)
->setHref($commit_link)
->setDisabled($commit->isUnreachable())
->setDescription($message)
->setImageURI($author_image_uri)
->setImageHref($author_image_href)
->addByline(pht('Author: %s', $author_name))
->addIcon('none', $committed)
->addAttribute($commit_tag);
$list->addItem($item);
$cur_date = $new_date;
}
if (!$view) {
$list = id(new PHUIObjectItemListView())
->setFlush(true)
->setNoDataString($this->noDataString);
$view = id(new PHUIObjectBoxView())
->setHeaderText(pht('Recent Commits'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setObjectList($list);
}
return $view;
}
}

View file

@ -67,16 +67,16 @@ final class FeedQueryConduitAPIMethod extends FeedConduitAPIMethod {
if (!$limit) { if (!$limit) {
$limit = $this->getDefaultLimit(); $limit = $this->getDefaultLimit();
} }
$filter_phids = $request->getValue('filterPHIDs');
if (!$filter_phids) {
$filter_phids = array();
}
$query = id(new PhabricatorFeedQuery()) $query = id(new PhabricatorFeedQuery())
->setLimit($limit) ->setLimit($limit)
->setFilterPHIDs($filter_phids)
->setViewer($user); ->setViewer($user);
$filter_phids = $request->getValue('filterPHIDs');
if ($filter_phids) {
$query->withFilterPHIDs($filter_phids);
}
$after = $request->getValue('after'); $after = $request->getValue('after');
if (strlen($after)) { if (strlen($after)) {
$query->setAfterID($after); $query->setAfterID($after);

View file

@ -5,8 +5,10 @@ final class PhabricatorFeedQuery
private $filterPHIDs; private $filterPHIDs;
private $chronologicalKeys; private $chronologicalKeys;
private $rangeMin;
private $rangeMax;
public function setFilterPHIDs(array $phids) { public function withFilterPHIDs(array $phids) {
$this->filterPHIDs = $phids; $this->filterPHIDs = $phids;
return $this; return $this;
} }
@ -16,50 +18,52 @@ final class PhabricatorFeedQuery
return $this; return $this;
} }
public function withEpochInRange($range_min, $range_max) {
$this->rangeMin = $range_min;
$this->rangeMax = $range_max;
return $this;
}
public function newResultObject() {
return new PhabricatorFeedStoryData();
}
protected function loadPage() { protected function loadPage() {
$story_table = new PhabricatorFeedStoryData(); // NOTE: We return raw rows from this method, which is a little unusual.
$conn = $story_table->establishConnection('r'); return $this->loadStandardPageRows($this->newResultObject());
$data = queryfx_all(
$conn,
'SELECT story.* FROM %T story %Q %Q %Q %Q %Q',
$story_table->getTableName(),
$this->buildJoinClause($conn),
$this->buildWhereClause($conn),
$this->buildGroupClause($conn),
$this->buildOrderClause($conn),
$this->buildLimitClause($conn));
return $data;
} }
protected function willFilterPage(array $data) { protected function willFilterPage(array $data) {
return PhabricatorFeedStory::loadAllFromRows($data, $this->getViewer()); return PhabricatorFeedStory::loadAllFromRows($data, $this->getViewer());
} }
protected function buildJoinClause(AphrontDatabaseConnection $conn_r) { protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
$joins = parent::buildJoinClauseParts($conn);
// NOTE: We perform this join unconditionally (even if we have no filter // NOTE: We perform this join unconditionally (even if we have no filter
// PHIDs) to omit rows which have no story references. These story data // PHIDs) to omit rows which have no story references. These story data
// rows are notifications or realtime alerts. // rows are notifications or realtime alerts.
$ref_table = new PhabricatorFeedStoryReference(); $ref_table = new PhabricatorFeedStoryReference();
return qsprintf( $joins[] = qsprintf(
$conn_r, $conn,
'JOIN %T ref ON ref.chronologicalKey = story.chronologicalKey', 'JOIN %T ref ON ref.chronologicalKey = story.chronologicalKey',
$ref_table->getTableName()); $ref_table->getTableName());
return $joins;
} }
protected function buildWhereClause(AphrontDatabaseConnection $conn_r) { protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = array(); $where = parent::buildWhereClauseParts($conn);
if ($this->filterPHIDs) { if ($this->filterPHIDs !== null) {
$where[] = qsprintf( $where[] = qsprintf(
$conn_r, $conn,
'ref.objectPHID IN (%Ls)', 'ref.objectPHID IN (%Ls)',
$this->filterPHIDs); $this->filterPHIDs);
} }
if ($this->chronologicalKeys) { if ($this->chronologicalKeys !== null) {
// NOTE: We want to use integers in the query so we can take advantage // NOTE: We want to use integers in the query so we can take advantage
// of keys, but can't use %d on 32-bit systems. Make sure all the keys // of keys, but can't use %d on 32-bit systems. Make sure all the keys
// are integers and then format them raw. // are integers and then format them raw.
@ -73,21 +77,37 @@ final class PhabricatorFeedQuery
} }
$where[] = qsprintf( $where[] = qsprintf(
$conn_r, $conn,
'ref.chronologicalKey IN (%Q)', 'ref.chronologicalKey IN (%Q)',
implode(', ', $keys)); implode(', ', $keys));
} }
$where[] = $this->buildPagingClause($conn_r); // NOTE: We may not have 64-bit PHP, so do the shifts in MySQL instead.
// From EXPLAIN, it appears like MySQL is smart enough to compute the
// result and make use of keys to execute the query.
return $this->formatWhereClause($where); if ($this->rangeMin !== null) {
$where[] = qsprintf(
$conn,
'ref.chronologicalKey >= (%d << 32)',
$this->rangeMin);
}
if ($this->rangeMax !== null) {
$where[] = qsprintf(
$conn,
'ref.chronologicalKey < (%d << 32)',
$this->rangeMax);
}
return $where;
} }
protected function buildGroupClause(AphrontDatabaseConnection $conn_r) { protected function buildGroupClause(AphrontDatabaseConnection $conn) {
if ($this->filterPHIDs) { if ($this->filterPHIDs !== null) {
return qsprintf($conn_r, 'GROUP BY ref.chronologicalKey'); return qsprintf($conn, 'GROUP BY ref.chronologicalKey');
} else { } else {
return qsprintf($conn_r, 'GROUP BY story.chronologicalKey'); return qsprintf($conn, 'GROUP BY story.chronologicalKey');
} }
} }
@ -95,6 +115,20 @@ final class PhabricatorFeedQuery
return array('key'); return array('key');
} }
public function getBuiltinOrders() {
return array(
'newest' => array(
'vector' => array('key'),
'name' => pht('Creation (Newest First)'),
'aliases' => array('created'),
),
'oldest' => array(
'vector' => array('-key'),
'name' => pht('Creation (Oldest First)'),
),
);
}
public function getOrderableColumns() { public function getOrderableColumns() {
$table = ($this->filterPHIDs ? 'ref' : 'story'); $table = ($this->filterPHIDs ? 'ref' : 'story');
return array( return array(
@ -120,6 +154,10 @@ final class PhabricatorFeedQuery
return $item['chronologicalKey']; return $item['chronologicalKey'];
} }
protected function getPrimaryTableAlias() {
return 'story';
}
public function getQueryApplicationClass() { public function getQueryApplicationClass() {
return 'PhabricatorFeedApplication'; return 'PhabricatorFeedApplication';
} }

View file

@ -11,87 +11,99 @@ final class PhabricatorFeedSearchEngine
return 'PhabricatorFeedApplication'; return 'PhabricatorFeedApplication';
} }
public function buildSavedQueryFromRequest(AphrontRequest $request) { public function newQuery() {
$saved = new PhabricatorSavedQuery(); return new PhabricatorFeedQuery();
$saved->setParameter(
'userPHIDs',
$this->readUsersFromRequest($request, 'users'));
$saved->setParameter(
'projectPHIDs',
array_values($request->getArr('projectPHIDs')));
$saved->setParameter(
'viewerProjects',
$request->getBool('viewerProjects'));
return $saved;
} }
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) { protected function shouldShowOrderField() {
$query = id(new PhabricatorFeedQuery()); return false;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorUsersSearchField())
->setLabel(pht('Include Users'))
->setKey('userPHIDs'),
// NOTE: This query is not executed with EdgeLogic, so we can't use
// a fancy logical datasource.
id(new PhabricatorSearchDatasourceField())
->setDatasource(new PhabricatorProjectDatasource())
->setLabel(pht('Include Projects'))
->setKey('projectPHIDs'),
id(new PhabricatorSearchDateControlField())
->setLabel(pht('Occurs After'))
->setKey('rangeStart'),
id(new PhabricatorSearchDateControlField())
->setLabel(pht('Occurs Before'))
->setKey('rangeEnd'),
// NOTE: This is a legacy field retained only for backward
// compatibility. If the projects field used EdgeLogic, we could use
// `viewerprojects()` to execute an equivalent query.
id(new PhabricatorSearchCheckboxesField())
->setKey('viewerProjects')
->setOptions(
array(
'self' => pht('Include stories about projects I am a member of.'),
)),
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
$phids = array(); $phids = array();
if ($map['userPHIDs']) {
$user_phids = $saved->getParameter('userPHIDs'); $phids += array_fuse($map['userPHIDs']);
if ($user_phids) {
$phids[] = $user_phids;
} }
$proj_phids = $saved->getParameter('projectPHIDs'); if ($map['projectPHIDs']) {
if ($proj_phids) { $phids += array_fuse($map['projectPHIDs']);
$phids[] = $proj_phids;
} }
$viewer_projects = $saved->getParameter('viewerProjects'); // NOTE: This value may be `true` for older saved queries, or
// `array('self')` for newer ones.
$viewer_projects = $map['viewerProjects'];
if ($viewer_projects) { if ($viewer_projects) {
$viewer = $this->requireViewer(); $viewer = $this->requireViewer();
$projects = id(new PhabricatorProjectQuery()) $projects = id(new PhabricatorProjectQuery())
->setViewer($viewer) ->setViewer($viewer)
->withMemberPHIDs(array($viewer->getPHID())) ->withMemberPHIDs(array($viewer->getPHID()))
->execute(); ->execute();
$phids[] = mpull($projects, 'getPHID'); $phids += array_fuse(mpull($projects, 'getPHID'));
} }
$phids = array_mergev($phids);
if ($phids) { if ($phids) {
$query->setFilterPHIDs($phids); $query->withFilterPHIDs($phids);
}
$range_min = $map['rangeStart'];
if ($range_min) {
$range_min = $range_min->getEpoch();
}
$range_max = $map['rangeEnd'];
if ($range_max) {
$range_max = $range_max->getEpoch();
}
if ($range_min && $range_max) {
if ($range_min > $range_max) {
throw new PhabricatorSearchConstraintException(
pht(
'The specified "Occurs Before" date is earlier in time than the '.
'specified "Occurs After" date, so this query can never match '.
'any results.'));
}
}
if ($range_min || $range_max) {
$query->withEpochInRange($range_min, $range_max);
} }
return $query; return $query;
} }
public function buildSearchForm(
AphrontFormView $form,
PhabricatorSavedQuery $saved_query) {
$user_phids = $saved_query->getParameter('userPHIDs', array());
$proj_phids = $saved_query->getParameter('projectPHIDs', array());
$viewer_projects = $saved_query->getParameter('viewerProjects');
$form
->appendControl(
id(new AphrontFormTokenizerControl())
->setDatasource(new PhabricatorPeopleDatasource())
->setName('users')
->setLabel(pht('Include Users'))
->setValue($user_phids))
->appendControl(
id(new AphrontFormTokenizerControl())
->setDatasource(new PhabricatorProjectDatasource())
->setName('projectPHIDs')
->setLabel(pht('Include Projects'))
->setValue($proj_phids))
->appendChild(
id(new AphrontFormCheckboxControl())
->addCheckbox(
'viewerProjects',
1,
pht('Include stories about projects I am a member of.'),
$viewer_projects));
}
protected function getURI($path) { protected function getURI($path) {
return '/feed/'.$path; return '/feed/'.$path;
} }
@ -117,7 +129,7 @@ final class PhabricatorFeedSearchEngine
case 'all': case 'all':
return $query; return $query;
case 'projects': case 'projects':
return $query->setParameter('viewerProjects', true); return $query->setParameter('viewerProjects', array('self'));
} }
return parent::buildSavedQueryFromBuiltin($query_key); return parent::buildSavedQueryFromBuiltin($query_key);

View file

@ -44,7 +44,7 @@ final class PhabricatorFileInfoController extends PhabricatorFileController {
if ($ttl !== null) { if ($ttl !== null) {
$ttl_tag = id(new PHUITagView()) $ttl_tag = id(new PHUITagView())
->setType(PHUITagView::TYPE_SHADE) ->setType(PHUITagView::TYPE_SHADE)
->setShade(PHUITagView::COLOR_YELLOW) ->setColor(PHUITagView::COLOR_YELLOW)
->setName(pht('Temporary')); ->setName(pht('Temporary'));
$header->addTag($ttl_tag); $header->addTag($ttl_tag);
} }
@ -53,7 +53,7 @@ final class PhabricatorFileInfoController extends PhabricatorFileController {
if ($partial) { if ($partial) {
$partial_tag = id(new PHUITagView()) $partial_tag = id(new PHUITagView())
->setType(PHUITagView::TYPE_SHADE) ->setType(PHUITagView::TYPE_SHADE)
->setShade(PHUITagView::COLOR_ORANGE) ->setColor(PHUITagView::COLOR_ORANGE)
->setName(pht('Partial Upload')); ->setName(pht('Partial Upload'));
$header->addTag($partial_tag); $header->addTag($partial_tag);
} }

View file

@ -30,8 +30,8 @@ final class PhabricatorGuideListView extends AphrontView {
->setText(pht('Skip')) ->setText(pht('Skip'))
->setTag('a') ->setTag('a')
->setHref($skip_href) ->setHref($skip_href)
->setColor(PHUIButtonView::GREY); ->setColor(PHUIButtonView::SIMPLE);
$list_item->setLaunchButton($skip); $list_item->setSideColumn($skip);
} }
$list->addItem($list_item); $list->addItem($list_item);
} }

View file

@ -56,7 +56,7 @@ final class HarbormasterUnitSummaryView extends AphrontView {
$tag = id(new PHUITagView()) $tag = id(new PHUITagView())
->setType(PHUITagView::TYPE_SHADE) ->setType(PHUITagView::TYPE_SHADE)
->setShade($tag_color) ->setColor($tag_color)
->setIcon($tag_icon) ->setIcon($tag_icon)
->setName($tag_text); ->setName($tag_text);

View file

@ -125,6 +125,34 @@ final class ManiphestTaskTestCase extends PhabricatorTestCase {
9, 9,
count($subpri), count($subpri),
pht('Expected subpriorities to be distributed.')); pht('Expected subpriorities to be distributed.'));
// Move task 9 to the end.
$this->moveTask($viewer, $t[9], $t[1], true);
$tasks = $this->loadTasks($viewer, $auto_base);
$this->assertEqual(
array(8, 7, 6, 5, 4, 3, 2, 1, 9),
array_keys($tasks));
// Move task 3 to the beginning.
$this->moveTask($viewer, $t[3], $t[8], false);
$tasks = $this->loadTasks($viewer, $auto_base);
$this->assertEqual(
array(3, 8, 7, 6, 5, 4, 2, 1, 9),
array_keys($tasks));
// Move task 3 to the end.
$this->moveTask($viewer, $t[3], $t[9], true);
$tasks = $this->loadTasks($viewer, $auto_base);
$this->assertEqual(
array(8, 7, 6, 5, 4, 2, 1, 9, 3),
array_keys($tasks));
// Move task 5 to before task 4 (this is its current position).
$this->moveTask($viewer, $t[5], $t[4], false);
$tasks = $this->loadTasks($viewer, $auto_base);
$this->assertEqual(
array(8, 7, 6, 5, 4, 2, 1, 9, 3),
array_keys($tasks));
} }
private function newTask(PhabricatorUser $viewer, $title) { private function newTask(PhabricatorUser $viewer, $title) {

View file

@ -0,0 +1,44 @@
<?php
final class ManiphestPrioritySearchConduitAPIMethod
extends ManiphestConduitAPIMethod {
public function getAPIMethodName() {
return 'maniphest.priority.search';
}
public function getMethodSummary() {
return pht('Read information about task priorities.');
}
public function getMethodDescription() {
return pht(
'Returns information about the possible priorities for Maniphest '.
'tasks.');
}
protected function defineParamTypes() {
return array();
}
protected function defineReturnType() {
return 'map<string, wild>';
}
public function getRequiredScope() {
return self::SCOPE_ALWAYS;
}
protected function execute(ConduitAPIRequest $request) {
$config = ManiphestTaskPriority::getConfig();
$results = array();
foreach ($config as $code => $priority) {
$priority['value'] = $code;
$results[] = $priority;
}
return array('data' => $results);
}
}

View file

@ -335,9 +335,16 @@ dictionary with these keys:
"task", "feature", or "bug". "task", "feature", or "bug".
- `name` //Required string.// Human-readable name for this subtype, like - `name` //Required string.// Human-readable name for this subtype, like
"Task", "Feature Request" or "Bug Report". "Task", "Feature Request" or "Bug Report".
- `tag` //Optional string.// Tag text for this subtype.
- `color` //Optional string.// Display color for this subtype.
- `icon` //Optional string.// Icon for the subtype.
Each subtype must have a unique key, and you must define a subtype with Each subtype must have a unique key, and you must define a subtype with
the key "%s", which is used as a default subtype. the key "%s", which is used as a default subtype.
The tag text (`tag`) is used to set the text shown in the subtype tag on list
views and workboards. If you do not configure it, the default subtype will have
no subtype tag and other subtypes will use their name as tag text.
EOTEXT EOTEXT
, ,
$subtype_default_key)); $subtype_default_key));

View file

@ -110,7 +110,7 @@ final class ManiphestTaskPriority extends ManiphestConstants {
return idx($config, 'disabled', false); return idx($config, 'disabled', false);
} }
private static function getConfig() { public static function getConfig() {
$config = PhabricatorEnv::getEnvConfig('maniphest.priorities'); $config = PhabricatorEnv::getEnvConfig('maniphest.priorities');
krsort($config); krsort($config);
return $config; return $config;

View file

@ -97,7 +97,7 @@ final class ManiphestTaskStatus extends ManiphestConstants {
->setName($name) ->setName($name)
->setIcon($icon) ->setIcon($icon)
->setType(PHUITagView::TYPE_SHADE) ->setType(PHUITagView::TYPE_SHADE)
->setShade($color); ->setColor($color);
return $tag; return $tag;
} }

View file

@ -233,13 +233,19 @@ final class ManiphestTaskDetailController extends ManiphestController {
ManiphestTaskPoints::getPointsLabel()); ManiphestTaskPoints::getPointsLabel());
$tag = id(new PHUITagView()) $tag = id(new PHUITagView())
->setName($points_name) ->setName($points_name)
->setShade('blue') ->setColor(PHUITagView::COLOR_BLUE)
->setType(PHUITagView::TYPE_SHADE); ->setType(PHUITagView::TYPE_SHADE);
$view->addTag($tag); $view->addTag($tag);
} }
} }
$subtype = $task->newSubtypeObject();
if ($subtype && $subtype->hasTagView()) {
$subtype_tag = $subtype->newTagView();
$view->addTag($subtype_tag);
}
return $view; return $view;
} }

View file

@ -384,8 +384,7 @@ final class ManiphestTransactionEditor
*/ */
public static function getAdjacentSubpriority( public static function getAdjacentSubpriority(
ManiphestTask $dst, ManiphestTask $dst,
$is_after, $is_after) {
$allow_recursion = true) {
$query = id(new ManiphestTaskQuery()) $query = id(new ManiphestTaskQuery())
->setViewer(PhabricatorUser::getOmnipotentUser()) ->setViewer(PhabricatorUser::getOmnipotentUser())
@ -407,76 +406,25 @@ final class ManiphestTransactionEditor
// If we find an adjacent task, we average the two subpriorities and // If we find an adjacent task, we average the two subpriorities and
// return the result. // return the result.
if ($adjacent) { if ($adjacent) {
$epsilon = 0.01; $epsilon = 1.0;
// If the adjacent task has a subpriority that is identical or very // If the adjacent task has a subpriority that is identical or very
// close to the task we're looking at, we're going to move it and all // close to the task we're looking at, we're going to spread out all
// tasks with the same subpriority a little farther down the subpriority // the nearby tasks.
// scale.
if ($allow_recursion &&
(abs($adjacent->getSubpriority() - $base) < $epsilon)) {
$conn_w = $adjacent->establishConnection('w');
$min = ($adjacent->getSubpriority() - ($epsilon)); $adjacent_sub = $adjacent->getSubpriority();
$max = ($adjacent->getSubpriority() + ($epsilon)); if ((abs($adjacent_sub - $base) < $epsilon)) {
$base = self::disperseBlock(
// Get all of the tasks with the similar subpriorities to the adjacent $dst,
// task, including the adjacent task itself. $epsilon * 2);
$query = id(new ManiphestTaskQuery()) if ($is_after) {
->setViewer(PhabricatorUser::getOmnipotentUser()) $sub = $base - $epsilon;
->withPriorities(array($adjacent->getPriority()))
->withSubpriorityBetween($min, $max);
if (!$is_after) {
$query->setOrderVector(array('-priority', '-subpriority', '-id'));
} else { } else {
$query->setOrderVector(array('priority', 'subpriority', 'id')); $sub = $base + $epsilon;
}
$shift_all = $query->execute();
$shift_last = last($shift_all);
// Select the most extreme subpriority in the result set as the
// base value.
$shift_base = head($shift_all)->getSubpriority();
// Find the subpriority before or after the task at the end of the
// block.
list($shift_pri, $shift_sub) = self::getAdjacentSubpriority(
$shift_last,
$is_after,
$allow_recursion = false);
$delta = ($shift_sub - $shift_base);
$count = count($shift_all);
$shift = array();
$cursor = 1;
foreach ($shift_all as $shift_task) {
$shift_target = $shift_base + (($cursor / $count) * $delta);
$cursor++;
queryfx(
$conn_w,
'UPDATE %T SET subpriority = %f WHERE id = %d',
$adjacent->getTableName(),
$shift_target,
$shift_task->getID());
// If we're shifting the adjacent task, update it.
if ($shift_task->getID() == $adjacent->getID()) {
$adjacent->setSubpriority($shift_target);
}
// If we're shifting the original target task, update the base
// subpriority.
if ($shift_task->getID() == $dst->getID()) {
$base = $shift_target;
}
} }
} else {
$sub = ($adjacent_sub + $base) / 2;
} }
$sub = ($adjacent->getSubpriority() + $base) / 2;
} else { } else {
// Otherwise, we take a step away from the target's subpriority and // Otherwise, we take a step away from the target's subpriority and
// use that. // use that.
@ -490,6 +438,156 @@ final class ManiphestTransactionEditor
return array($dst->getPriority(), $sub); return array($dst->getPriority(), $sub);
} }
/**
* Distribute a cluster of tasks with similar subpriorities.
*/
private static function disperseBlock(
ManiphestTask $task,
$spacing) {
$conn = $task->establishConnection('w');
// Find a block of subpriority space which is, on average, sparse enough
// to hold all the tasks that are inside it with a reasonable level of
// separation between them.
// We'll start by looking near the target task for a range of numbers
// which has more space available than tasks. For example, if the target
// task has subpriority 33 and we want to separate each task by at least 1,
// we might start by looking in the range [23, 43].
// If we find fewer than 20 tasks there, we have room to reassign them
// with the desired level of separation. We space them out, then we're
// done.
// However: if we find more than 20 tasks, we don't have enough room to
// distribute them. We'll widen our search and look in a bigger range,
// maybe [13, 53]. This range has more space, so if we find fewer than
// 40 tasks in this range we can spread them out. If we still find too
// many tasks, we keep widening the search.
$base = $task->getSubpriority();
$scale = 4.0;
while (true) {
$range = ($spacing * $scale) / 2.0;
$min = ($base - $range);
$max = ($base + $range);
$result = queryfx_one(
$conn,
'SELECT COUNT(*) N FROM %T WHERE priority = %d AND
subpriority BETWEEN %f AND %f',
$task->getTableName(),
$task->getPriority(),
$min,
$max);
$count = $result['N'];
if ($count < $scale) {
// We have found a block which we can make sparse enough, so bail and
// continue below with our selection.
break;
}
// This block had too many tasks for its size, so try again with a
// bigger block.
$scale *= 2.0;
}
$rows = queryfx_all(
$conn,
'SELECT id FROM %T WHERE priority = %d AND
subpriority BETWEEN %f AND %f
ORDER BY priority, subpriority, id',
$task->getTableName(),
$task->getPriority(),
$min,
$max);
$task_id = $task->getID();
$result = null;
// NOTE: In strict mode (which we encourage enabling) we can't structure
// this bulk update as an "INSERT ... ON DUPLICATE KEY UPDATE" unless we
// provide default values for ALL of the columns that don't have defaults.
// This is gross, but we may be moving enough rows that individual
// queries are unreasonably slow. An alternate construction which might
// be worth evaluating is to use "CASE". Another approach is to disable
// strict mode for this query.
$extra_columns = array(
'phid' => '""',
'authorPHID' => '""',
'status' => '""',
'priority' => 0,
'title' => '""',
'originalTitle' => '""',
'description' => '""',
'dateCreated' => 0,
'dateModified' => 0,
'mailKey' => '""',
'viewPolicy' => '""',
'editPolicy' => '""',
'ownerOrdering' => '""',
'spacePHID' => '""',
'bridgedObjectPHID' => '""',
'properties' => '""',
'points' => 0,
'subtype' => '""',
);
$defaults = implode(', ', $extra_columns);
$sql = array();
$offset = 0;
// Often, we'll have more room than we need in the range. Distribute the
// tasks evenly over the whole range so that we're less likely to end up
// with tasks spaced exactly the minimum distance apart, which may
// get shifted again later. We have one fewer space to distribute than we
// have tasks.
$divisor = (double)(count($rows) - 1.0);
if ($divisor > 0) {
$available_distance = (($max - $min) / $divisor);
} else {
$available_distance = 0.0;
}
foreach ($rows as $row) {
$subpriority = $min + ($offset * $available_distance);
// If this is the task that we're spreading out relative to, keep track
// of where it is ending up so we can return the new subpriority.
$id = $row['id'];
if ($id == $task_id) {
$result = $subpriority;
}
$sql[] = qsprintf(
$conn,
'(%d, %Q, %f)',
$id,
$defaults,
$subpriority);
$offset++;
}
foreach (PhabricatorLiskDAO::chunkSQL($sql) as $chunk) {
queryfx(
$conn,
'INSERT INTO %T (id, %Q, subpriority) VALUES %Q
ON DUPLICATE KEY UPDATE subpriority = VALUES(subpriority)',
$task->getTableName(),
implode(', ', array_keys($extra_columns)),
$chunk);
}
return $result;
}
protected function validateAllTransactions( protected function validateAllTransactions(
PhabricatorLiskDAO $object, PhabricatorLiskDAO $object,
array $xactions) { array $xactions) {

View file

@ -17,8 +17,6 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
private $dateCreatedBefore; private $dateCreatedBefore;
private $dateModifiedAfter; private $dateModifiedAfter;
private $dateModifiedBefore; private $dateModifiedBefore;
private $subpriorityMin;
private $subpriorityMax;
private $bridgedObjectPHIDs; private $bridgedObjectPHIDs;
private $hasOpenParents; private $hasOpenParents;
private $hasOpenSubtasks; private $hasOpenSubtasks;
@ -112,12 +110,6 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
return $this; return $this;
} }
public function withSubpriorityBetween($min, $max) {
$this->subpriorityMin = $min;
$this->subpriorityMax = $max;
return $this;
}
public function withSubscribers(array $subscribers) { public function withSubscribers(array $subscribers) {
$this->subscriberPHIDs = $subscribers; $this->subscriberPHIDs = $subscribers;
return $this; return $this;
@ -408,20 +400,6 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
$this->subpriorities); $this->subpriorities);
} }
if ($this->subpriorityMin !== null) {
$where[] = qsprintf(
$conn,
'task.subpriority >= %f',
$this->subpriorityMin);
}
if ($this->subpriorityMax !== null) {
$where[] = qsprintf(
$conn,
'task.subpriority <= %f',
$this->subpriorityMax);
}
if ($this->bridgedObjectPHIDs !== null) { if ($this->bridgedObjectPHIDs !== null) {
$where[] = qsprintf( $where[] = qsprintf(
$conn, $conn,

View file

@ -540,6 +540,11 @@ final class ManiphestTask extends ManiphestDAO
); );
} }
public function newSubtypeObject() {
$subtype_key = $this->getEditEngineSubtype();
$subtype_map = $this->newEditEngineSubtypeMap();
return idx($subtype_map, $subtype_key);
}
/* -( PhabricatorFulltextInterface )--------------------------------------- */ /* -( PhabricatorFulltextInterface )--------------------------------------- */

View file

@ -211,4 +211,14 @@ final class ManiphestTransaction
return parent::getNoEffectDescription(); return parent::getNoEffectDescription();
} }
public function renderSubtypeName($value) {
$object = $this->getObject();
$map = $object->newEditEngineSubtypeMap();
if (!isset($map[$value])) {
return $value;
}
return $map[$value]->getName();
}
} }

View file

@ -32,6 +32,7 @@ final class ManiphestTaskSubtypeDatasource
$result = id(new PhabricatorTypeaheadResult()) $result = id(new PhabricatorTypeaheadResult())
->setIcon($subtype->getIcon()) ->setIcon($subtype->getIcon())
->setColor($subtype->getColor())
->setPHID($key) ->setPHID($key)
->setName($subtype->getName()); ->setName($subtype->getName());

View file

@ -56,6 +56,9 @@ final class ManiphestTaskListView extends ManiphestView {
Javelin::initBehavior('maniphest-list-editor'); Javelin::initBehavior('maniphest-list-editor');
} }
$subtype_map = id(new ManiphestTask())
->newEditEngineSubtypeMap();
foreach ($this->tasks as $task) { foreach ($this->tasks as $task) {
$item = id(new PHUIObjectItemView()) $item = id(new PHUIObjectItemView())
->setUser($this->getUser()) ->setUser($this->getUser())
@ -94,6 +97,13 @@ final class ManiphestTaskListView extends ManiphestView {
$item->addSigil('maniphest-task'); $item->addSigil('maniphest-task');
} }
$subtype = $task->newSubtypeObject();
if ($subtype && $subtype->hasTagView()) {
$subtype_tag = $subtype->newTagView()
->setSlimShady(true);
$item->addAttribute($subtype_tag);
}
$project_handles = array_select_keys( $project_handles = array_select_keys(
$handles, $handles,
array_reverse($task->getProjectPHIDs())); array_reverse($task->getProjectPHIDs()));

View file

@ -50,6 +50,32 @@ final class ManiphestTaskPointsTransaction
} }
} }
public function getTitleForFeed() {
$old = $this->getOldValue();
$new = $this->getNewValue();
if ($old === null) {
return pht(
'%s set the point value for %s to %s.',
$this->renderAuthor(),
$this->renderObject(),
$this->renderNewValue());
} else if ($new === null) {
return pht(
'%s removed the point value for %s.',
$this->renderAuthor(),
$this->renderObject());
} else {
return pht(
'%s changed the point value for %s from %s to %s.',
$this->renderAuthor(),
$this->renderObject(),
$this->renderOldValue(),
$this->renderNewValue());
}
}
public function validateTransactions($object, array $xactions) { public function validateTransactions($object, array $xactions) {
$errors = array(); $errors = array();

View file

@ -19,8 +19,8 @@ final class ManiphestTaskTitleTransaction
public function getActionName() { public function getActionName() {
$old = $this->getOldValue(); $old = $this->getOldValue();
$new = $this->getNewValue();
if ($old === null) { if (!strlen($old)) {
return pht('Created'); return pht('Created');
} }
@ -29,7 +29,8 @@ final class ManiphestTaskTitleTransaction
public function getTitle() { public function getTitle() {
$old = $this->getOldValue(); $old = $this->getOldValue();
if ($old === null) {
if (!strlen($old)) {
return pht( return pht(
'%s created this task.', '%s created this task.',
$this->renderAuthor()); $this->renderAuthor());

View file

@ -3,14 +3,4 @@
abstract class ManiphestTaskTransactionType abstract class ManiphestTaskTransactionType
extends PhabricatorModularTransactionType { extends PhabricatorModularTransactionType {
public function renderSubtypeName($value) {
$object = $this->getObject();
$map = $object->newEditEngineSubtypeMap();
if (!isset($map[$value])) {
return $value;
}
return $map[$value]->getName();
}
} }

View file

@ -218,20 +218,39 @@ final class PhabricatorAppSearchEngine
$configure = id(new PHUIButtonView()) $configure = id(new PHUIButtonView())
->setTag('a') ->setTag('a')
->setIcon('fa-gears')
->setHref('/applications/view/'.get_class($application).'/') ->setHref('/applications/view/'.get_class($application).'/')
->setText(pht('Configure')) ->setText(pht('Configure'))
->setColor(PHUIButtonView::GREY); ->setColor(PHUIButtonView::GREY);
$name = $application->getName(); $name = $application->getName();
if ($application->isPrototype()) {
$name = $name.' '.pht('(Prototype)');
}
$item = id(new PHUIObjectItemView()) $item = id(new PHUIObjectItemView())
->setHeader($name) ->setHeader($name)
->setImageIcon($icon) ->setImageIcon($icon)
->setSubhead($description) ->setSideColumn($configure);
->setLaunchButton($configure);
if (!$application->isFirstParty()) {
$tag = id(new PHUITagView())
->setName(pht('Extension'))
->setIcon('fa-puzzle-piece')
->setColor(PHUITagView::COLOR_BLUE)
->setType(PHUITagView::TYPE_SHADE)
->setSlimShady(true);
$item->addAttribute($tag);
}
if ($application->isPrototype()) {
$prototype_tag = id(new PHUITagView())
->setName(pht('Prototype'))
->setIcon('fa-exclamation-circle')
->setColor(PHUITagView::COLOR_ORANGE)
->setType(PHUITagView::TYPE_SHADE)
->setSlimShady(true);
$item->addAttribute($prototype_tag);
}
$item->addAttribute($description);
if ($application->getBaseURI() && $application->isInstalled()) { if ($application->getBaseURI() && $application->isInstalled()) {
$item->setHref($application->getBaseURI()); $item->setHref($application->getBaseURI());
@ -242,10 +261,6 @@ final class PhabricatorAppSearchEngine
$item->setDisabled(true); $item->setDisabled(true);
} }
if (!$application->isFirstParty()) {
$item->addAttribute(pht('Extension'));
}
$list->addItem($item); $list->addItem($item);
} }

View file

@ -51,6 +51,9 @@ final class PhabricatorNuanceApplication extends PhabricatorApplication {
$this->getQueryRoutePattern() => 'NuanceQueueListController', $this->getQueryRoutePattern() => 'NuanceQueueListController',
$this->getEditRoutePattern('edit/') => 'NuanceQueueEditController', $this->getEditRoutePattern('edit/') => 'NuanceQueueEditController',
'view/(?P<id>[1-9]\d*)/' => 'NuanceQueueViewController', 'view/(?P<id>[1-9]\d*)/' => 'NuanceQueueViewController',
'work/(?P<id>[1-9]\d*)/' => 'NuanceQueueWorkController',
'action/(?P<queueID>[1-9]\d*)/(?P<action>[^/]+)/(?P<id>[1-9]\d*)/'
=> 'NuanceItemActionController',
), ),
), ),
'/action/' => array( '/action/' => array(

View file

@ -0,0 +1,113 @@
<?php
abstract class NuanceCommandImplementation
extends Phobject {
private $actor;
private $transactionQueue = array();
final public function setActor(PhabricatorUser $actor) {
$this->actor = $actor;
return $this;
}
final public function getActor() {
return $this->actor;
}
abstract public function getCommandName();
abstract public function canApplyToItem(NuanceItem $item);
public function canApplyImmediately(
NuanceItem $item,
NuanceItemCommand $command) {
return false;
}
abstract protected function executeCommand(
NuanceItem $item,
NuanceItemCommand $command);
final public function applyCommand(
NuanceItem $item,
NuanceItemCommand $command) {
$command_key = $command->getCommand();
$implementation_key = $this->getCommandKey();
if ($command_key !== $implementation_key) {
throw new Exception(
pht(
'This command implementation("%s") can not apply a command of a '.
'different type ("%s").',
$implementation_key,
$command_key));
}
if (!$this->canApplyToItem($item)) {
throw new Exception(
pht(
'This command implementation ("%s") can not be applied to an '.
'item of type "%s".',
$implementation_key,
$item->getItemType()));
}
$this->transactionQueue = array();
$command_type = NuanceItemCommandTransaction::TRANSACTIONTYPE;
$command_xaction = $this->newTransaction($command_type);
$result = $this->executeCommand($item, $command);
$xactions = $this->transactionQueue;
$this->transactionQueue = array();
$command_xaction->setNewValue(
array(
'command' => $command->getCommand(),
'parameters' => $command->getParameters(),
'result' => $result,
));
// TODO: Maybe preserve the actor's original content source?
$source = PhabricatorContentSource::newForSource(
PhabricatorDaemonContentSource::SOURCECONST);
$actor = $this->getActor();
id(new NuanceItemEditor())
->setActor($actor)
->setActingAsPHID($command->getAuthorPHID())
->setContentSource($source)
->setContinueOnMissingFields(true)
->setContinueOnNoEffect(true)
->applyTransactions($item, $xactions);
}
final public function getCommandKey() {
return $this->getPhobjectClassConstant('COMMANDKEY');
}
final public static function getAllCommands() {
return id(new PhutilClassMapQuery())
->setAncestorClass(__CLASS__)
->setUniqueMethod('getCommandKey')
->execute();
}
protected function newTransaction($type) {
$xaction = id(new NuanceItemTransaction())
->setTransactionType($type);
$this->transactionQueue[] = $xaction;
return $xaction;
}
protected function newStatusTransaction($status) {
return $this->newTransaction(NuanceItemStatusTransaction::TRANSACTIONTYPE)
->setNewValue($status);
}
}

View file

@ -0,0 +1,37 @@
<?php
final class NuanceItemCommandSpec
extends Phobject {
private $commandKey;
private $name;
private $icon;
public function setCommandKey($command_key) {
$this->commandKey = $command_key;
return $this;
}
public function getCommandKey() {
return $this->commandKey;
}
public function setName($name) {
$this->name = $name;
return $this;
}
public function getName() {
return $this->name;
}
public function setIcon($icon) {
$this->icon = $icon;
return $this;
}
public function getIcon() {
return $this->icon;
}
}

View file

@ -0,0 +1,29 @@
<?php
final class NuanceTrashCommand
extends NuanceCommandImplementation {
const COMMANDKEY = 'trash';
public function getCommandName() {
return pht('Throw in Trash');
}
public function canApplyToItem(NuanceItem $item) {
$type = $item->getImplementation();
return ($type instanceof NuanceFormItemType);
}
public function canApplyImmediately(
NuanceItem $item,
NuanceItemCommand $command) {
return true;
}
protected function executeCommand(
NuanceItem $item,
NuanceItemCommand $command) {
$this->newStatusTransaction(NuanceItem::STATUS_CLOSED);
}
}

View file

@ -6,6 +6,14 @@ final class NuanceItemActionController extends NuanceController {
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$id = $request->getURIData('id'); $id = $request->getURIData('id');
if (!$request->validateCSRF()) {
return new Aphront400Response();
}
// NOTE: This controller can be reached from an individual item (usually
// by a user) or while working through a queue (usually by staff). When
// a command originates from a queue, the URI will have a queue ID.
$item = id(new NuanceItemQuery()) $item = id(new NuanceItemQuery())
->setViewer($viewer) ->setViewer($viewer)
->withIDs(array($id)) ->withIDs(array($id))
@ -14,13 +22,100 @@ final class NuanceItemActionController extends NuanceController {
return new Aphront404Response(); return new Aphront404Response();
} }
$cancel_uri = $item->getURI();
$queue_id = $request->getURIData('queueID');
$queue = null;
if ($queue_id) {
$queue = id(new NuanceQueueQuery())
->setViewer($viewer)
->withIDs(array($queue_id))
->executeOne();
if (!$queue) {
return new Aphront404Response();
}
$item_queue = $item->getQueue();
if (!$item_queue || ($item_queue->getPHID() != $queue->getPHID())) {
return $this->newDialog()
->setTitle(pht('Wrong Queue'))
->appendParagraph(
pht(
'You are trying to act on this item from the wrong queue: it '.
'is currently in a different queue.'))
->addCancelButton($cancel_uri);
}
}
$action = $request->getURIData('action'); $action = $request->getURIData('action');
$impl = $item->getImplementation(); $impl = $item->getImplementation();
$impl->setViewer($viewer); $impl->setViewer($viewer);
$impl->setController($this); $impl->setController($this);
return $impl->buildActionResponse($item, $action); $executors = NuanceCommandImplementation::getAllCommands();
$executor = idx($executors, $action);
if (!$executor) {
return new Aphront404Response();
}
$executor = id(clone $executor)
->setActor($viewer);
if (!$executor->canApplyToItem($item)) {
return $this->newDialog()
->setTitle(pht('Command Not Supported'))
->appendParagraph(
pht(
'This item does not support the specified command ("%s").',
$action))
->addCancelButton($cancel_uri);
}
$command = NuanceItemCommand::initializeNewCommand()
->setItemPHID($item->getPHID())
->setAuthorPHID($viewer->getPHID())
->setCommand($action);
if ($queue) {
$command->setQueuePHID($queue->getPHID());
}
$command->save();
// If this command can be applied immediately, try to apply it now.
// In most cases, local commands (like closing an item) can be applied
// immediately.
// Commands that require making a call to a remote system (for example,
// to reply to a tweet or close a remote object) are usually done in the
// background so the user doesn't have to wait for the operation to
// complete before they can continue work.
$did_apply = false;
$immediate = $executor->canApplyImmediately($item, $command);
if ($immediate) {
// TODO: Move this stuff to a new Engine, and have the controller and
// worker both call into the Engine.
$worker = new NuanceItemUpdateWorker(array());
$did_apply = $worker->executeCommands($item, array($command));
}
// If this can't be applied immediately or we were unable to get a lock
// fast enough, do the update in the background instead.
if (!$did_apply) {
$item->scheduleUpdate();
}
if ($queue) {
$done_uri = $queue->getWorkURI();
} else {
$done_uri = $item->getURI();
}
return id(new AphrontRedirectResponse())
->setURI($done_uri);
} }
} }

View file

@ -26,14 +26,12 @@ final class NuanceItemViewController extends NuanceController {
$curtain = $this->buildCurtain($item); $curtain = $this->buildCurtain($item);
$content = $this->buildContent($item); $content = $this->buildContent($item);
$commands = $this->buildCommands($item);
$timeline = $this->buildTransactionTimeline( $timeline = $this->buildTransactionTimeline(
$item, $item,
new NuanceItemTransactionQuery()); new NuanceItemTransactionQuery());
$main = array( $main = array(
$commands,
$content, $content,
$timeline, $timeline,
); );
@ -91,36 +89,4 @@ final class NuanceItemViewController extends NuanceController {
return $impl->buildItemView($item); return $impl->buildItemView($item);
} }
private function buildCommands(NuanceItem $item) {
$viewer = $this->getViewer();
$commands = id(new NuanceItemCommandQuery())
->setViewer($viewer)
->withItemPHIDs(array($item->getPHID()))
->execute();
$commands = msort($commands, 'getID');
if (!$commands) {
return null;
}
$rows = array();
foreach ($commands as $command) {
$rows[] = array(
$command->getCommand(),
);
}
$table = id(new AphrontTableView($rows))
->setHeaders(
array(
pht('Command'),
));
return id(new PHUIObjectBoxView())
->setHeaderText(pht('Pending Commands'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($table);
}
} }

View file

@ -70,6 +70,14 @@ final class NuanceQueueViewController
->setDisabled(!$can_edit) ->setDisabled(!$can_edit)
->setWorkflow(!$can_edit)); ->setWorkflow(!$can_edit));
$curtain->addAction(
id(new PhabricatorActionView())
->setName(pht('Begin Work'))
->setIcon('fa-play-circle-o')
->setHref($this->getApplicationURI("queue/work/{$id}/"))
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit));
return $curtain; return $curtain;
} }

View file

@ -0,0 +1,186 @@
<?php
final class NuanceQueueWorkController
extends NuanceQueueController {
public function handleRequest(AphrontRequest $request) {
$viewer = $this->getViewer();
$queue = id(new NuanceQueueQuery())
->setViewer($viewer)
->withIDs(array($request->getURIData('id')))
->executeOne();
if (!$queue) {
return new Aphront404Response();
}
$title = $queue->getName();
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(pht('Queues'), $this->getApplicationURI('queue/'));
$crumbs->addTextCrumb($queue->getName(), $queue->getURI());
$crumbs->addTextCrumb(pht('Work'));
$crumbs->setBorder(true);
// For now, just pick the first open item.
$items = id(new NuanceItemQuery())
->setViewer($viewer)
->withQueuePHIDs(
array(
$queue->getPHID(),
))
->withStatuses(
array(
NuanceItem::STATUS_OPEN,
))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->setLimit(5)
->execute();
if (!$items) {
return $this->newDialog()
->setTitle(pht('Queue Empty'))
->appendParagraph(
pht(
'This queue has no open items which you have permission to '.
'work on.'))
->addCancelButton($queue->getURI());
}
$item = head($items);
$curtain = $this->buildCurtain($queue, $item);
$timeline = $this->buildTransactionTimeline(
$item,
new NuanceItemTransactionQuery());
$timeline->setShouldTerminate(true);
$impl = $item->getImplementation()
->setViewer($viewer);
$commands = $this->buildCommands($item);
$work_content = $impl->buildItemWorkView($item);
$view = id(new PHUITwoColumnView())
->setCurtain($curtain)
->setMainColumn(
array(
$commands,
$work_content,
$timeline,
));
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->appendChild($view);
}
private function buildCurtain(NuanceQueue $queue, NuanceItem $item) {
$viewer = $this->getViewer();
$id = $queue->getID();
$curtain = $this->newCurtainView();
$impl = $item->getImplementation();
$commands = $impl->buildWorkCommands($item);
foreach ($commands as $command) {
$command_key = $command->getCommandKey();
$item_id = $item->getID();
$action_uri = "queue/action/{$id}/{$command_key}/{$item_id}/";
$action_uri = $this->getApplicationURI($action_uri);
$curtain->addAction(
id(new PhabricatorActionView())
->setName($command->getName())
->setIcon($command->getIcon())
->setHref($action_uri)
->setWorkflow(true));
}
$curtain->addAction(
id(new PhabricatorActionView())
->setType(PhabricatorActionView::TYPE_DIVIDER));
$curtain->addAction(
id(new PhabricatorActionView())
->setType(PhabricatorActionView::TYPE_LABEL)
->setName(pht('Queue Actions')));
$curtain->addAction(
id(new PhabricatorActionView())
->setName(pht('Manage Queue'))
->setIcon('fa-cog')
->setHref($this->getApplicationURI("queue/view/{$id}/")));
return $curtain;
}
private function buildCommands(NuanceItem $item) {
$viewer = $this->getViewer();
$commands = id(new NuanceItemCommandQuery())
->setViewer($viewer)
->withItemPHIDs(array($item->getPHID()))
->withStatuses(
array(
NuanceItemCommand::STATUS_ISSUED,
NuanceItemCommand::STATUS_EXECUTING,
NuanceItemCommand::STATUS_FAILED,
))
->execute();
$commands = msort($commands, 'getID');
if (!$commands) {
return null;
}
$rows = array();
foreach ($commands as $command) {
$icon = $command->getStatusIcon();
$color = $command->getStatusColor();
$rows[] = array(
$command->getID(),
id(new PHUIIconView())
->setIcon($icon, $color),
$viewer->renderHandle($command->getAuthorPHID()),
$command->getCommand(),
phabricator_datetime($command->getDateCreated(), $viewer),
);
}
$table = id(new AphrontTableView($rows))
->setHeaders(
array(
pht('ID'),
null,
pht('Actor'),
pht('Command'),
pht('Date'),
))
->setColumnClasses(
array(
null,
'icon',
null,
'pri',
'wide right',
));
return id(new PHUIObjectBoxView())
->setHeaderText(pht('Pending Commands'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($table);
}
}

View file

@ -17,10 +17,9 @@ final class NuanceGitHubIssuesImportCursor
$container_key = null; $container_key = null;
return NuanceItem::initializeNewItem() return NuanceItem::initializeNewItem(NuanceGitHubEventItemType::ITEMTYPE)
->setStatus(NuanceItem::STATUS_IMPORTING) ->setStatus(NuanceItem::STATUS_IMPORTING)
->setSourcePHID($source->getPHID()) ->setSourcePHID($source->getPHID())
->setItemType(NuanceGitHubEventItemType::ITEMTYPE)
->setItemKey($item_key) ->setItemKey($item_key)
->setItemContainerKey($container_key) ->setItemContainerKey($container_key)
->setItemProperty('api.type', 'issue') ->setItemProperty('api.type', 'issue')

View file

@ -36,10 +36,9 @@ final class NuanceGitHubRepositoryImportCursor
$container_key = "github.issue.{$issue_id}"; $container_key = "github.issue.{$issue_id}";
} }
return NuanceItem::initializeNewItem() return NuanceItem::initializeNewItem(NuanceGitHubEventItemType::ITEMTYPE)
->setStatus(NuanceItem::STATUS_IMPORTING) ->setStatus(NuanceItem::STATUS_IMPORTING)
->setSourcePHID($source->getPHID()) ->setSourcePHID($source->getPHID())
->setItemType(NuanceGitHubEventItemType::ITEMTYPE)
->setItemKey($item_key) ->setItemKey($item_key)
->setItemContainerKey($container_key) ->setItemContainerKey($container_key)
->setItemProperty('api.type', 'repository') ->setItemProperty('api.type', 'repository')

View file

@ -14,104 +14,10 @@ final class NuanceItemEditor
public function getTransactionTypes() { public function getTransactionTypes() {
$types = parent::getTransactionTypes(); $types = parent::getTransactionTypes();
$types[] = NuanceItemTransaction::TYPE_OWNER;
$types[] = NuanceItemTransaction::TYPE_SOURCE;
$types[] = NuanceItemTransaction::TYPE_REQUESTOR;
$types[] = NuanceItemTransaction::TYPE_PROPERTY;
$types[] = NuanceItemTransaction::TYPE_QUEUE;
$types[] = NuanceItemTransaction::TYPE_COMMAND;
$types[] = PhabricatorTransactions::TYPE_EDGE;
$types[] = PhabricatorTransactions::TYPE_COMMENT;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types; return $types;
} }
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case NuanceItemTransaction::TYPE_REQUESTOR:
return $object->getRequestorPHID();
case NuanceItemTransaction::TYPE_SOURCE:
return $object->getSourcePHID();
case NuanceItemTransaction::TYPE_OWNER:
return $object->getOwnerPHID();
case NuanceItemTransaction::TYPE_QUEUE:
return $object->getQueuePHID();
case NuanceItemTransaction::TYPE_PROPERTY:
$key = $xaction->getMetadataValue(
NuanceItemTransaction::PROPERTY_KEY);
return $object->getNuanceProperty($key);
case NuanceItemTransaction::TYPE_COMMAND:
return null;
}
return parent::getCustomTransactionOldValue($object, $xaction);
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case NuanceItemTransaction::TYPE_REQUESTOR:
case NuanceItemTransaction::TYPE_SOURCE:
case NuanceItemTransaction::TYPE_OWNER:
case NuanceItemTransaction::TYPE_PROPERTY:
case NuanceItemTransaction::TYPE_QUEUE:
case NuanceItemTransaction::TYPE_COMMAND:
return $xaction->getNewValue();
}
return parent::getCustomTransactionNewValue($object, $xaction);
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case NuanceItemTransaction::TYPE_REQUESTOR:
$object->setRequestorPHID($xaction->getNewValue());
break;
case NuanceItemTransaction::TYPE_SOURCE:
$object->setSourcePHID($xaction->getNewValue());
break;
case NuanceItemTransaction::TYPE_OWNER:
$object->setOwnerPHID($xaction->getNewValue());
break;
case NuanceItemTransaction::TYPE_QUEUE:
$object->setQueuePHID($xaction->getNewValue());
break;
case NuanceItemTransaction::TYPE_PROPERTY:
$key = $xaction->getMetadataValue(
NuanceItemTransaction::PROPERTY_KEY);
$object->setNuanceProperty($key, $xaction->getNewValue());
break;
case NuanceItemTransaction::TYPE_COMMAND:
break;
}
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case NuanceItemTransaction::TYPE_REQUESTOR:
case NuanceItemTransaction::TYPE_SOURCE:
case NuanceItemTransaction::TYPE_OWNER:
case NuanceItemTransaction::TYPE_PROPERTY:
case NuanceItemTransaction::TYPE_QUEUE:
case NuanceItemTransaction::TYPE_COMMAND:
return;
}
return parent::applyCustomExternalTransaction($object, $xaction);
}
} }

View file

@ -75,7 +75,7 @@ final class NuanceQueueEditEngine
->setKey('name') ->setKey('name')
->setLabel(pht('Name')) ->setLabel(pht('Name'))
->setDescription(pht('Name of the queue.')) ->setDescription(pht('Name of the queue.'))
->setTransactionType(NuanceQueueTransaction::TYPE_NAME) ->setTransactionType(NuanceQueueNameTransaction::TRANSACTIONTYPE)
->setIsRequired(true) ->setIsRequired(true)
->setValue($object->getName()), ->setValue($object->getName()),
); );

View file

@ -14,89 +14,10 @@ final class NuanceQueueEditor
public function getTransactionTypes() { public function getTransactionTypes() {
$types = parent::getTransactionTypes(); $types = parent::getTransactionTypes();
$types[] = NuanceQueueTransaction::TYPE_NAME;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types; return $types;
} }
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case NuanceQueueTransaction::TYPE_NAME:
return $object->getName();
}
return parent::getCustomTransactionOldValue($object, $xaction);
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case NuanceQueueTransaction::TYPE_NAME:
return $xaction->getNewValue();
}
return parent::getCustomTransactionNewValue($object, $xaction);
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case NuanceQueueTransaction::TYPE_NAME:
$object->setName($xaction->getNewValue());
break;
}
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case NuanceQueueTransaction::TYPE_NAME:
return;
}
return parent::applyCustomExternalTransaction($object, $xaction);
}
protected function validateTransaction(
PhabricatorLiskDAO $object,
$type,
array $xactions) {
$errors = parent::validateTransaction($object, $type, $xactions);
switch ($type) {
case NuanceQueueTransaction::TYPE_NAME:
$missing = $this->validateIsEmptyTextField(
$object->getName(),
$xactions);
if ($missing) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Required'),
pht('A queue must have a name.'),
nonempty(last($xactions), null));
$error->setIsMissingFieldError(true);
$errors[] = $error;
}
break;
}
return $errors;
}
} }

View file

@ -96,14 +96,15 @@ final class NuanceSourceEditEngine
->setKey('name') ->setKey('name')
->setLabel(pht('Name')) ->setLabel(pht('Name'))
->setDescription(pht('Name of the source.')) ->setDescription(pht('Name of the source.'))
->setTransactionType(NuanceSourceTransaction::TYPE_NAME) ->setTransactionType(NuanceSourceNameTransaction::TRANSACTIONTYPE)
->setIsRequired(true) ->setIsRequired(true)
->setValue($object->getName()), ->setValue($object->getName()),
id(new PhabricatorDatasourceEditField()) id(new PhabricatorDatasourceEditField())
->setKey('defaultQueue') ->setKey('defaultQueue')
->setLabel(pht('Default Queue')) ->setLabel(pht('Default Queue'))
->setDescription(pht('Default queue.')) ->setDescription(pht('Default queue.'))
->setTransactionType(NuanceSourceTransaction::TYPE_DEFAULT_QUEUE) ->setTransactionType(
NuanceSourceDefaultQueueTransaction::TRANSACTIONTYPE)
->setDatasource(new NuanceQueueDatasource()) ->setDatasource(new NuanceQueueDatasource())
->setSingleValue($object->getDefaultQueuePHID()), ->setSingleValue($object->getDefaultQueuePHID()),
); );

View file

@ -18,111 +18,10 @@ final class NuanceSourceEditor
public function getTransactionTypes() { public function getTransactionTypes() {
$types = parent::getTransactionTypes(); $types = parent::getTransactionTypes();
$types[] = NuanceSourceTransaction::TYPE_NAME;
$types[] = NuanceSourceTransaction::TYPE_DEFAULT_QUEUE;
$types[] = PhabricatorTransactions::TYPE_EDGE;
$types[] = PhabricatorTransactions::TYPE_COMMENT;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types; return $types;
} }
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case NuanceSourceTransaction::TYPE_NAME:
return $object->getName();
case NuanceSourceTransaction::TYPE_DEFAULT_QUEUE:
return $object->getDefaultQueuePHID();
}
return parent::getCustomTransactionOldValue($object, $xaction);
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case NuanceSourceTransaction::TYPE_NAME:
case NuanceSourceTransaction::TYPE_DEFAULT_QUEUE:
return $xaction->getNewValue();
}
return parent::getCustomTransactionNewValue($object, $xaction);
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case NuanceSourceTransaction::TYPE_NAME:
$object->setName($xaction->getNewValue());
break;
case NuanceSourceTransaction::TYPE_DEFAULT_QUEUE:
$object->setDefaultQueuePHID($xaction->getNewValue());
break;
}
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case NuanceSourceTransaction::TYPE_NAME:
case NuanceSourceTransaction::TYPE_DEFAULT_QUEUE:
return;
}
return parent::applyCustomExternalTransaction($object, $xaction);
}
protected function validateTransaction(
PhabricatorLiskDAO $object,
$type,
array $xactions) {
$errors = parent::validateTransaction($object, $type, $xactions);
switch ($type) {
case NuanceSourceTransaction::TYPE_NAME:
$missing = $this->validateIsEmptyTextField(
$object->getName(),
$xactions);
if ($missing) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Required'),
pht('Source name is required.'),
nonempty(last($xactions), null));
$error->setIsMissingFieldError(true);
$errors[] = $error;
}
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;
}
} }

View file

@ -0,0 +1,54 @@
<?php
final class NuanceFormItemType
extends NuanceItemType {
const ITEMTYPE = 'form.item';
public function getItemTypeDisplayName() {
return pht('Form');
}
public function getItemDisplayName(NuanceItem $item) {
return pht('Complaint');
}
protected function newWorkCommands(NuanceItem $item) {
return array(
$this->newCommand('trash')
->setIcon('fa-trash')
->setName(pht('Throw In Trash')),
);
}
protected function newItemView(NuanceItem $item) {
$viewer = $this->getViewer();
$content = $item->getItemProperty('complaint');
$content_view = id(new PHUIRemarkupView($viewer, $content))
->setContextObject($item);
$content_section = id(new PHUIPropertyListView())
->addTextContent(
phutil_tag(
'div',
array(
'class' => 'phabricator-remarkup',
),
$content_view));
$content_box = id(new PHUIObjectBoxView())
->setHeaderText(pht('Complaint'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->appendChild($content_section);
return array(
$content_box,
);
}
protected function handleAction(NuanceItem $item, $action) {
return null;
}
}

View file

@ -329,6 +329,9 @@ final class NuanceGitHubEventItemType
NuanceItem $item, NuanceItem $item,
NuanceItemCommand $command) { NuanceItemCommand $command) {
// TODO: This code is no longer reachable, and has moved to
// CommandImplementation subclasses.
$action = $command->getCommand(); $action = $command->getCommand();
switch ($action) { switch ($action) {
case 'sync': case 'sync':

View file

@ -32,6 +32,10 @@ abstract class NuanceItemType
return $this->newItemView($item); return $this->newItemView($item);
} }
final public function buildItemWorkView(NuanceItem $item) {
return $this->newItemView($item);
}
protected function newItemView(NuanceItem $item) { protected function newItemView(NuanceItem $item) {
return null; return null;
} }
@ -91,57 +95,15 @@ abstract class NuanceItemType
} }
final public function buildActionResponse(NuanceItem $item, $action) { final public function buildActionResponse(NuanceItem $item, $action) {
$response = $this->handleAction($item, $action); return $this->handleAction($item, $action);
if ($response === null) {
return new Aphront404Response();
}
return $response;
} }
protected function handleAction(NuanceItem $item, $action) { protected function handleAction(NuanceItem $item, $action) {
return null; return null;
} }
final public function applyCommand( final public function buildWorkCommands(NuanceItem $item) {
NuanceItem $item, return $this->newWorkCommands($item);
NuanceItemCommand $command) {
$result = $this->handleCommand($item, $command);
if ($result === null) {
return;
}
$xaction = id(new NuanceItemTransaction())
->setTransactionType(NuanceItemTransaction::TYPE_COMMAND)
->setNewValue(
array(
'command' => $command->getCommand(),
'parameters' => $command->getParameters(),
'result' => $result,
));
$viewer = $this->getViewer();
// TODO: Maybe preserve the actor's original content source?
$source = PhabricatorContentSource::newForSource(
PhabricatorDaemonContentSource::SOURCECONST);
$editor = id(new NuanceItemEditor())
->setActor($viewer)
->setActingAsPHID($command->getAuthorPHID())
->setContentSource($source)
->setContinueOnMissingFields(true)
->setContinueOnNoEffect(true)
->applyTransactions($item, array($xaction));
}
protected function handleCommand(
NuanceItem $item,
NuanceItemCommand $command) {
return null;
} }
final protected function newContentSource( final protected function newContentSource(
@ -159,4 +121,8 @@ abstract class NuanceItemType
return id(new PhabricatorNuanceApplication())->getPHID(); return id(new PhabricatorNuanceApplication())->getPHID();
} }
protected function newCommand($command_key) {
return id(new NuanceItemCommandSpec())
->setCommandKey($command_key);
}
} }

View file

@ -33,7 +33,7 @@ final class NuanceItemPHIDType extends PhabricatorPHIDType {
foreach ($handles as $phid => $handle) { foreach ($handles as $phid => $handle) {
$item = $objects[$phid]; $item = $objects[$phid];
$handle->setName($item->getItemDisplayName()); $handle->setName($item->getDisplayName());
$handle->setURI($item->getURI()); $handle->setURI($item->getURI());
} }
} }

View file

@ -5,6 +5,7 @@ final class NuanceItemCommandQuery
private $ids; private $ids;
private $itemPHIDs; private $itemPHIDs;
private $statuses;
public function withIDs(array $ids) { public function withIDs(array $ids) {
$this->ids = $ids; $this->ids = $ids;
@ -16,6 +17,11 @@ final class NuanceItemCommandQuery
return $this; return $this;
} }
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function newResultObject() { public function newResultObject() {
return new NuanceItemCommand(); return new NuanceItemCommand();
} }
@ -41,6 +47,13 @@ final class NuanceItemCommandQuery
$this->itemPHIDs); $this->itemPHIDs);
} }
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'status IN (%Ls)',
$this->statuses);
}
return $where; return $where;
} }

View file

@ -6,9 +6,11 @@ final class NuanceItemQuery
private $ids; private $ids;
private $phids; private $phids;
private $sourcePHIDs; private $sourcePHIDs;
private $queuePHIDs;
private $itemTypes; private $itemTypes;
private $itemKeys; private $itemKeys;
private $containerKeys; private $containerKeys;
private $statuses;
public function withIDs(array $ids) { public function withIDs(array $ids) {
$this->ids = $ids; $this->ids = $ids;
@ -25,6 +27,11 @@ final class NuanceItemQuery
return $this; return $this;
} }
public function withQueuePHIDs(array $queue_phids) {
$this->queuePHIDs = $queue_phids;
return $this;
}
public function withItemTypes(array $item_types) { public function withItemTypes(array $item_types) {
$this->itemTypes = $item_types; $this->itemTypes = $item_types;
return $this; return $this;
@ -35,6 +42,11 @@ final class NuanceItemQuery
return $this; return $this;
} }
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function withItemContainerKeys(array $container_keys) { public function withItemContainerKeys(array $container_keys) {
$this->containerKeys = $container_keys; $this->containerKeys = $container_keys;
return $this; return $this;
@ -49,13 +61,11 @@ final class NuanceItemQuery
} }
protected function willFilterPage(array $items) { protected function willFilterPage(array $items) {
$viewer = $this->getViewer();
$source_phids = mpull($items, 'getSourcePHID'); $source_phids = mpull($items, 'getSourcePHID');
// 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()) $sources = id(new NuanceSourceQuery())
->setViewer(PhabricatorUser::getOmnipotentUser()) ->setViewer($viewer)
->withPHIDs($source_phids) ->withPHIDs($source_phids)
->execute(); ->execute();
$sources = mpull($sources, null, 'getPHID'); $sources = mpull($sources, null, 'getPHID');
@ -81,6 +91,43 @@ final class NuanceItemQuery
$item->attachImplementation($type); $item->attachImplementation($type);
} }
$queue_phids = array();
foreach ($items as $item) {
$queue_phid = $item->getQueuePHID();
if ($queue_phid) {
$queue_phids[$queue_phid] = $queue_phid;
}
}
if ($queue_phids) {
$queues = id(new NuanceQueueQuery())
->setViewer($viewer)
->withPHIDs($queue_phids)
->execute();
$queues = mpull($queues, null, 'getPHID');
} else {
$queues = array();
}
foreach ($items as $key => $item) {
$queue_phid = $item->getQueuePHID();
if (!$queue_phid) {
$item->attachQueue(null);
continue;
}
$queue = idx($queues, $queue_phid);
if (!$queue) {
unset($items[$key]);
$this->didRejectResult($item);
continue;
}
$item->attachQueue($queue);
}
return $items; return $items;
} }
@ -94,6 +141,13 @@ final class NuanceItemQuery
$this->sourcePHIDs); $this->sourcePHIDs);
} }
if ($this->queuePHIDs !== null) {
$where[] = qsprintf(
$conn,
'queuePHID IN (%Ls)',
$this->queuePHIDs);
}
if ($this->ids !== null) { if ($this->ids !== null) {
$where[] = qsprintf( $where[] = qsprintf(
$conn, $conn,
@ -108,6 +162,13 @@ final class NuanceItemQuery
$this->phids); $this->phids);
} }
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'status IN (%Ls)',
$this->statuses);
}
if ($this->itemTypes !== null) { if ($this->itemTypes !== null) {
$where[] = qsprintf( $where[] = qsprintf(
$conn, $conn,

View file

@ -72,6 +72,19 @@ final class NuanceItemSearchEngine
$impl->getItemTypeDisplayIcon(), $impl->getItemTypeDisplayIcon(),
$impl->getItemTypeDisplayName()); $impl->getItemTypeDisplayName());
$queue = $item->getQueue();
if ($queue) {
$view->addAttribute(
phutil_tag(
'a',
array(
'href' => $queue->getURI(),
),
$queue->getName()));
} else {
$view->addAttribute(phutil_tag('em', array(), pht('Not in Queue')));
}
$list->addItem($view); $list->addItem($view);
} }

View file

@ -39,6 +39,8 @@ final class NuancePhabricatorFormSourceDefinition
$content_source = PhabricatorContentSource::newFromRequest($request); $content_source = PhabricatorContentSource::newFromRequest($request);
$item = $this->newItemFromProperties( $item = $this->newItemFromProperties(
NuanceFormItemType::ITEMTYPE,
$viewer->getPHID(),
$properties, $properties,
$content_source); $content_source);
@ -79,7 +81,7 @@ final class NuancePhabricatorFormSourceDefinition
NuanceItem $item, NuanceItem $item,
PHUIPropertyListView $view) { PHUIPropertyListView $view) {
$complaint = $item->getNuanceProperty('complaint'); $complaint = $item->getItemProperty('complaint');
$complaint = new PHUIRemarkupView($viewer, $complaint); $complaint = new PHUIRemarkupView($viewer, $complaint);
$view->addSectionHeader( $view->addSectionHeader(
pht('Complaint'), 'fa-exclamation-circle'); pht('Complaint'), 'fa-exclamation-circle');

View file

@ -149,6 +149,8 @@ abstract class NuanceSourceDefinition extends Phobject {
} }
protected function newItemFromProperties( protected function newItemFromProperties(
$item_type,
$author_phid,
array $properties, array $properties,
PhabricatorContentSource $content_source) { PhabricatorContentSource $content_source) {
@ -157,29 +159,31 @@ abstract class NuanceSourceDefinition extends Phobject {
$actor = PhabricatorUser::getOmnipotentUser(); $actor = PhabricatorUser::getOmnipotentUser();
$source = $this->getSource(); $source = $this->getSource();
$item = NuanceItem::initializeNewItem(); $item = NuanceItem::initializeNewItem($item_type);
$xactions = array(); $xactions = array();
$xactions[] = id(new NuanceItemTransaction()) $xactions[] = id(new NuanceItemTransaction())
->setTransactionType(NuanceItemTransaction::TYPE_SOURCE) ->setTransactionType(NuanceItemSourceTransaction::TRANSACTIONTYPE)
->setNewValue($source->getPHID()); ->setNewValue($source->getPHID());
// TODO: Eventually, apply real routing rules. For now, just put everything // TODO: Eventually, apply real routing rules. For now, just put everything
// in the default queue for the source. // in the default queue for the source.
$xactions[] = id(new NuanceItemTransaction()) $xactions[] = id(new NuanceItemTransaction())
->setTransactionType(NuanceItemTransaction::TYPE_QUEUE) ->setTransactionType(NuanceItemQueueTransaction::TRANSACTIONTYPE)
->setNewValue($source->getDefaultQueuePHID()); ->setNewValue($source->getDefaultQueuePHID());
// TODO: Maybe this should all be modular transactions now?
foreach ($properties as $key => $property) { foreach ($properties as $key => $property) {
$xactions[] = id(new NuanceItemTransaction()) $xactions[] = id(new NuanceItemTransaction())
->setTransactionType(NuanceItemTransaction::TYPE_PROPERTY) ->setTransactionType(NuanceItemPropertyTransaction::TRANSACTIONTYPE)
->setMetadataValue(NuanceItemTransaction::PROPERTY_KEY, $key) ->setMetadataValue(NuanceItemTransaction::PROPERTY_KEY, $key)
->setNewValue($property); ->setNewValue($property);
} }
$editor = id(new NuanceItemEditor()) $editor = id(new NuanceItemEditor())
->setActor($actor) ->setActor($actor)
->setActingAsPHID($author_phid)
->setContentSource($content_source); ->setContentSource($content_source);
$editor->applyTransactions($item, $xactions); $editor->applyTransactions($item, $xactions);

View file

@ -9,7 +9,6 @@ final class NuanceItem
const STATUS_IMPORTING = 'importing'; const STATUS_IMPORTING = 'importing';
const STATUS_ROUTING = 'routing'; const STATUS_ROUTING = 'routing';
const STATUS_OPEN = 'open'; const STATUS_OPEN = 'open';
const STATUS_ASSIGNED = 'assigned';
const STATUS_CLOSED = 'closed'; const STATUS_CLOSED = 'closed';
protected $status; protected $status;
@ -23,11 +22,16 @@ final class NuanceItem
protected $data = array(); protected $data = array();
protected $mailKey; protected $mailKey;
private $queue = self::ATTACHABLE;
private $source = self::ATTACHABLE; private $source = self::ATTACHABLE;
private $implementation = self::ATTACHABLE; private $implementation = self::ATTACHABLE;
public static function initializeNewItem() { public static function initializeNewItem($item_type) {
// TODO: Validate that the type is valid, and construct and attach it.
return id(new NuanceItem()) return id(new NuanceItem())
->setItemType($item_type)
->setStatus(self::STATUS_OPEN); ->setStatus(self::STATUS_OPEN);
} }
@ -42,7 +46,7 @@ final class NuanceItem
'requestorPHID' => 'phid?', 'requestorPHID' => 'phid?',
'queuePHID' => 'phid?', 'queuePHID' => 'phid?',
'itemType' => 'text64', 'itemType' => 'text64',
'itemKey' => 'text64', 'itemKey' => 'text64?',
'itemContainerKey' => 'text64?', 'itemContainerKey' => 'text64?',
'status' => 'text32', 'status' => 'text32',
'mailKey' => 'bytes20', 'mailKey' => 'bytes20',
@ -172,6 +176,15 @@ final class NuanceItem
return $this; return $this;
} }
public function getQueue() {
return $this->assertAttached($this->queue);
}
public function attachQueue(NuanceQueue $queue = null) {
$this->queue = $queue;
return $this;
}
/* -( PhabricatorApplicationTransactionInterface )------------------------- */ /* -( PhabricatorApplicationTransactionInterface )------------------------- */

View file

@ -4,32 +4,86 @@ final class NuanceItemCommand
extends NuanceDAO extends NuanceDAO
implements PhabricatorPolicyInterface { implements PhabricatorPolicyInterface {
const STATUS_ISSUED = 'issued';
const STATUS_EXECUTING = 'executing';
const STATUS_DONE = 'done';
const STATUS_FAILED = 'failed';
protected $itemPHID; protected $itemPHID;
protected $authorPHID; protected $authorPHID;
protected $queuePHID;
protected $command; protected $command;
protected $parameters; protected $status;
protected $parameters = array();
public static function initializeNewCommand() { public static function initializeNewCommand() {
return new self(); return id(new self())
->setStatus(self::STATUS_ISSUED);
} }
protected function getConfiguration() { protected function getConfiguration() {
return array( return array(
self::CONFIG_TIMESTAMPS => false,
self::CONFIG_SERIALIZATION => array( self::CONFIG_SERIALIZATION => array(
'parameters' => self::SERIALIZATION_JSON, 'parameters' => self::SERIALIZATION_JSON,
), ),
self::CONFIG_COLUMN_SCHEMA => array( self::CONFIG_COLUMN_SCHEMA => array(
'command' => 'text64', 'command' => 'text64',
'status' => 'text64',
'queuePHID' => 'phid?',
), ),
self::CONFIG_KEY_SCHEMA => array( self::CONFIG_KEY_SCHEMA => array(
'key_item' => array( 'key_pending' => array(
'columns' => array('itemPHID'), 'columns' => array('itemPHID', 'status'),
), ),
), ),
) + parent::getConfiguration(); ) + parent::getConfiguration();
} }
public static function getStatusMap() {
return array(
self::STATUS_ISSUED => array(
'name' => pht('Issued'),
'icon' => 'fa-clock-o',
'color' => 'bluegrey',
),
self::STATUS_EXECUTING => array(
'name' => pht('Executing'),
'icon' => 'fa-play',
'color' => 'green',
),
self::STATUS_DONE => array(
'name' => pht('Done'),
'icon' => 'fa-check',
'color' => 'blue',
),
self::STATUS_FAILED => array(
'name' => pht('Failed'),
'icon' => 'fa-times',
'color' => 'red',
),
);
}
private function getStatusSpec() {
$map = self::getStatusMap();
return idx($map, $this->getStatus(), array());
}
public function getStatusIcon() {
$spec = $this->getStatusSpec();
return idx($spec, 'icon', 'fa-question');
}
public function getStatusColor() {
$spec = $this->getStatusSpec();
return idx($spec, 'color', 'indigo');
}
public function getStatusName() {
$spec = $this->getStatusSpec();
return idx($spec, 'name', $this->getStatus());
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */ /* -( PhabricatorPolicyInterface )----------------------------------------- */

View file

@ -5,13 +5,6 @@ final class NuanceItemTransaction
const PROPERTY_KEY = 'property.key'; const PROPERTY_KEY = 'property.key';
const TYPE_OWNER = 'nuance.item.owner';
const TYPE_REQUESTOR = 'nuance.item.requestor';
const TYPE_SOURCE = 'nuance.item.source';
const TYPE_PROPERTY = 'nuance.item.property';
const TYPE_QUEUE = 'nuance.item.queue';
const TYPE_COMMAND = 'nuance.item.command';
public function getApplicationTransactionType() { public function getApplicationTransactionType() {
return NuanceItemPHIDType::TYPECONST; return NuanceItemPHIDType::TYPECONST;
} }
@ -20,61 +13,8 @@ final class NuanceItemTransaction
return new NuanceItemTransactionComment(); return new NuanceItemTransactionComment();
} }
public function shouldHide() { public function getBaseTransactionClass() {
$old = $this->getOldValue(); return 'NuanceItemTransactionType';
$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));
case self::TYPE_COMMAND:
// TODO: Give item types a chance to render this properly.
return pht(
'%s applied command "%s" to this item.',
$this->renderHandleLink($author_phid),
idx($new, 'command'));
}
return parent::getTitle();
} }
} }

View file

@ -43,6 +43,10 @@ final class NuanceQueue
return '/nuance/queue/view/'.$this->getID().'/'; return '/nuance/queue/view/'.$this->getID().'/';
} }
public function getWorkURI() {
return '/nuance/queue/work/'.$this->getID().'/';
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */ /* -( PhabricatorPolicyInterface )----------------------------------------- */

View file

@ -2,8 +2,6 @@
final class NuanceQueueTransaction extends NuanceTransaction { final class NuanceQueueTransaction extends NuanceTransaction {
const TYPE_NAME = 'nuance.queue.name';
public function getApplicationTransactionType() { public function getApplicationTransactionType() {
return NuanceQueuePHIDType::TYPECONST; return NuanceQueuePHIDType::TYPECONST;
} }
@ -12,26 +10,8 @@ final class NuanceQueueTransaction extends NuanceTransaction {
return new NuanceQueueTransactionComment(); return new NuanceQueueTransactionComment();
} }
public function getTitle() { public function getBaseTransactionClass() {
$old = $this->getOldValue(); return 'NuanceQueueTransactionType';
$new = $this->getNewValue();
$type = $this->getTransactionType();
$author_phid = $this->getAuthorPHID();
switch ($type) {
case PhabricatorTransactions::TYPE_CREATE:
return pht(
'%s created this queue.',
$this->renderHandleLink($author_phid));
case self::TYPE_NAME:
return pht(
'%s renamed this queue from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
}
return parent::getTitle();
} }
} }

View file

@ -3,9 +3,6 @@
final class NuanceSourceTransaction final class NuanceSourceTransaction
extends NuanceTransaction { extends NuanceTransaction {
const TYPE_NAME = 'source.name';
const TYPE_DEFAULT_QUEUE = 'source.queue.default';
public function getApplicationTransactionType() { public function getApplicationTransactionType() {
return NuanceSourcePHIDType::TYPECONST; return NuanceSourcePHIDType::TYPECONST;
} }
@ -14,63 +11,8 @@ final class NuanceSourceTransaction
return new NuanceSourceTransactionComment(); return new NuanceSourceTransactionComment();
} }
public function shouldHide() { public function getBaseTransactionClass() {
$old = $this->getOldValue(); return 'NuanceSourceTransactionType';
$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() {
$old = $this->getOldValue();
$new = $this->getNewValue();
$type = $this->getTransactionType();
$author_phid = $this->getAuthorPHID();
switch ($type) {
case self::TYPE_DEFAULT_QUEUE:
return pht(
'%s changed the default queue from %s to %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($old),
$this->renderHandleLink($new));
case self::TYPE_NAME:
return pht(
'%s renamed this source from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
}
return parent::getTitle();
} }
} }

View file

@ -1,7 +1,7 @@
<?php <?php
abstract class NuanceTransaction abstract class NuanceTransaction
extends PhabricatorApplicationTransaction { extends PhabricatorModularTransaction {
public function getApplicationName() { public function getApplicationName() {
return 'nuance'; return 'nuance';

View file

@ -6,9 +6,7 @@ final class NuanceItemUpdateWorker
protected function doWork() { protected function doWork() {
$item_phid = $this->getTaskDataValue('itemPHID'); $item_phid = $this->getTaskDataValue('itemPHID');
$hash = PhabricatorHash::digestForIndex($item_phid); $lock = $this->newLock($item_phid);
$lock_key = "nuance.item.{$hash}";
$lock = PhabricatorGlobalLock::newLock($lock_key);
$lock->lock(1); $lock->lock(1);
try { try {
@ -55,19 +53,109 @@ final class NuanceItemUpdateWorker
private function applyCommands(NuanceItem $item) { private function applyCommands(NuanceItem $item) {
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$impl = $item->getImplementation();
$impl->setViewer($viewer);
$commands = id(new NuanceItemCommandQuery()) $commands = id(new NuanceItemCommandQuery())
->setViewer($viewer) ->setViewer($viewer)
->withItemPHIDs(array($item->getPHID())) ->withItemPHIDs(array($item->getPHID()))
->withStatuses(
array(
NuanceItemCommand::STATUS_ISSUED,
))
->execute(); ->execute();
$commands = msort($commands, 'getID'); $commands = msort($commands, 'getID');
$this->executeCommandList($item, $commands);
}
public function executeCommands(NuanceItem $item, array $commands) {
if (!$commands) {
return true;
}
$item_phid = $item->getPHID();
$viewer = $this->getViewer();
$lock = $this->newLock($item_phid);
try {
$lock->lock(1);
} catch (PhutilLockException $ex) {
return false;
}
try {
$item = $this->loadItem($item_phid);
// Reload commands now that we have a lock, to make sure we don't
// execute any commands twice by mistake.
$commands = id(new NuanceItemCommandQuery())
->setViewer($viewer)
->withIDs(mpull($commands, 'getID'))
->execute();
$this->executeCommandList($item, $commands);
} catch (Exception $ex) {
$lock->unlock();
throw $ex;
}
$lock->unlock();
return true;
}
private function executeCommandList(NuanceItem $item, array $commands) {
$viewer = $this->getViewer();
$executors = NuanceCommandImplementation::getAllCommands();
foreach ($commands as $command) { foreach ($commands as $command) {
$impl->applyCommand($item, $command); if ($command->getItemPHID() !== $item->getPHID()) {
$command->delete(); throw new Exception(
pht('Trying to apply a command to the wrong item!'));
}
if ($command->getStatus() !== NuanceItemCommand::STATUS_ISSUED) {
// Never execute commands which have already been issued.
continue;
}
$command
->setStatus(NuanceItemCommand::STATUS_EXECUTING)
->save();
try {
$command_key = $command->getCommand();
$executor = idx($executors, $command_key);
if (!$executor) {
throw new Exception(
pht(
'Unable to execute command "%s": this command does not have '.
'a recognized command implementation.',
$command_key));
}
$executor = clone $executor;
$executor
->setActor($viewer)
->applyCommand($item, $command);
$command
->setStatus(NuanceItemCommand::STATUS_DONE)
->save();
} catch (Exception $ex) {
$command
->setStatus(NuanceItemCommand::STATUS_FAILED)
->save();
throw $ex;
}
} }
} }
private function newLock($item_phid) {
$hash = PhabricatorHash::digestForIndex($item_phid);
$lock_key = "nuance.item.{$hash}";
return PhabricatorGlobalLock::newLock($lock_key);
}
} }

View file

@ -0,0 +1,22 @@
<?php
final class NuanceItemCommandTransaction
extends NuanceItemTransactionType {
const TRANSACTIONTYPE = 'nuance.item.command';
public function generateOldValue($object) {
return null;
}
public function getTitle() {
$spec = $this->getNewValue();
$command_key = idx($spec, 'command', '???');
return pht(
'%s applied a "%s" command to this item.',
$this->renderAuthor(),
$command_key);
}
}

View file

@ -0,0 +1,27 @@
<?php
final class NuanceItemOwnerTransaction
extends NuanceItemTransactionType {
const TRANSACTIONTYPE = 'nuance.item.owner';
public function generateOldValue($object) {
return $object->getOwnerPHID();
}
public function applyInternalEffects($object, $value) {
$object->setOwnerPHID($value);
}
public function getTitle() {
// TODO: Assign, unassign strings probably need variants.
return pht(
'%s reassigned this item from %s to %s.',
$this->renderAuthor(),
$this->renderHandle($this->getOldValue()),
$this->renderHandle($this->getNewValue()));
}
}

View file

@ -0,0 +1,27 @@
<?php
final class NuanceItemPropertyTransaction
extends NuanceItemTransactionType {
const TRANSACTIONTYPE = 'nuance.item.property';
public function generateOldValue($object) {
$property_key = NuanceItemTransaction::PROPERTY_KEY;
$key = $this->getMetadataValue($property_key);
return $object->getItemProperty($key);
}
public function applyInternalEffects($object, $value) {
$property_key = NuanceItemTransaction::PROPERTY_KEY;
$key = $this->getMetadataValue($property_key);
$object->setItemProperty($key, $value);
}
public function getTitle() {
return pht(
'%s set a property on this item.',
$this->renderAuthor());
}
}

View file

@ -0,0 +1,25 @@
<?php
final class NuanceItemQueueTransaction
extends NuanceItemTransactionType {
const TRANSACTIONTYPE = 'nuance.item.queue';
public function generateOldValue($object) {
return $object->getQueuePHID();
}
public function applyInternalEffects($object, $value) {
$object->setQueuePHID($value);
}
public function getTitle() {
return pht(
'%s rerouted this item from %s to %s.',
$this->renderAuthor(),
$this->renderHandle($this->getOldValue()),
$this->renderHandle($this->getNewValue()));
}
}

View file

@ -0,0 +1,16 @@
<?php
final class NuanceItemRequestorTransaction
extends NuanceItemTransactionType {
const TRANSACTIONTYPE = 'nuance.item.requestor';
public function generateOldValue($object) {
return $object->getRequestorPHID();
}
public function applyInternalEffects($object, $value) {
$object->setRequestorPHID($value);
}
}

View file

@ -0,0 +1,16 @@
<?php
final class NuanceItemSourceTransaction
extends NuanceItemTransactionType {
const TRANSACTIONTYPE = 'nuance.item.source';
public function generateOldValue($object) {
return $object->getSourcePHID();
}
public function applyInternalEffects($object, $value) {
$object->setSourcePHID($value);
}
}

View file

@ -0,0 +1,25 @@
<?php
final class NuanceItemStatusTransaction
extends NuanceItemTransactionType {
const TRANSACTIONTYPE = 'nuance.item.status';
public function generateOldValue($object) {
return $object->getStatus();
}
public function applyInternalEffects($object, $value) {
$object->setStatus($value);
}
public function getTitle() {
return pht(
'%s changed the status of this item from %s to %s.',
$this->renderAuthor(),
$this->renderOldValue(),
$this->renderNewValue());
}
}

View file

@ -0,0 +1,4 @@
<?php
abstract class NuanceItemTransactionType
extends PhabricatorModularTransactionType {}

View file

@ -0,0 +1,47 @@
<?php
final class NuanceQueueNameTransaction
extends NuanceQueueTransactionType {
const TRANSACTIONTYPE = 'nuance.queue.name';
public function generateOldValue($object) {
return $object->getName();
}
public function applyInternalEffects($object, $value) {
$object->setName($value);
}
public function getTitle() {
return pht(
'%s renamed this queue from %s to %s.',
$this->renderAuthor(),
$this->renderOldValue(),
$this->renderNewValue());
}
public function validateTransactions($object, array $xactions) {
$errors = array();
if ($this->isEmptyTextTransaction($object->getName(), $xactions)) {
$errors[] = $this->newRequiredError(
pht('Queues must have a name.'));
}
$max_length = $object->getColumnMaximumByteLength('name');
foreach ($xactions as $xaction) {
$new_value = $xaction->getNewValue();
$new_length = strlen($new_value);
if ($new_length > $max_length) {
$errors[] = $this->newInvalidError(
pht(
'Queue names must not be longer than %s character(s).',
new PhutilNumber($max_length)));
}
}
return $errors;
}
}

View file

@ -0,0 +1,4 @@
<?php
abstract class NuanceQueueTransactionType
extends PhabricatorModularTransactionType {}

View file

@ -0,0 +1,42 @@
<?php
final class NuanceSourceDefaultQueueTransaction
extends NuanceSourceTransactionType {
const TRANSACTIONTYPE = 'source.queue.default';
public function generateOldValue($object) {
return $object->getDefaultQueuePHID();
}
public function applyInternalEffects($object, $value) {
$object->setDefaultQueuePHID($value);
}
public function getTitle() {
return pht(
'%s changed the default queue for this source from %s to %s.',
$this->renderAuthor(),
$this->renderOldHandle(),
$this->renderNewHandle());
}
public function validateTransactions($object, array $xactions) {
$errors = array();
if (!$object->getDefaultQueuePHID() && !$xactions) {
$errors[] = $this->newRequiredError(
pht('Sources must have a default queue.'));
}
foreach ($xactions as $xaction) {
if (!$xaction->getNewValue()) {
$errors[] = $this->newRequiredError(
pht('Sources must have a default queue.'));
}
}
return $errors;
}
}

View file

@ -0,0 +1,47 @@
<?php
final class NuanceSourceNameTransaction
extends NuanceSourceTransactionType {
const TRANSACTIONTYPE = 'source.name';
public function generateOldValue($object) {
return $object->getName();
}
public function applyInternalEffects($object, $value) {
$object->setName($value);
}
public function getTitle() {
return pht(
'%s renamed this source from %s to %s.',
$this->renderAuthor(),
$this->renderOldValue(),
$this->renderNewValue());
}
public function validateTransactions($object, array $xactions) {
$errors = array();
if ($this->isEmptyTextTransaction($object->getName(), $xactions)) {
$errors[] = $this->newRequiredError(
pht('Sources must have a name.'));
}
$max_length = $object->getColumnMaximumByteLength('name');
foreach ($xactions as $xaction) {
$new_value = $xaction->getNewValue();
$new_length = strlen($new_value);
if ($new_length > $max_length) {
$errors[] = $this->newInvalidError(
pht(
'Source names must not be longer than %s character(s).',
new PhutilNumber($max_length)));
}
}
return $errors;
}
}

Some files were not shown because too many files have changed in this diff Show more