Index: resources/sql/autopatches/20140109.ddxactions.sql =================================================================== --- /dev/null +++ resources/sql/autopatches/20140109.ddxactions.sql @@ -0,0 +1,21 @@ +CREATE TABLE {$NAMESPACE}_drydock.drydock_blueprinttransaction ( + id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, + phid VARCHAR(64) NOT NULL COLLATE utf8_bin, + authorPHID VARCHAR(64) NOT NULL COLLATE utf8_bin, + objectPHID VARCHAR(64) NOT NULL COLLATE utf8_bin, + viewPolicy VARCHAR(64) NOT NULL COLLATE utf8_bin, + editPolicy VARCHAR(64) NOT NULL COLLATE utf8_bin, + commentPHID VARCHAR(64) COLLATE utf8_bin, + commentVersion INT UNSIGNED NOT NULL, + transactionType VARCHAR(32) NOT NULL COLLATE utf8_bin, + oldValue LONGTEXT NOT NULL COLLATE utf8_bin, + newValue LONGTEXT NOT NULL COLLATE utf8_bin, + contentSource LONGTEXT NOT NULL COLLATE utf8_bin, + metadata LONGTEXT NOT NULL COLLATE utf8_bin, + dateCreated INT UNSIGNED NOT NULL, + dateModified INT UNSIGNED NOT NULL, + + UNIQUE KEY `key_phid` (phid), + KEY `key_object` (objectPHID) + +) ENGINE=InnoDB, COLLATE utf8_general_ci; Index: src/__phutil_library_map__.php =================================================================== --- src/__phutil_library_map__.php +++ src/__phutil_library_map__.php @@ -647,11 +647,14 @@ 'DrydockBlueprintController' => 'applications/drydock/controller/DrydockBlueprintController.php', 'DrydockBlueprintCreateController' => 'applications/drydock/controller/DrydockBlueprintCreateController.php', 'DrydockBlueprintEditController' => 'applications/drydock/controller/DrydockBlueprintEditController.php', + 'DrydockBlueprintEditor' => 'applications/drydock/editor/DrydockBlueprintEditor.php', 'DrydockBlueprintImplementation' => 'applications/drydock/blueprint/DrydockBlueprintImplementation.php', 'DrydockBlueprintListController' => 'applications/drydock/controller/DrydockBlueprintListController.php', 'DrydockBlueprintQuery' => 'applications/drydock/query/DrydockBlueprintQuery.php', 'DrydockBlueprintScopeGuard' => 'applications/drydock/util/DrydockBlueprintScopeGuard.php', 'DrydockBlueprintSearchEngine' => 'applications/drydock/query/DrydockBlueprintSearchEngine.php', + 'DrydockBlueprintTransaction' => 'applications/drydock/storage/DrydockBlueprintTransaction.php', + 'DrydockBlueprintTransactionQuery' => 'applications/drydock/query/DrydockBlueprintTransactionQuery.php', 'DrydockBlueprintViewController' => 'applications/drydock/controller/DrydockBlueprintViewController.php', 'DrydockCapabilityCreateBlueprints' => 'applications/drydock/capability/DrydockCapabilityCreateBlueprints.php', 'DrydockCapabilityDefaultEdit' => 'applications/drydock/capability/DrydockCapabilityDefaultEdit.php', @@ -3075,6 +3078,7 @@ 'DrydockBlueprintController' => 'DrydockController', 'DrydockBlueprintCreateController' => 'DrydockBlueprintController', 'DrydockBlueprintEditController' => 'DrydockBlueprintController', + 'DrydockBlueprintEditor' => 'PhabricatorApplicationTransactionEditor', 'DrydockBlueprintListController' => array( 0 => 'DrydockBlueprintController', @@ -3082,6 +3086,8 @@ ), 'DrydockBlueprintQuery' => 'DrydockQuery', 'DrydockBlueprintSearchEngine' => 'PhabricatorApplicationSearchEngine', + 'DrydockBlueprintTransaction' => 'PhabricatorApplicationTransaction', + 'DrydockBlueprintTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'DrydockBlueprintViewController' => 'DrydockBlueprintController', 'DrydockCapabilityCreateBlueprints' => 'PhabricatorPolicyCapability', 'DrydockCapabilityDefaultEdit' => 'PhabricatorPolicyCapability', Index: src/applications/drydock/controller/DrydockBlueprintEditController.php =================================================================== --- src/applications/drydock/controller/DrydockBlueprintEditController.php +++ src/applications/drydock/controller/DrydockBlueprintEditController.php @@ -57,13 +57,27 @@ $errors[] = pht('You must name this blueprint.'); } - // TODO: We should use transactions here. - $blueprint->setViewPolicy($v_view_policy); - $blueprint->setEditPolicy($v_edit_policy); - $blueprint->setBlueprintName($v_name); - if (!$errors) { - $blueprint->save(); + $xactions = array(); + + $xactions[] = id(new DrydockBlueprintTransaction()) + ->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY) + ->setNewValue($v_view_policy); + + $xactions[] = id(new DrydockBlueprintTransaction()) + ->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY) + ->setNewValue($v_edit_policy); + + $xactions[] = id(new DrydockBlueprintTransaction()) + ->setTransactionType(DrydockBlueprintTransaction::TYPE_NAME) + ->setNewValue($v_name); + + $editor = id(new DrydockBlueprintEditor()) + ->setActor($viewer) + ->setContentSourceFromRequest($request) + ->setContinueOnNoEffect(true); + + $editor->applyTransactions($blueprint, $xactions); $id = $blueprint->getID(); $save_uri = $this->getApplicationURI("blueprint/{$id}/"); Index: src/applications/drydock/controller/DrydockBlueprintViewController.php =================================================================== --- src/applications/drydock/controller/DrydockBlueprintViewController.php +++ src/applications/drydock/controller/DrydockBlueprintViewController.php @@ -53,11 +53,26 @@ ->setHeader($header) ->addPropertyList($properties); + $xactions = id(new DrydockBlueprintTransactionQuery()) + ->setViewer($viewer) + ->withObjectPHIDs(array($blueprint->getPHID())) + ->execute(); + + $engine = id(new PhabricatorMarkupEngine()) + ->setViewer($viewer); + + $timeline = id(new PhabricatorApplicationTransactionView()) + ->setUser($viewer) + ->setObjectPHID($blueprint->getPHID()) + ->setTransactions($xactions) + ->setMarkupEngine($engine); + return $this->buildApplicationPage( array( $crumbs, $object_box, - $resource_list + $resource_list, + $timeline, ), array( 'device' => true, Index: src/applications/drydock/editor/DrydockBlueprintEditor.php =================================================================== --- /dev/null +++ src/applications/drydock/editor/DrydockBlueprintEditor.php @@ -0,0 +1,65 @@ +getTransactionType()) { + case DrydockBlueprintTransaction::TYPE_NAME: + return $object->getBlueprintName(); + } + } + + protected function getCustomTransactionNewValue( + PhabricatorLiskDAO $object, + PhabricatorApplicationTransaction $xaction) { + + switch ($xaction->getTransactionType()) { + case DrydockBlueprintTransaction::TYPE_NAME: + return $xaction->getNewValue(); + } + } + + protected function applyCustomInternalTransaction( + PhabricatorLiskDAO $object, + PhabricatorApplicationTransaction $xaction) { + + switch ($xaction->getTransactionType()) { + case DrydockBlueprintTransaction::TYPE_NAME: + $object->setBlueprintName($xaction->getNewValue()); + break; + } + } + + protected function applyCustomExternalTransaction( + PhabricatorLiskDAO $object, + PhabricatorApplicationTransaction $xaction) { + return; + } + + protected function extractFilePHIDsFromCustomTransaction( + PhabricatorLiskDAO $object, + PhabricatorApplicationTransaction $xaction) { + return array(); + } + + protected function shouldSendMail( + PhabricatorLiskDAO $object, + array $xactions) { + return false; + } + +} Index: src/applications/drydock/query/DrydockBlueprintTransactionQuery.php =================================================================== --- /dev/null +++ src/applications/drydock/query/DrydockBlueprintTransactionQuery.php @@ -0,0 +1,10 @@ +getOldValue(); + $new = $this->getNewValue(); + $author_handle = $this->renderHandleLink($this->getAuthorPHID()); + + switch ($this->getTransactionType()) { + case self::TYPE_NAME: + if (!strlen($old)) { + return pht( + '%s created this blueprint.', + $author_handle); + } else { + return pht( + '%s renamed this blueprint from "%s" to "%s".', + $author_handle, + $old, + $new); + } + } + + return parent::getTitle(); + } + +}