diff --git a/src/applications/drydock/controller/DrydockLeaseViewController.php b/src/applications/drydock/controller/DrydockLeaseViewController.php --- a/src/applications/drydock/controller/DrydockLeaseViewController.php +++ b/src/applications/drydock/controller/DrydockLeaseViewController.php @@ -9,6 +9,7 @@ $lease = id(new DrydockLeaseQuery()) ->setViewer($viewer) ->withIDs(array($id)) + ->needUnconsumedCommands(true) ->executeOne(); if (!$lease) { return new Aphront404Response(); @@ -21,6 +22,10 @@ $header = id(new PHUIHeaderView()) ->setHeader($title); + if ($lease->isReleasing()) { + $header->setStatus('fa-exclamation-triangle', 'red', pht('Releasing')); + } + $actions = $this->buildActionListView($lease); $properties = $this->buildPropertyListView($lease, $actions); @@ -78,6 +83,10 @@ $id = $lease->getID(); $can_release = $lease->canRelease(); + if ($lease->isReleasing()) { + $can_release = false; + } + $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $lease, diff --git a/src/applications/drydock/controller/DrydockResourceViewController.php b/src/applications/drydock/controller/DrydockResourceViewController.php --- a/src/applications/drydock/controller/DrydockResourceViewController.php +++ b/src/applications/drydock/controller/DrydockResourceViewController.php @@ -9,6 +9,7 @@ $resource = id(new DrydockResourceQuery()) ->setViewer($viewer) ->withIDs(array($id)) + ->needUnconsumedCommands(true) ->executeOne(); if (!$resource) { return new Aphront404Response(); @@ -21,6 +22,10 @@ ->setPolicyObject($resource) ->setHeader($title); + if ($resource->isReleasing()) { + $header->setStatus('fa-exclamation-triangle', 'red', pht('Releasing')); + } + $actions = $this->buildActionListView($resource); $properties = $this->buildPropertyListView($resource, $actions); @@ -82,6 +87,10 @@ ->setObject($resource); $can_release = $resource->canRelease(); + if ($resource->isReleasing()) { + $can_release = false; + } + $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $resource, diff --git a/src/applications/drydock/query/DrydockLeaseQuery.php b/src/applications/drydock/query/DrydockLeaseQuery.php --- a/src/applications/drydock/query/DrydockLeaseQuery.php +++ b/src/applications/drydock/query/DrydockLeaseQuery.php @@ -7,7 +7,7 @@ private $resourcePHIDs; private $statuses; private $datasourceQuery; - private $needCommands; + private $needUnconsumedCommands; public function withIDs(array $ids) { $this->ids = $ids; @@ -34,6 +34,11 @@ return $this; } + public function needUnconsumedCommands($need) { + $this->needUnconsumedCommands = $need; + return $this; + } + public function newResultObject() { return new DrydockLease(); } @@ -71,6 +76,25 @@ return $leases; } + protected function didFilterPage(array $leases) { + if ($this->needUnconsumedCommands) { + $commands = id(new DrydockCommandQuery()) + ->setViewer($this->getViewer()) + ->setParentQuery($this) + ->withTargetPHIDs(mpull($leases, 'getPHID')) + ->withConsumed(false) + ->execute(); + $commands = mgroup($commands, 'getTargetPHID'); + + foreach ($leases as $lease) { + $list = idx($commands, $lease->getPHID(), array()); + $lease->attachUnconsumedCommands($list); + } + } + + return $leases; + } + protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) { $where = parent::buildWhereClauseParts($conn); diff --git a/src/applications/drydock/query/DrydockResourceQuery.php b/src/applications/drydock/query/DrydockResourceQuery.php --- a/src/applications/drydock/query/DrydockResourceQuery.php +++ b/src/applications/drydock/query/DrydockResourceQuery.php @@ -8,6 +8,7 @@ private $types; private $blueprintPHIDs; private $datasourceQuery; + private $needUnconsumedCommands; public function withIDs(array $ids) { $this->ids = $ids; @@ -39,6 +40,11 @@ return $this; } + public function needUnconsumedCommands($need) { + $this->needUnconsumedCommands = $need; + return $this; + } + public function newResultObject() { return new DrydockResource(); } @@ -69,6 +75,25 @@ return $resources; } + protected function didFilterPage(array $resources) { + if ($this->needUnconsumedCommands) { + $commands = id(new DrydockCommandQuery()) + ->setViewer($this->getViewer()) + ->setParentQuery($this) + ->withTargetPHIDs(mpull($resources, 'getPHID')) + ->withConsumed(false) + ->execute(); + $commands = mgroup($commands, 'getTargetPHID'); + + foreach ($resources as $resource) { + $list = idx($commands, $resource->getPHID(), array()); + $resource->attachUnconsumedCommands($list); + } + } + + return $resources; + } + protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) { $where = parent::buildWhereClauseParts($conn); diff --git a/src/applications/drydock/storage/DrydockLease.php b/src/applications/drydock/storage/DrydockLease.php --- a/src/applications/drydock/storage/DrydockLease.php +++ b/src/applications/drydock/storage/DrydockLease.php @@ -11,6 +11,8 @@ protected $status = DrydockLeaseStatus::STATUS_PENDING; private $resource = self::ATTACHABLE; + private $unconsumedCommands = self::ATTACHABLE; + private $releaseOnDestruction; private $isAcquired = false; private $isActivated = false; @@ -104,6 +106,25 @@ return ($this->resource !== null); } + public function getUnconsumedCommands() { + return $this->assertAttached($this->unconsumedCommands); + } + + public function attachUnconsumedCommands(array $commands) { + $this->unconsumedCommands = $commands; + return $this; + } + + public function isReleasing() { + foreach ($this->getUnconsumedCommands() as $command) { + if ($command->getCommand() == DrydockCommand::COMMAND_RELEASE) { + return true; + } + } + + return false; + } + public function queueForActivation() { if ($this->getID()) { throw new Exception( diff --git a/src/applications/drydock/storage/DrydockResource.php b/src/applications/drydock/storage/DrydockResource.php --- a/src/applications/drydock/storage/DrydockResource.php +++ b/src/applications/drydock/storage/DrydockResource.php @@ -8,7 +8,6 @@ protected $blueprintPHID; protected $status; protected $until; - protected $type; protected $name; protected $attributes = array(); @@ -16,6 +15,8 @@ protected $ownerPHID; private $blueprint = self::ATTACHABLE; + private $unconsumedCommands = self::ATTACHABLE; + private $isAllocated = false; private $isActivated = false; private $activateWhenAllocated = false; @@ -80,6 +81,25 @@ return $this; } + public function getUnconsumedCommands() { + return $this->assertAttached($this->unconsumedCommands); + } + + public function attachUnconsumedCommands(array $commands) { + $this->unconsumedCommands = $commands; + return $this; + } + + public function isReleasing() { + foreach ($this->getUnconsumedCommands() as $command) { + if ($command->getCommand() == DrydockCommand::COMMAND_RELEASE) { + return true; + } + } + + return false; + } + public function setActivateWhenAllocated($activate) { $this->activateWhenAllocated = $activate; return $this;