@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Allow Drydock blueprints to be disabled

Summary: Ref T9252. If you have a blueprint and you do not like that blueprint very much, you can disable it.

Test Plan: Disabled / enabled some blueprints.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T9252

Differential Revision: https://secure.phabricator.com/D14156

+183 -27
+2
resources/sql/autopatches/20150924.drydock.disable.1.sql
··· 1 + ALTER TABLE {$NAMESPACE}_drydock.drydock_blueprint 2 + ADD isDisabled BOOL NOT NULL;
+2
src/__phutil_library_map__.php
··· 805 805 'DrydockBlueprintCreateController' => 'applications/drydock/controller/DrydockBlueprintCreateController.php', 806 806 'DrydockBlueprintCustomField' => 'applications/drydock/customfield/DrydockBlueprintCustomField.php', 807 807 'DrydockBlueprintDatasource' => 'applications/drydock/typeahead/DrydockBlueprintDatasource.php', 808 + 'DrydockBlueprintDisableController' => 'applications/drydock/controller/DrydockBlueprintDisableController.php', 808 809 'DrydockBlueprintEditController' => 'applications/drydock/controller/DrydockBlueprintEditController.php', 809 810 'DrydockBlueprintEditor' => 'applications/drydock/editor/DrydockBlueprintEditor.php', 810 811 'DrydockBlueprintImplementation' => 'applications/drydock/blueprint/DrydockBlueprintImplementation.php', ··· 4530 4531 'DrydockBlueprintCreateController' => 'DrydockBlueprintController', 4531 4532 'DrydockBlueprintCustomField' => 'PhabricatorCustomField', 4532 4533 'DrydockBlueprintDatasource' => 'PhabricatorTypeaheadDatasource', 4534 + 'DrydockBlueprintDisableController' => 'DrydockBlueprintController', 4533 4535 'DrydockBlueprintEditController' => 'DrydockBlueprintController', 4534 4536 'DrydockBlueprintEditor' => 'PhabricatorApplicationTransactionEditor', 4535 4537 'DrydockBlueprintImplementation' => 'Phobject',
+9 -3
src/applications/drydock/application/PhabricatorDrydockApplication.php
··· 49 49 '' => 'DrydockConsoleController', 50 50 'blueprint/' => array( 51 51 '(?:query/(?P<queryKey>[^/]+)/)?' => 'DrydockBlueprintListController', 52 - '(?P<id>[1-9]\d*)/' => 'DrydockBlueprintViewController', 52 + '(?P<id>[1-9]\d*)/' => array( 53 + '' => 'DrydockBlueprintViewController', 54 + '(?P<action>disable|enable)/' => 55 + 'DrydockBlueprintDisableController', 56 + ), 53 57 'create/' => 'DrydockBlueprintCreateController', 54 58 'edit/(?:(?P<id>[1-9]\d*)/)?' => 'DrydockBlueprintEditController', 55 59 ), ··· 62 66 ), 63 67 'lease/' => array( 64 68 '(?:query/(?P<queryKey>[^/]+)/)?' => 'DrydockLeaseListController', 65 - '(?P<id>[1-9]\d*)/' => 'DrydockLeaseViewController', 66 - '(?P<id>[1-9]\d*)/release/' => 'DrydockLeaseReleaseController', 69 + '(?P<id>[1-9]\d*)/' => array( 70 + '' => 'DrydockLeaseViewController', 71 + 'release/' => 'DrydockLeaseReleaseController', 72 + ), 67 73 ), 68 74 'log/' => array( 69 75 '(?:query/(?P<queryKey>[^/]+)/)?' => 'DrydockLogListController',
+64
src/applications/drydock/controller/DrydockBlueprintDisableController.php
··· 1 + <?php 2 + 3 + final class DrydockBlueprintDisableController 4 + extends DrydockBlueprintController { 5 + 6 + public function handleRequest(AphrontRequest $request) { 7 + $viewer = $request->getViewer(); 8 + $id = $request->getURIData('id'); 9 + 10 + $blueprint = id(new DrydockBlueprintQuery()) 11 + ->setViewer($viewer) 12 + ->withIDs(array($id)) 13 + ->requireCapabilities( 14 + array( 15 + PhabricatorPolicyCapability::CAN_VIEW, 16 + PhabricatorPolicyCapability::CAN_EDIT, 17 + )) 18 + ->executeOne(); 19 + if (!$blueprint) { 20 + return new Aphront404Response(); 21 + } 22 + 23 + $is_disable = ($request->getURIData('action') == 'disable'); 24 + $id = $blueprint->getID(); 25 + $cancel_uri = $this->getApplicationURI("blueprint/{$id}/"); 26 + 27 + if ($request->isFormPost()) { 28 + $xactions = array(); 29 + 30 + $xactions[] = id(new DrydockBlueprintTransaction()) 31 + ->setTransactionType(DrydockBlueprintTransaction::TYPE_DISABLED) 32 + ->setNewValue($is_disable ? 1 : 0); 33 + 34 + $editor = id(new DrydockBlueprintEditor()) 35 + ->setActor($viewer) 36 + ->setContentSourceFromRequest($request) 37 + ->setContinueOnNoEffect(true) 38 + ->setContinueOnMissingFields(true) 39 + ->applyTransactions($blueprint, $xactions); 40 + 41 + return id(new AphrontRedirectResponse())->setURI($cancel_uri); 42 + } 43 + 44 + if ($is_disable) { 45 + $title = pht('Disable Blueprint'); 46 + $body = pht( 47 + 'If you disable this blueprint, Drydock will no longer use it to '. 48 + 'allocate new resources. Existing resources will not be affected.'); 49 + $button = pht('Disable Blueprint'); 50 + } else { 51 + $title = pht('Enable Blueprint'); 52 + $body = pht( 53 + 'If you enable this blueprint, Drydock will start using it to '. 54 + 'allocate new resources.'); 55 + $button = pht('Enable Blueprint'); 56 + } 57 + 58 + return $this->newDialog() 59 + ->setTitle($title) 60 + ->appendParagraph($body) 61 + ->addCancelButton($cancel_uri) 62 + ->addSubmitButton($button); 63 + } 64 + }
+4 -2
src/applications/drydock/controller/DrydockBlueprintEditController.php
··· 33 33 return new Aphront400Response(); 34 34 } 35 35 36 - $blueprint = DrydockBlueprint::initializeNewBlueprint($viewer); 37 - $blueprint->setClassName($class); 36 + $blueprint = DrydockBlueprint::initializeNewBlueprint($viewer) 37 + ->setClassName($class) 38 + ->attachImplementation($impl); 39 + 38 40 $cancel_uri = $this->getApplicationURI('blueprint/'); 39 41 } 40 42
+28 -4
src/applications/drydock/controller/DrydockBlueprintViewController.php
··· 21 21 ->setUser($viewer) 22 22 ->setPolicyObject($blueprint); 23 23 24 + if ($blueprint->getIsDisabled()) { 25 + $header->setStatus('fa-ban', 'red', pht('Disabled')); 26 + } else { 27 + $header->setStatus('fa-check', 'bluegrey', pht('Active')); 28 + } 29 + 24 30 $actions = $this->buildActionListView($blueprint); 25 31 $properties = $this->buildPropertyListView($blueprint, $actions); 26 32 ··· 84 90 } 85 91 86 92 private function buildActionListView(DrydockBlueprint $blueprint) { 87 - $viewer = $this->getRequest()->getUser(); 93 + $viewer = $this->getViewer(); 94 + $id = $blueprint->getID(); 88 95 89 96 $view = id(new PhabricatorActionListView()) 90 97 ->setUser($viewer) 91 98 ->setObjectURI($this->getRequest()->getRequestURI()) 92 99 ->setObject($blueprint); 93 100 94 - $uri = '/blueprint/edit/'.$blueprint->getID().'/'; 95 - $uri = $this->getApplicationURI($uri); 101 + $edit_uri = $this->getApplicationURI("blueprint/edit/{$id}/"); 96 102 97 103 $can_edit = PhabricatorPolicyFilter::hasCapability( 98 104 $viewer, ··· 101 107 102 108 $view->addAction( 103 109 id(new PhabricatorActionView()) 104 - ->setHref($uri) 110 + ->setHref($edit_uri) 105 111 ->setName(pht('Edit Blueprint')) 106 112 ->setIcon('fa-pencil') 107 113 ->setWorkflow(!$can_edit) 114 + ->setDisabled(!$can_edit)); 115 + 116 + if (!$blueprint->getIsDisabled()) { 117 + $disable_name = pht('Disable Blueprint'); 118 + $disable_icon = 'fa-ban'; 119 + $disable_uri = $this->getApplicationURI("blueprint/{$id}/disable/"); 120 + } else { 121 + $disable_name = pht('Enable Blueprint'); 122 + $disable_icon = 'fa-check'; 123 + $disable_uri = $this->getApplicationURI("blueprint/{$id}/enable/"); 124 + } 125 + 126 + $view->addAction( 127 + id(new PhabricatorActionView()) 128 + ->setHref($disable_uri) 129 + ->setName($disable_name) 130 + ->setIcon($disable_icon) 131 + ->setWorkflow(true) 108 132 ->setDisabled(!$can_edit)); 109 133 110 134 return $view;
+22 -12
src/applications/drydock/editor/DrydockBlueprintEditor.php
··· 16 16 17 17 $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; 18 18 $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; 19 + 19 20 $types[] = DrydockBlueprintTransaction::TYPE_NAME; 21 + $types[] = DrydockBlueprintTransaction::TYPE_DISABLED; 20 22 21 23 return $types; 22 24 } ··· 28 30 switch ($xaction->getTransactionType()) { 29 31 case DrydockBlueprintTransaction::TYPE_NAME: 30 32 return $object->getBlueprintName(); 33 + case DrydockBlueprintTransaction::TYPE_DISABLED: 34 + return (int)$object->getIsDisabled(); 31 35 } 36 + 37 + return parent::getCustomTransactionOldValue($object, $xaction); 32 38 } 33 39 34 40 protected function getCustomTransactionNewValue( ··· 38 44 switch ($xaction->getTransactionType()) { 39 45 case DrydockBlueprintTransaction::TYPE_NAME: 40 46 return $xaction->getNewValue(); 47 + case DrydockBlueprintTransaction::TYPE_DISABLED: 48 + return (int)$xaction->getNewValue(); 41 49 } 50 + 51 + return parent::getCustomTransactionNewValue($object, $xaction); 42 52 } 43 53 44 54 protected function applyCustomInternalTransaction( ··· 48 58 switch ($xaction->getTransactionType()) { 49 59 case DrydockBlueprintTransaction::TYPE_NAME: 50 60 $object->setBlueprintName($xaction->getNewValue()); 51 - break; 61 + return; 62 + case DrydockBlueprintTransaction::TYPE_DISABLED: 63 + $object->setIsDisabled((int)$xaction->getNewValue()); 64 + return; 52 65 } 66 + 67 + return parent::applyCustomInternalTransaction($object, $xaction); 53 68 } 54 69 55 70 protected function applyCustomExternalTransaction( 56 71 PhabricatorLiskDAO $object, 57 72 PhabricatorApplicationTransaction $xaction) { 58 - return; 59 - } 60 73 61 - protected function extractFilePHIDsFromCustomTransaction( 62 - PhabricatorLiskDAO $object, 63 - PhabricatorApplicationTransaction $xaction) { 64 - return array(); 65 - } 74 + switch ($xaction->getTransactionType()) { 75 + case DrydockBlueprintTransaction::TYPE_NAME: 76 + case DrydockBlueprintTransaction::TYPE_DISABLED: 77 + return; 78 + } 66 79 67 - protected function shouldSendMail( 68 - PhabricatorLiskDAO $object, 69 - array $xactions) { 70 - return false; 80 + return parent::applyCustomExternalTransaction($object, $xaction); 71 81 } 72 82 73 83 }
+13
src/applications/drydock/query/DrydockBlueprintQuery.php
··· 6 6 private $phids; 7 7 private $blueprintClasses; 8 8 private $datasourceQuery; 9 + private $disabled; 9 10 10 11 public function withIDs(array $ids) { 11 12 $this->ids = $ids; ··· 24 25 25 26 public function withDatasourceQuery($query) { 26 27 $this->datasourceQuery = $query; 28 + return $this; 29 + } 30 + 31 + public function withDisabled($disabled) { 32 + $this->disabled = $disabled; 27 33 return $this; 28 34 } 29 35 ··· 80 86 $conn, 81 87 'className IN (%Ls)', 82 88 $this->blueprintClasses); 89 + } 90 + 91 + if ($this->disabled !== null) { 92 + $where[] = qsprintf( 93 + $conn, 94 + 'isDisabled = %d', 95 + (int)$this->disabled); 83 96 } 84 97 85 98 return $where;
+22 -1
src/applications/drydock/query/DrydockBlueprintSearchEngine.php
··· 18 18 protected function buildQueryFromParameters(array $map) { 19 19 $query = $this->newQuery(); 20 20 21 + if ($map['isDisabled'] !== null) { 22 + $query->withDisabled($map['isDisabled']); 23 + } 24 + 21 25 return $query; 22 26 } 23 27 24 28 protected function buildCustomSearchFields() { 25 - return array(); 29 + return array( 30 + id(new PhabricatorSearchThreeStateField()) 31 + ->setLabel(pht('Disabled')) 32 + ->setKey('isDisabled') 33 + ->setOptions( 34 + pht('(Show All)'), 35 + pht('Show Only Disabled Blueprints'), 36 + pht('Hide Disabled Blueprints')), 37 + ); 26 38 } 27 39 28 40 protected function getURI($path) { ··· 31 43 32 44 protected function getBuiltinQueryNames() { 33 45 return array( 46 + 'active' => pht('Active Blueprints'), 34 47 'all' => pht('All Blueprints'), 35 48 ); 36 49 } ··· 40 53 $query->setQueryKey($query_key); 41 54 42 55 switch ($query_key) { 56 + case 'active': 57 + return $query->setParameter('isDisabled', false); 43 58 case 'all': 44 59 return $query; 45 60 } ··· 64 79 65 80 if (!$blueprint->getImplementation()->isEnabled()) { 66 81 $item->setDisabled(true); 82 + $item->addIcon('fa-chain-broken grey', pht('Implementation')); 83 + } 84 + 85 + if ($blueprint->getIsDisabled()) { 86 + $item->setDisabled(true); 87 + $item->addIcon('fa-ban grey', pht('Disabled')); 67 88 } 68 89 69 90 $item->addAttribute($blueprint->getImplementation()->getBlueprintName());
+4 -1
src/applications/drydock/storage/DrydockBlueprint.php
··· 15 15 protected $viewPolicy; 16 16 protected $editPolicy; 17 17 protected $details = array(); 18 + protected $isDisabled; 18 19 19 20 private $implementation = self::ATTACHABLE; 20 21 private $customFields = self::ATTACHABLE; ··· 34 35 return id(new DrydockBlueprint()) 35 36 ->setViewPolicy($view_policy) 36 37 ->setEditPolicy($edit_policy) 37 - ->setBlueprintName(''); 38 + ->setBlueprintName('') 39 + ->setIsDisabled(0); 38 40 } 39 41 40 42 protected function getConfiguration() { ··· 46 48 self::CONFIG_COLUMN_SCHEMA => array( 47 49 'className' => 'text255', 48 50 'blueprintName' => 'sort255', 51 + 'isDisabled' => 'bool', 49 52 ), 50 53 ) + parent::getConfiguration(); 51 54 }
+12 -1
src/applications/drydock/storage/DrydockBlueprintTransaction.php
··· 3 3 final class DrydockBlueprintTransaction 4 4 extends PhabricatorApplicationTransaction { 5 5 6 - const TYPE_NAME = 'drydock:blueprint:name'; 6 + const TYPE_NAME = 'drydock:blueprint:name'; 7 + const TYPE_DISABLED = 'drydock:blueprint:disabled'; 7 8 8 9 public function getApplicationName() { 9 10 return 'drydock'; ··· 30 31 $author_handle, 31 32 $old, 32 33 $new); 34 + } 35 + case self::TYPE_DISABLED: 36 + if ($new) { 37 + return pht( 38 + '%s disabled this blueprint.', 39 + $author_handle); 40 + } else { 41 + return pht( 42 + '%s enabled this blueprint.', 43 + $author_handle); 33 44 } 34 45 } 35 46
+1 -3
src/applications/drydock/worker/DrydockAllocatorWorker.php
··· 184 184 return array(); 185 185 } 186 186 187 - // TODO: When blueprints can be disabled, this query should ignore disabled 188 - // blueprints. 189 - 190 187 $blueprints = id(new DrydockBlueprintQuery()) 191 188 ->setViewer($viewer) 192 189 ->withBlueprintClasses(array_keys($impls)) 190 + ->withDisabled(false) 193 191 ->execute(); 194 192 195 193 $keep = array();