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 19

This commit is contained in:
epriestley 2017-05-14 15:09:23 -07:00
commit 6c211317fc
83 changed files with 1272 additions and 1205 deletions

View file

@ -1138,9 +1138,9 @@ phutil_register_library_map(array(
'FundInitiativeBackController' => 'applications/fund/controller/FundInitiativeBackController.php',
'FundInitiativeBackerTransaction' => 'applications/fund/xaction/FundInitiativeBackerTransaction.php',
'FundInitiativeCloseController' => 'applications/fund/controller/FundInitiativeCloseController.php',
'FundInitiativeCommentController' => 'applications/fund/controller/FundInitiativeCommentController.php',
'FundInitiativeDescriptionTransaction' => 'applications/fund/xaction/FundInitiativeDescriptionTransaction.php',
'FundInitiativeEditController' => 'applications/fund/controller/FundInitiativeEditController.php',
'FundInitiativeEditEngine' => 'applications/fund/editor/FundInitiativeEditEngine.php',
'FundInitiativeEditor' => 'applications/fund/editor/FundInitiativeEditor.php',
'FundInitiativeFulltextEngine' => 'applications/fund/search/FundInitiativeFulltextEngine.php',
'FundInitiativeListController' => 'applications/fund/controller/FundInitiativeListController.php',
@ -1404,10 +1404,10 @@ phutil_register_library_map(array(
'LegalpadDefaultViewCapability' => 'applications/legalpad/capability/LegalpadDefaultViewCapability.php',
'LegalpadDocument' => 'applications/legalpad/storage/LegalpadDocument.php',
'LegalpadDocumentBody' => 'applications/legalpad/storage/LegalpadDocumentBody.php',
'LegalpadDocumentCommentController' => 'applications/legalpad/controller/LegalpadDocumentCommentController.php',
'LegalpadDocumentDatasource' => 'applications/legalpad/typeahead/LegalpadDocumentDatasource.php',
'LegalpadDocumentDoneController' => 'applications/legalpad/controller/LegalpadDocumentDoneController.php',
'LegalpadDocumentEditController' => 'applications/legalpad/controller/LegalpadDocumentEditController.php',
'LegalpadDocumentEditEngine' => 'applications/legalpad/editor/LegalpadDocumentEditEngine.php',
'LegalpadDocumentEditor' => 'applications/legalpad/editor/LegalpadDocumentEditor.php',
'LegalpadDocumentListController' => 'applications/legalpad/controller/LegalpadDocumentListController.php',
'LegalpadDocumentManageController' => 'applications/legalpad/controller/LegalpadDocumentManageController.php',
@ -1451,6 +1451,7 @@ phutil_register_library_map(array(
'LiskRawMigrationIterator' => 'infrastructure/storage/lisk/LiskRawMigrationIterator.php',
'MacroConduitAPIMethod' => 'applications/macro/conduit/MacroConduitAPIMethod.php',
'MacroCreateMemeConduitAPIMethod' => 'applications/macro/conduit/MacroCreateMemeConduitAPIMethod.php',
'MacroEditConduitAPIMethod' => 'applications/macro/conduit/MacroEditConduitAPIMethod.php',
'MacroEmojiExample' => 'applications/uiexample/examples/MacroEmojiExample.php',
'MacroQueryConduitAPIMethod' => 'applications/macro/conduit/MacroQueryConduitAPIMethod.php',
'ManiphestAssignEmailCommand' => 'applications/maniphest/command/ManiphestAssignEmailCommand.php',
@ -3633,6 +3634,7 @@ phutil_register_library_map(array(
'PhabricatorProjectOrUserDatasource' => 'applications/project/typeahead/PhabricatorProjectOrUserDatasource.php',
'PhabricatorProjectOrUserFunctionDatasource' => 'applications/project/typeahead/PhabricatorProjectOrUserFunctionDatasource.php',
'PhabricatorProjectPHIDResolver' => 'applications/phid/resolver/PhabricatorProjectPHIDResolver.php',
'PhabricatorProjectPictureProfileMenuItem' => 'applications/project/menuitem/PhabricatorProjectPictureProfileMenuItem.php',
'PhabricatorProjectPointsProfileMenuItem' => 'applications/project/menuitem/PhabricatorProjectPointsProfileMenuItem.php',
'PhabricatorProjectProfileController' => 'applications/project/controller/PhabricatorProjectProfileController.php',
'PhabricatorProjectProfileMenuEngine' => 'applications/project/engine/PhabricatorProjectProfileMenuEngine.php',
@ -3912,12 +3914,12 @@ phutil_register_library_map(array(
'PhabricatorSlowvoteApplication' => 'applications/slowvote/application/PhabricatorSlowvoteApplication.php',
'PhabricatorSlowvoteChoice' => 'applications/slowvote/storage/PhabricatorSlowvoteChoice.php',
'PhabricatorSlowvoteCloseController' => 'applications/slowvote/controller/PhabricatorSlowvoteCloseController.php',
'PhabricatorSlowvoteCloseTransaction' => 'applications/slowvote/xactions/PhabricatorSlowvoteCloseTransaction.php',
'PhabricatorSlowvoteCloseTransaction' => 'applications/slowvote/xaction/PhabricatorSlowvoteCloseTransaction.php',
'PhabricatorSlowvoteCommentController' => 'applications/slowvote/controller/PhabricatorSlowvoteCommentController.php',
'PhabricatorSlowvoteController' => 'applications/slowvote/controller/PhabricatorSlowvoteController.php',
'PhabricatorSlowvoteDAO' => 'applications/slowvote/storage/PhabricatorSlowvoteDAO.php',
'PhabricatorSlowvoteDefaultViewCapability' => 'applications/slowvote/capability/PhabricatorSlowvoteDefaultViewCapability.php',
'PhabricatorSlowvoteDescriptionTransaction' => 'applications/slowvote/xactions/PhabricatorSlowvoteDescriptionTransaction.php',
'PhabricatorSlowvoteDescriptionTransaction' => 'applications/slowvote/xaction/PhabricatorSlowvoteDescriptionTransaction.php',
'PhabricatorSlowvoteEditController' => 'applications/slowvote/controller/PhabricatorSlowvoteEditController.php',
'PhabricatorSlowvoteEditor' => 'applications/slowvote/editor/PhabricatorSlowvoteEditor.php',
'PhabricatorSlowvoteListController' => 'applications/slowvote/controller/PhabricatorSlowvoteListController.php',
@ -3927,16 +3929,16 @@ phutil_register_library_map(array(
'PhabricatorSlowvotePollController' => 'applications/slowvote/controller/PhabricatorSlowvotePollController.php',
'PhabricatorSlowvotePollPHIDType' => 'applications/slowvote/phid/PhabricatorSlowvotePollPHIDType.php',
'PhabricatorSlowvoteQuery' => 'applications/slowvote/query/PhabricatorSlowvoteQuery.php',
'PhabricatorSlowvoteQuestionTransaction' => 'applications/slowvote/xactions/PhabricatorSlowvoteQuestionTransaction.php',
'PhabricatorSlowvoteQuestionTransaction' => 'applications/slowvote/xaction/PhabricatorSlowvoteQuestionTransaction.php',
'PhabricatorSlowvoteReplyHandler' => 'applications/slowvote/mail/PhabricatorSlowvoteReplyHandler.php',
'PhabricatorSlowvoteResponsesTransaction' => 'applications/slowvote/xactions/PhabricatorSlowvoteResponsesTransaction.php',
'PhabricatorSlowvoteResponsesTransaction' => 'applications/slowvote/xaction/PhabricatorSlowvoteResponsesTransaction.php',
'PhabricatorSlowvoteSchemaSpec' => 'applications/slowvote/storage/PhabricatorSlowvoteSchemaSpec.php',
'PhabricatorSlowvoteSearchEngine' => 'applications/slowvote/query/PhabricatorSlowvoteSearchEngine.php',
'PhabricatorSlowvoteShuffleTransaction' => 'applications/slowvote/xactions/PhabricatorSlowvoteShuffleTransaction.php',
'PhabricatorSlowvoteShuffleTransaction' => 'applications/slowvote/xaction/PhabricatorSlowvoteShuffleTransaction.php',
'PhabricatorSlowvoteTransaction' => 'applications/slowvote/storage/PhabricatorSlowvoteTransaction.php',
'PhabricatorSlowvoteTransactionComment' => 'applications/slowvote/storage/PhabricatorSlowvoteTransactionComment.php',
'PhabricatorSlowvoteTransactionQuery' => 'applications/slowvote/query/PhabricatorSlowvoteTransactionQuery.php',
'PhabricatorSlowvoteTransactionType' => 'applications/slowvote/xactions/PhabricatorSlowvoteTransactionType.php',
'PhabricatorSlowvoteTransactionType' => 'applications/slowvote/xaction/PhabricatorSlowvoteTransactionType.php',
'PhabricatorSlowvoteVoteController' => 'applications/slowvote/controller/PhabricatorSlowvoteVoteController.php',
'PhabricatorSlug' => 'infrastructure/util/PhabricatorSlug.php',
'PhabricatorSlugTestCase' => 'infrastructure/util/__tests__/PhabricatorSlugTestCase.php',
@ -4358,8 +4360,11 @@ phutil_register_library_map(array(
'PholioDefaultEditCapability' => 'applications/pholio/capability/PholioDefaultEditCapability.php',
'PholioDefaultViewCapability' => 'applications/pholio/capability/PholioDefaultViewCapability.php',
'PholioImage' => 'applications/pholio/storage/PholioImage.php',
'PholioImageDescriptionTransaction' => 'applications/pholio/xaction/PholioImageDescriptionTransaction.php',
'PholioImageNameTransaction' => 'applications/pholio/xaction/PholioImageNameTransaction.php',
'PholioImagePHIDType' => 'applications/pholio/phid/PholioImagePHIDType.php',
'PholioImageQuery' => 'applications/pholio/query/PholioImageQuery.php',
'PholioImageTransactionType' => 'applications/pholio/xaction/PholioImageTransactionType.php',
'PholioImageUploadController' => 'applications/pholio/controller/PholioImageUploadController.php',
'PholioInlineController' => 'applications/pholio/controller/PholioInlineController.php',
'PholioInlineListController' => 'applications/pholio/controller/PholioInlineListController.php',
@ -4368,6 +4373,7 @@ phutil_register_library_map(array(
'PholioMockAuthorHeraldField' => 'applications/pholio/herald/PholioMockAuthorHeraldField.php',
'PholioMockCommentController' => 'applications/pholio/controller/PholioMockCommentController.php',
'PholioMockDescriptionHeraldField' => 'applications/pholio/herald/PholioMockDescriptionHeraldField.php',
'PholioMockDescriptionTransaction' => 'applications/pholio/xaction/PholioMockDescriptionTransaction.php',
'PholioMockEditController' => 'applications/pholio/controller/PholioMockEditController.php',
'PholioMockEditor' => 'applications/pholio/editor/PholioMockEditor.php',
'PholioMockEmbedView' => 'applications/pholio/view/PholioMockEmbedView.php',
@ -4380,12 +4386,15 @@ phutil_register_library_map(array(
'PholioMockListController' => 'applications/pholio/controller/PholioMockListController.php',
'PholioMockMailReceiver' => 'applications/pholio/mail/PholioMockMailReceiver.php',
'PholioMockNameHeraldField' => 'applications/pholio/herald/PholioMockNameHeraldField.php',
'PholioMockNameTransaction' => 'applications/pholio/xaction/PholioMockNameTransaction.php',
'PholioMockPHIDType' => 'applications/pholio/phid/PholioMockPHIDType.php',
'PholioMockQuery' => 'applications/pholio/query/PholioMockQuery.php',
'PholioMockRelationship' => 'applications/pholio/relationships/PholioMockRelationship.php',
'PholioMockRelationshipSource' => 'applications/search/relationship/PholioMockRelationshipSource.php',
'PholioMockSearchEngine' => 'applications/pholio/query/PholioMockSearchEngine.php',
'PholioMockStatusTransaction' => 'applications/pholio/xaction/PholioMockStatusTransaction.php',
'PholioMockThumbGridView' => 'applications/pholio/view/PholioMockThumbGridView.php',
'PholioMockTransactionType' => 'applications/pholio/xaction/PholioMockTransactionType.php',
'PholioMockViewController' => 'applications/pholio/controller/PholioMockViewController.php',
'PholioRemarkupRule' => 'applications/pholio/remarkup/PholioRemarkupRule.php',
'PholioReplyHandler' => 'applications/pholio/mail/PholioReplyHandler.php',
@ -4393,6 +4402,7 @@ phutil_register_library_map(array(
'PholioTransaction' => 'applications/pholio/storage/PholioTransaction.php',
'PholioTransactionComment' => 'applications/pholio/storage/PholioTransactionComment.php',
'PholioTransactionQuery' => 'applications/pholio/query/PholioTransactionQuery.php',
'PholioTransactionType' => 'applications/pholio/xaction/PholioTransactionType.php',
'PholioTransactionView' => 'applications/pholio/view/PholioTransactionView.php',
'PholioUploadedImageView' => 'applications/pholio/view/PholioUploadedImageView.php',
'PhortuneAccount' => 'applications/phortune/storage/PhortuneAccount.php',
@ -6102,9 +6112,9 @@ phutil_register_library_map(array(
'FundInitiativeBackController' => 'FundController',
'FundInitiativeBackerTransaction' => 'FundInitiativeTransactionType',
'FundInitiativeCloseController' => 'FundController',
'FundInitiativeCommentController' => 'FundController',
'FundInitiativeDescriptionTransaction' => 'FundInitiativeTransactionType',
'FundInitiativeEditController' => 'FundController',
'FundInitiativeEditEngine' => 'PhabricatorEditEngine',
'FundInitiativeEditor' => 'PhabricatorApplicationTransactionEditor',
'FundInitiativeFulltextEngine' => 'PhabricatorFulltextEngine',
'FundInitiativeListController' => 'FundController',
@ -6427,10 +6437,10 @@ phutil_register_library_map(array(
'LegalpadDAO',
'PhabricatorMarkupInterface',
),
'LegalpadDocumentCommentController' => 'LegalpadController',
'LegalpadDocumentDatasource' => 'PhabricatorTypeaheadDatasource',
'LegalpadDocumentDoneController' => 'LegalpadController',
'LegalpadDocumentEditController' => 'LegalpadController',
'LegalpadDocumentEditEngine' => 'PhabricatorEditEngine',
'LegalpadDocumentEditor' => 'PhabricatorApplicationTransactionEditor',
'LegalpadDocumentListController' => 'LegalpadController',
'LegalpadDocumentManageController' => 'LegalpadController',
@ -6477,6 +6487,7 @@ phutil_register_library_map(array(
'LiskRawMigrationIterator' => 'PhutilBufferedIterator',
'MacroConduitAPIMethod' => 'ConduitAPIMethod',
'MacroCreateMemeConduitAPIMethod' => 'MacroConduitAPIMethod',
'MacroEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod',
'MacroEmojiExample' => 'PhabricatorUIExample',
'MacroQueryConduitAPIMethod' => 'MacroConduitAPIMethod',
'ManiphestAssignEmailCommand' => 'ManiphestEmailCommand',
@ -9010,6 +9021,7 @@ phutil_register_library_map(array(
'PhabricatorProjectOrUserDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
'PhabricatorProjectOrUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
'PhabricatorProjectPHIDResolver' => 'PhabricatorPHIDResolver',
'PhabricatorProjectPictureProfileMenuItem' => 'PhabricatorProfileMenuItem',
'PhabricatorProjectPointsProfileMenuItem' => 'PhabricatorProfileMenuItem',
'PhabricatorProjectProfileController' => 'PhabricatorProjectController',
'PhabricatorProjectProfileMenuEngine' => 'PhabricatorProfileMenuEngine',
@ -9895,8 +9907,11 @@ phutil_register_library_map(array(
'PhabricatorMarkupInterface',
'PhabricatorPolicyInterface',
),
'PholioImageDescriptionTransaction' => 'PholioImageTransactionType',
'PholioImageNameTransaction' => 'PholioImageTransactionType',
'PholioImagePHIDType' => 'PhabricatorPHIDType',
'PholioImageQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PholioImageTransactionType' => 'PholioTransactionType',
'PholioImageUploadController' => 'PholioController',
'PholioInlineController' => 'PholioController',
'PholioInlineListController' => 'PholioController',
@ -9918,6 +9933,7 @@ phutil_register_library_map(array(
'PholioMockAuthorHeraldField' => 'PholioMockHeraldField',
'PholioMockCommentController' => 'PholioController',
'PholioMockDescriptionHeraldField' => 'PholioMockHeraldField',
'PholioMockDescriptionTransaction' => 'PholioMockTransactionType',
'PholioMockEditController' => 'PholioController',
'PholioMockEditor' => 'PhabricatorApplicationTransactionEditor',
'PholioMockEmbedView' => 'AphrontView',
@ -9930,19 +9946,23 @@ phutil_register_library_map(array(
'PholioMockListController' => 'PholioController',
'PholioMockMailReceiver' => 'PhabricatorObjectMailReceiver',
'PholioMockNameHeraldField' => 'PholioMockHeraldField',
'PholioMockNameTransaction' => 'PholioMockTransactionType',
'PholioMockPHIDType' => 'PhabricatorPHIDType',
'PholioMockQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PholioMockRelationship' => 'PhabricatorObjectRelationship',
'PholioMockRelationshipSource' => 'PhabricatorObjectRelationshipSource',
'PholioMockSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PholioMockStatusTransaction' => 'PholioMockTransactionType',
'PholioMockThumbGridView' => 'AphrontView',
'PholioMockTransactionType' => 'PholioTransactionType',
'PholioMockViewController' => 'PholioController',
'PholioRemarkupRule' => 'PhabricatorObjectRemarkupRule',
'PholioReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler',
'PholioSchemaSpec' => 'PhabricatorConfigSchemaSpec',
'PholioTransaction' => 'PhabricatorApplicationTransaction',
'PholioTransaction' => 'PhabricatorModularTransaction',
'PholioTransactionComment' => 'PhabricatorApplicationTransactionComment',
'PholioTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PholioTransactionType' => 'PhabricatorModularTransactionType',
'PholioTransactionView' => 'PhabricatorApplicationTransactionView',
'PholioUploadedImageView' => 'AphrontView',
'PhortuneAccount' => array(

View file

@ -7,10 +7,17 @@ final class AphrontFileHTTPParameterType
return $key.'_raw';
}
private function getDefaultKey($key) {
return $key.'_default';
}
protected function getParameterExists(AphrontRequest $request, $key) {
$file_key = $this->getFileKey($key);
$default_key = $this->getDefaultKey($key);
return $request->getExists($key) ||
$request->getFileExists($file_key);
$request->getFileExists($file_key) ||
$request->getExists($default_key);
}
protected function getParameterValue(AphrontRequest $request, $key) {
@ -27,8 +34,9 @@ final class AphrontFileHTTPParameterType
// this code around as a fallback if the client-side JS goes awry.
$file_key = $this->getFileKey($key);
$default_key = $this->getDefaultKey($key);
if (!$request->getFileExists($file_key)) {
return null;
return $request->getStr($default_key);
}
$viewer = $this->getViewer();

View file

@ -2,7 +2,7 @@
final class PhabricatorAuditListView extends AphrontView {
private $commits;
private $commits = array();
private $header;
private $showDrafts;
private $noDataString;

View file

@ -642,7 +642,7 @@ abstract class PhabricatorApplication
public function getApplicationTransactionEditor() {
return new PhutilMethodNotImplementedException(pht('Coming Soon!'));
return new PhabricatorApplicationEditor();
}
public function getApplicationTransactionObject() {

View file

@ -5,7 +5,7 @@
*/
final class DifferentialRevisionListView extends AphrontView {
private $revisions;
private $revisions = array();
private $handles;
private $header;
private $noDataString;

View file

@ -42,8 +42,8 @@ final class PhabricatorFundApplication extends PhabricatorApplication {
'/fund/' => array(
'(?:query/(?P<queryKey>[^/]+)/)?' => 'FundInitiativeListController',
'create/' => 'FundInitiativeEditController',
'comment/(?P<id>[1-9]\d*)/' => 'FundInitiativeCommentController',
'edit/(?:(?P<id>\d+)/)?' => 'FundInitiativeEditController',
$this->getEditRoutePattern('edit/')
=> 'FundInitiativeEditController',
'close/(?P<id>\d+)/' => 'FundInitiativeCloseController',
'back/(?P<id>\d+)/' => 'FundInitiativeBackController',
'backers/(?:(?P<id>\d+)/)?(?:query/(?P<queryKey>[^/]+)/)?'

View file

@ -1,63 +0,0 @@
<?php
final class FundInitiativeCommentController
extends FundController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$id = $request->getURIData('id');
if (!$request->isFormPost()) {
return new Aphront400Response();
}
$initiative = id(new FundInitiativeQuery())
->setViewer($viewer)
->withIDs(array($id))
->executeOne();
if (!$initiative) {
return new Aphront404Response();
}
$is_preview = $request->isPreviewRequest();
$draft = PhabricatorDraft::buildFromRequest($request);
$view_uri = '/'.$initiative->getMonogram();
$xactions = array();
$xactions[] = id(new FundInitiativeTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_COMMENT)
->attachComment(
id(new FundInitiativeTransactionComment())
->setContent($request->getStr('comment')));
$editor = id(new FundInitiativeEditor())
->setActor($viewer)
->setContinueOnNoEffect($request->isContinueRequest())
->setContentSourceFromRequest($request)
->setIsPreview($is_preview);
try {
$xactions = $editor->applyTransactions($initiative, $xactions);
} catch (PhabricatorApplicationTransactionNoEffectException $ex) {
return id(new PhabricatorApplicationTransactionNoEffectResponse())
->setCancelURI($view_uri)
->setException($ex);
}
if ($draft) {
$draft->replaceOrDelete();
}
if ($request->isAjax() && $is_preview) {
return id(new PhabricatorApplicationTransactionResponse())
->setViewer($viewer)
->setTransactions($xactions)
->setIsPreview($is_preview);
} else {
return id(new AphrontRedirectResponse())
->setURI($view_uri);
}
}
}

View file

@ -1,256 +1,11 @@
<?php
final class FundInitiativeEditController
extends FundController {
final class FundInitiativeEditController extends
FundController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$id = $request->getURIData('id');
if ($id) {
$initiative = id(new FundInitiativeQuery())
->setViewer($viewer)
->withIDs(array($id))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$initiative) {
return new Aphront404Response();
}
$is_new = false;
} else {
$initiative = FundInitiative::initializeNewInitiative($viewer);
$is_new = true;
}
if ($is_new) {
$title = pht('Create Initiative');
$button_text = pht('Create Initiative');
$cancel_uri = $this->getApplicationURI();
$header_icon = 'fa-plus-square';
} else {
$title = pht(
'Edit Initiative: %s',
$initiative->getName());
$button_text = pht('Save Changes');
$cancel_uri = '/'.$initiative->getMonogram();
$header_icon = 'fa-pencil';
}
$e_name = true;
$v_name = $initiative->getName();
$e_merchant = null;
$v_merchant = $initiative->getMerchantPHID();
$v_desc = $initiative->getDescription();
$v_risk = $initiative->getRisks();
if ($is_new) {
$v_projects = array();
} else {
$v_projects = PhabricatorEdgeQuery::loadDestinationPHIDs(
$initiative->getPHID(),
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST);
$v_projects = array_reverse($v_projects);
}
$validation_exception = null;
if ($request->isFormPost()) {
$v_name = $request->getStr('name');
$v_desc = $request->getStr('description');
$v_risk = $request->getStr('risks');
$v_view = $request->getStr('viewPolicy');
$v_edit = $request->getStr('editPolicy');
$v_merchant = $request->getStr('merchantPHID');
$v_projects = $request->getArr('projects');
$type_name = FundInitiativeNameTransaction::TRANSACTIONTYPE;
$type_desc = FundInitiativeDescriptionTransaction::TRANSACTIONTYPE;
$type_risk = FundInitiativeRisksTransaction::TRANSACTIONTYPE;
$type_merchant = FundInitiativeMerchantTransaction::TRANSACTIONTYPE;
$type_view = PhabricatorTransactions::TYPE_VIEW_POLICY;
$type_edit = PhabricatorTransactions::TYPE_EDIT_POLICY;
$xactions = array();
$xactions[] = id(new FundInitiativeTransaction())
->setTransactionType($type_name)
->setNewValue($v_name);
$xactions[] = id(new FundInitiativeTransaction())
->setTransactionType($type_desc)
->setNewValue($v_desc);
$xactions[] = id(new FundInitiativeTransaction())
->setTransactionType($type_risk)
->setNewValue($v_risk);
$xactions[] = id(new FundInitiativeTransaction())
->setTransactionType($type_merchant)
->setNewValue($v_merchant);
$xactions[] = id(new FundInitiativeTransaction())
->setTransactionType($type_view)
->setNewValue($v_view);
$xactions[] = id(new FundInitiativeTransaction())
->setTransactionType($type_edit)
->setNewValue($v_edit);
$proj_edge_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST;
$xactions[] = id(new FundInitiativeTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
->setMetadataValue('edge:type', $proj_edge_type)
->setNewValue(array('=' => array_fuse($v_projects)));
$editor = id(new FundInitiativeEditor())
->setActor($viewer)
->setContentSourceFromRequest($request)
->setContinueOnNoEffect(true);
try {
$editor->applyTransactions($initiative, $xactions);
return id(new AphrontRedirectResponse())
->setURI('/'.$initiative->getMonogram());
} catch (PhabricatorApplicationTransactionValidationException $ex) {
$validation_exception = $ex;
$e_name = $ex->getShortMessage($type_name);
$e_merchant = $ex->getShortMessage($type_merchant);
$initiative->setViewPolicy($v_view);
$initiative->setEditPolicy($v_edit);
}
}
$policies = id(new PhabricatorPolicyQuery())
->setViewer($viewer)
->setObject($initiative)
->execute();
$merchants = id(new PhortuneMerchantQuery())
->setViewer($viewer)
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->execute();
$merchant_options = array();
foreach ($merchants as $merchant) {
$merchant_options[$merchant->getPHID()] = pht(
'Merchant %d %s',
$merchant->getID(),
$merchant->getName());
}
if ($v_merchant && empty($merchant_options[$v_merchant])) {
$merchant_options = array(
$v_merchant => pht('(Restricted Merchant)'),
) + $merchant_options;
}
if (!$merchant_options) {
return $this->newDialog()
->setTitle(pht('No Valid Phortune Merchant Accounts'))
->appendParagraph(
pht(
'You do not control any merchant accounts which can receive '.
'payments from this initiative. When you create an initiative, '.
'you need to specify a merchant account where funds will be paid '.
'to.'))
->appendParagraph(
pht(
'Create a merchant account in the Phortune application before '.
'creating an initiative in Fund.'))
->addCancelButton($this->getApplicationURI());
}
$form = id(new AphrontFormView())
->setUser($viewer)
->appendChild(
id(new AphrontFormTextControl())
->setName('name')
->setLabel(pht('Name'))
->setValue($v_name)
->setError($e_name))
->appendChild(
id(new AphrontFormSelectControl())
->setName('merchantPHID')
->setLabel(pht('Pay To Merchant'))
->setValue($v_merchant)
->setError($e_merchant)
->setOptions($merchant_options))
->appendChild(
id(new PhabricatorRemarkupControl())
->setUser($viewer)
->setName('description')
->setLabel(pht('Description'))
->setValue($v_desc))
->appendChild(
id(new PhabricatorRemarkupControl())
->setUser($viewer)
->setName('risks')
->setLabel(pht('Risks/Challenges'))
->setValue($v_risk))
->appendControl(
id(new AphrontFormTokenizerControl())
->setLabel(pht('Tags'))
->setName('projects')
->setValue($v_projects)
->setDatasource(new PhabricatorProjectDatasource()))
->appendChild(
id(new AphrontFormPolicyControl())
->setName('viewPolicy')
->setPolicyObject($initiative)
->setCapability(PhabricatorPolicyCapability::CAN_VIEW)
->setPolicies($policies))
->appendChild(
id(new AphrontFormPolicyControl())
->setName('editPolicy')
->setPolicyObject($initiative)
->setCapability(PhabricatorPolicyCapability::CAN_EDIT)
->setPolicies($policies))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue($button_text)
->addCancelButton($cancel_uri));
$crumbs = $this->buildApplicationCrumbs();
if ($is_new) {
$crumbs->addTextCrumb(pht('Create Initiative'));
} else {
$crumbs->addTextCrumb(
$initiative->getMonogram(),
'/'.$initiative->getMonogram());
$crumbs->addTextCrumb(pht('Edit'));
}
$crumbs->setBorder(true);
$box = id(new PHUIObjectBoxView())
->setValidationException($validation_exception)
->setHeaderText(pht('Initiative'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->appendChild($form);
$header = id(new PHUIHeaderView())
->setHeader($title)
->setHeaderIcon($header_icon);
$view = id(new PHUITwoColumnView())
->setHeader($header)
->setFooter($box);
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->appendChild($view);
return id(new FundInitiativeEditEngine())
->setController($this)
->buildResponse();
}
}

View file

@ -52,15 +52,16 @@ final class FundInitiativeViewController
$timeline = $this->buildTransactionTimeline(
$initiative,
new FundInitiativeTransactionQuery());
$timeline->setQuoteRef($initiative->getMonogram());
$add_comment = $this->buildCommentForm($initiative);
$comment_view = $this->buildCommentForm($initiative, $timeline);
$view = id(new PHUITwoColumnView())
->setHeader($header)
->setCurtain($curtain)
->setMainColumn(array(
$timeline,
$add_comment,
$comment_view,
))
->addPropertySection(pht('Details'), $details);
@ -164,26 +165,14 @@ final class FundInitiativeViewController
return $curtain;
}
private function buildCommentForm(FundInitiative $initiative) {
private function buildCommentForm(FundInitiative $initiative, $timeline) {
$viewer = $this->getViewer();
$box = id(new FundInitiativeEditEngine())
->setViewer($viewer)
->buildEditEngineCommentView($initiative)
->setTransactionTimeline($timeline);
$is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
$add_comment_header = $is_serious
? pht('Add Comment')
: pht('Add Liquidity');
$draft = PhabricatorDraft::newFromUserAndKey(
$viewer, $initiative->getPHID());
return id(new PhabricatorApplicationTransactionCommentView())
->setUser($viewer)
->setObjectPHID($initiative->getPHID())
->setDraft($draft)
->setHeaderText($add_comment_header)
->setAction(
$this->getApplicationURI('/comment/'.$initiative->getID().'/'))
->setSubmitButtonName(pht('Add Comment'));
return $box;
}

View file

@ -0,0 +1,152 @@
<?php
final class FundInitiativeEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'fund.initiative';
public function getEngineName() {
return pht('Fund');
}
public function getEngineApplicationClass() {
return 'PhabricatorFundApplication';
}
public function getSummaryHeader() {
return pht('Configure Fund Forms');
}
public function getSummaryText() {
return pht('Configure creation and editing forms in Fund.');
}
public function isEngineConfigurable() {
return false;
}
protected function newEditableObject() {
return FundInitiative::initializeNewInitiative($this->getViewer());
}
protected function newObjectQuery() {
return new FundInitiativeQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create New Initiative');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Initiative: %s', $object->getName());
}
protected function getObjectEditShortText($object) {
return $object->getName();
}
protected function getObjectCreateShortText() {
return pht('Create Initiative');
}
protected function getObjectName() {
return pht('Initivative');
}
protected function getObjectCreateCancelURI($object) {
return $this->getApplication()->getApplicationURI('/');
}
protected function getEditorURI() {
return $this->getApplication()->getApplicationURI('edit/');
}
protected function getObjectViewURI($object) {
return $object->getViewURI();
}
protected function getCreateNewObjectPolicy() {
return $this->getApplication()->getPolicy(
FundCreateInitiativesCapability::CAPABILITY);
}
protected function buildCustomEditFields($object) {
$viewer = $this->getViewer();
$v_merchant = $object->getMerchantPHID();
$merchants = id(new PhortuneMerchantQuery())
->setViewer($viewer)
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->execute();
$merchant_options = array();
foreach ($merchants as $merchant) {
$merchant_options[$merchant->getPHID()] = pht(
'Merchant %d %s',
$merchant->getID(),
$merchant->getName());
}
if ($v_merchant && empty($merchant_options[$v_merchant])) {
$merchant_options = array(
$v_merchant => pht('(Restricted Merchant)'),
) + $merchant_options;
}
$merchant_instructions = null;
if (!$merchant_options) {
$merchant_instructions = pht(
'NOTE: You do not control any merchant accounts which can receive '.
'payments from this initiative. When you create an initiative, '.
'you need to specify a merchant account where funds will be paid '.
'to. Create a merchant account in the Phortune application before '.
'creating an initiative in Fund.');
}
return array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setDescription(pht('Initiative name.'))
->setConduitTypeDescription(pht('New initiative name.'))
->setTransactionType(
FundInitiativeNameTransaction::TRANSACTIONTYPE)
->setValue($object->getName())
->setIsRequired(true),
id(new PhabricatorSelectEditField())
->setKey('merchantPHID')
->setLabel(pht('Merchant'))
->setDescription(pht('Merchant operating the initiative.'))
->setConduitTypeDescription(pht('New initiative merchant.'))
->setControlInstructions($merchant_instructions)
->setValue($object->getMerchantPHID())
->setTransactionType(
FundInitiativeMerchantTransaction::TRANSACTIONTYPE)
->setOptions($merchant_options)
->setIsRequired(true),
id(new PhabricatorRemarkupEditField())
->setKey('description')
->setLabel(pht('Description'))
->setDescription(pht('Initiative long description.'))
->setConduitTypeDescription(pht('New initiative description.'))
->setTransactionType(
FundInitiativeDescriptionTransaction::TRANSACTIONTYPE)
->setValue($object->getDescription()),
id(new PhabricatorRemarkupEditField())
->setKey('risks')
->setLabel(pht('Risks/Challenges'))
->setDescription(pht('Initiative risks and challenges.'))
->setConduitTypeDescription(pht('Initiative risks and challenges.'))
->setTransactionType(
FundInitiativeRisksTransaction::TRANSACTIONTYPE)
->setValue($object->getRisks()),
);
}
}

View file

@ -126,6 +126,7 @@ final class FundBackerSearchEngine
}
$table = id(new AphrontTableView($rows))
->setNoDataString(pht('No backers found.'))
->setHeaders(
array(
pht('Initiative'),

View file

@ -85,6 +85,10 @@ final class FundInitiative extends FundDAO
return 'I'.$this->getID();
}
public function getViewURI() {
return '/'.$this->getMonogram();
}
public function getProjectPHIDs() {
return $this->assertAttached($this->projectPHIDs);
}

View file

@ -45,7 +45,7 @@ final class FundInitiativeMerchantTransaction
return pht(
'%s changed the merchant receiving funds from %s '.
'initiative from %s to %s.',
'from %s to %s.',
$this->renderAuthor(),
$this->renderObject(),
$old_merchant,

View file

@ -37,7 +37,7 @@ final class FundInitiativeNameTransaction
$this->renderObject());
} else {
return pht(
'%s renamed %s initiative from %s to %s.',
'%s renamed %s from %s to %s.',
$this->renderAuthor(),
$this->renderObject(),
$this->renderOldValue(),

View file

@ -55,7 +55,7 @@ final class FundInitiativeRefundTransaction
'%s refunded %s to %s.',
$this->renderAuthor(),
$amount->formatForDisplay(),
$this->renderHandleLink($backer_phid));
$this->renderHandle($backer_phid));
}
public function getTitleForFeed() {
@ -69,7 +69,7 @@ final class FundInitiativeRefundTransaction
'%s refunded %s to %s for %s.',
$this->renderAuthor(),
$amount->formatForDisplay(),
$this->renderHandleLink($backer_phid),
$this->renderHandle($backer_phid),
$this->renderObject());
}

View file

@ -28,12 +28,12 @@ final class FundInitiativeStatusTransaction
public function getTitleForFeed() {
if ($this->getNewValue() == FundInitiative::STATUS_CLOSED) {
return pht(
'%s closed the initiative %s.',
'%s closed %s.',
$this->renderAuthor(),
$this->renderObject());
} else {
return pht(
'%s reopened the initiative %s.',
'%s reopened %s.',
$this->renderAuthor(),
$this->renderObject());
}

View file

@ -53,10 +53,10 @@ final class PhabricatorLegalpadApplication extends PhabricatorApplication {
'/L(?P<id>\d+)' => 'LegalpadDocumentSignController',
'/legalpad/' => array(
'' => 'LegalpadDocumentListController',
'(?:query/(?P<queryKey>[^/]+)/)?' => 'LegalpadDocumentListController',
'create/' => 'LegalpadDocumentEditController',
'edit/(?P<id>\d+)/' => 'LegalpadDocumentEditController',
'comment/(?P<id>\d+)/' => 'LegalpadDocumentCommentController',
'(?:query/(?P<queryKey>[^/]+)/)?'
=> 'LegalpadDocumentListController',
$this->getEditRoutePattern('edit/')
=> 'LegalpadDocumentEditController',
'view/(?P<id>\d+)/' => 'LegalpadDocumentManageController',
'done/' => 'LegalpadDocumentDoneController',
'verify/(?P<code>[^/]+)/'

View file

@ -9,7 +9,7 @@ abstract class LegalpadController extends PhabricatorController {
$nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
if ($for_app) {
$nav->addFilter('create/', pht('Create Document'));
$nav->addFilter('edit/', pht('Create Document'));
}
id(new LegalpadDocumentSearchEngine())

View file

@ -1,72 +0,0 @@
<?php
final class LegalpadDocumentCommentController extends LegalpadController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$id = $request->getURIData('id');
if (!$request->isFormPost()) {
return new Aphront400Response();
}
$document = id(new LegalpadDocumentQuery())
->setViewer($viewer)
->withIDs(array($id))
->needDocumentBodies(true)
->executeOne();
if (!$document) {
return new Aphront404Response();
}
$is_preview = $request->isPreviewRequest();
$draft = PhabricatorDraft::buildFromRequest($request);
$document_uri = $this->getApplicationURI('view/'.$document->getID());
$comment = $request->getStr('comment');
$xactions = array();
if (strlen($comment)) {
$xactions[] = id(new LegalpadTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_COMMENT)
->attachComment(
id(new LegalpadTransactionComment())
->setDocumentID($document->getID())
->setLineNumber(0)
->setLineLength(0)
->setContent($comment));
}
$editor = id(new LegalpadDocumentEditor())
->setActor($viewer)
->setContentSourceFromRequest($request)
->setContinueOnNoEffect($request->isContinueRequest())
->setIsPreview($is_preview);
try {
$xactions = $editor->applyTransactions($document, $xactions);
} catch (PhabricatorApplicationTransactionNoEffectException $ex) {
return id(new PhabricatorApplicationTransactionNoEffectResponse())
->setCancelURI($document_uri)
->setException($ex);
}
if ($draft) {
$draft->replaceOrDelete();
}
if ($request->isAjax() && $is_preview) {
return id(new PhabricatorApplicationTransactionResponse())
->setViewer($viewer)
->setTransactions($xactions)
->setIsPreview($is_preview);
} else {
return id(new AphrontRedirectResponse())->setURI($document_uri);
}
}
}

View file

@ -3,275 +3,9 @@
final class LegalpadDocumentEditController extends LegalpadController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$id = $request->getURIData('id');
if (!$id) {
$is_create = true;
$this->requireApplicationCapability(
LegalpadCreateDocumentsCapability::CAPABILITY);
$document = LegalpadDocument::initializeNewDocument($viewer);
$body = id(new LegalpadDocumentBody())
->setCreatorPHID($viewer->getPHID());
$document->attachDocumentBody($body);
$document->setDocumentBodyPHID(PhabricatorPHIDConstants::PHID_VOID);
} else {
$is_create = false;
$document = id(new LegalpadDocumentQuery())
->setViewer($viewer)
->needDocumentBodies(true)
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->withIDs(array($id))
->executeOne();
if (!$document) {
return new Aphront404Response();
}
}
$e_title = true;
$e_text = true;
$title = $document->getDocumentBody()->getTitle();
$text = $document->getDocumentBody()->getText();
$v_signature_type = $document->getSignatureType();
$v_preamble = $document->getPreamble();
$v_require_signature = $document->getRequireSignature();
$errors = array();
$can_view = null;
$can_edit = null;
if ($request->isFormPost()) {
$xactions = array();
$title = $request->getStr('title');
if (!strlen($title)) {
$e_title = pht('Required');
$errors[] = pht('The document title may not be blank.');
} else {
$xactions[] = id(new LegalpadTransaction())
->setTransactionType(
LegalpadDocumentTitleTransaction::TRANSACTIONTYPE)
->setNewValue($title);
}
$text = $request->getStr('text');
if (!strlen($text)) {
$e_text = pht('Required');
$errors[] = pht('The document may not be blank.');
} else {
$xactions[] = id(new LegalpadTransaction())
->setTransactionType(
LegalpadDocumentTextTransaction::TRANSACTIONTYPE)
->setNewValue($text);
}
$can_view = $request->getStr('can_view');
$xactions[] = id(new LegalpadTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)
->setNewValue($can_view);
$can_edit = $request->getStr('can_edit');
$xactions[] = id(new LegalpadTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY)
->setNewValue($can_edit);
if ($is_create) {
$v_signature_type = $request->getStr('signatureType');
$xactions[] = id(new LegalpadTransaction())
->setTransactionType(
LegalpadDocumentSignatureTypeTransaction::TRANSACTIONTYPE)
->setNewValue($v_signature_type);
}
$v_preamble = $request->getStr('preamble');
$xactions[] = id(new LegalpadTransaction())
->setTransactionType(
LegalpadDocumentPreambleTransaction::TRANSACTIONTYPE)
->setNewValue($v_preamble);
$v_require_signature = $request->getBool('requireSignature', 0);
if ($v_require_signature) {
if (!$viewer->getIsAdmin()) {
$errors[] = pht('Only admins may require signature.');
}
$individual = LegalpadDocument::SIGNATURE_TYPE_INDIVIDUAL;
if ($v_signature_type != $individual) {
$errors[] = pht(
'Only documents with signature type "individual" may require '.
'signing to use Phabricator.');
}
}
if ($viewer->getIsAdmin()) {
$xactions[] = id(new LegalpadTransaction())
->setTransactionType(
LegalpadDocumentRequireSignatureTransaction::TRANSACTIONTYPE)
->setNewValue($v_require_signature);
}
if (!$errors) {
$editor = id(new LegalpadDocumentEditor())
->setContentSourceFromRequest($request)
->setContinueOnNoEffect(true)
->setActor($viewer);
$xactions = $editor->applyTransactions($document, $xactions);
return id(new AphrontRedirectResponse())
->setURI($this->getApplicationURI('view/'.$document->getID()));
}
}
if ($errors) {
// set these to what was specified in the form on post
$document->setViewPolicy($can_view);
$document->setEditPolicy($can_edit);
}
$form = id(new AphrontFormView())
->setUser($viewer)
->appendChild(
id(new AphrontFormTextControl())
->setID('document-title')
->setLabel(pht('Title'))
->setError($e_title)
->setValue($title)
->setName('title'));
if ($is_create) {
$form->appendChild(
id(new AphrontFormSelectControl())
->setLabel(pht('Who Should Sign?'))
->setName(pht('signatureType'))
->setValue($v_signature_type)
->setOptions(LegalpadDocument::getSignatureTypeMap()));
$show_require = true;
$caption = pht('Applies only to documents individuals sign.');
} else {
$form->appendChild(
id(new AphrontFormMarkupControl())
->setLabel(pht('Who Should Sign?'))
->setValue($document->getSignatureTypeName()));
$individual = LegalpadDocument::SIGNATURE_TYPE_INDIVIDUAL;
$show_require = $document->getSignatureType() == $individual;
$caption = null;
}
if ($show_require) {
$form
->appendChild(
id(new AphrontFormCheckboxControl())
->setDisabled(!$viewer->getIsAdmin())
->setLabel(pht('Require Signature'))
->addCheckbox(
'requireSignature',
'requireSignature',
pht('Should signing this document be required to use Phabricator?'),
$v_require_signature)
->setCaption($caption));
}
$form
->appendChild(
id(new PhabricatorRemarkupControl())
->setUser($viewer)
->setID('preamble')
->setLabel(pht('Preamble'))
->setValue($v_preamble)
->setName('preamble')
->setCaption(
pht('Optional help text for users signing this document.')))
->appendChild(
id(new PhabricatorRemarkupControl())
->setUser($viewer)
->setID('document-text')
->setLabel(pht('Document Body'))
->setError($e_text)
->setValue($text)
->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_TALL)
->setName('text'));
$policies = id(new PhabricatorPolicyQuery())
->setViewer($viewer)
->setObject($document)
->execute();
$form
->appendChild(
id(new AphrontFormPolicyControl())
->setUser($viewer)
->setCapability(PhabricatorPolicyCapability::CAN_VIEW)
->setPolicyObject($document)
->setPolicies($policies)
->setName('can_view'))
->appendChild(
id(new AphrontFormPolicyControl())
->setUser($viewer)
->setCapability(PhabricatorPolicyCapability::CAN_EDIT)
->setPolicyObject($document)
->setPolicies($policies)
->setName('can_edit'));
$crumbs = $this->buildApplicationCrumbs();
$submit = new AphrontFormSubmitControl();
if ($is_create) {
$submit->setValue(pht('Create Document'));
$submit->addCancelButton($this->getApplicationURI());
$title = pht('Create Document');
$short = pht('Create');
$header_icon = 'fa-plus-square';
} else {
$submit->setValue(pht('Save Document'));
$submit->addCancelButton(
$this->getApplicationURI('view/'.$document->getID()));
$title = pht('Edit Document: %s', $document->getTitle());
$short = pht('Edit');
$header_icon = 'fa-pencil';
$crumbs->addTextCrumb(
$document->getMonogram(),
$this->getApplicationURI('view/'.$document->getID()));
}
$form->appendChild($submit);
$form_box = id(new PHUIObjectBoxView())
->setHeaderText(pht('Document'))
->setFormErrors($errors)
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setForm($form);
$crumbs->addTextCrumb($short);
$crumbs->setBorder(true);
$preview = id(new PHUIRemarkupPreviewPanel())
->setHeader($document->getTitle())
->setPreviewURI($this->getApplicationURI('document/preview/'))
->setControlID('document-text')
->setPreviewType(PHUIRemarkupPreviewPanel::DOCUMENT);
$header = id(new PHUIHeaderView())
->setHeader($title)
->setHeaderIcon($header_icon);
$view = id(new PHUITwoColumnView())
->setHeader($header)
->setFooter(array(
$form_box,
$preview,
));
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->appendChild($view);
return id(new LegalpadDocumentEditEngine())
->setController($this)
->buildResponse();
}
}

View file

@ -26,7 +26,7 @@ final class LegalpadDocumentListController extends LegalpadController {
$crumbs->addAction(
id(new PHUIListItemView())
->setName(pht('Create Document'))
->setHref($this->getApplicationURI('create/'))
->setHref($this->getApplicationURI('edit/'))
->setIcon('fa-plus-square')
->setDisabled(!$can_create)
->setWorkflow(!$can_create));

View file

@ -37,6 +37,7 @@ final class LegalpadDocumentManageController extends LegalpadController {
$document,
new LegalpadTransactionQuery(),
$engine);
$timeline->setQuoteRef($document->getMonogram());
$title = $document_body->getTitle();
@ -50,9 +51,7 @@ final class LegalpadDocumentManageController extends LegalpadController {
$properties = $this->buildPropertyView($document, $engine);
$document_view = $this->buildDocumentView($document, $engine);
$comment_form_id = celerity_generate_unique_node_id();
$add_comment = $this->buildAddCommentView($document, $comment_form_id);
$comment_form = $this->buildCommentView($document, $timeline);
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(
@ -69,7 +68,7 @@ final class LegalpadDocumentManageController extends LegalpadController {
$properties,
$document_view,
$timeline,
$add_comment,
$comment_form,
));
return $this->newPage()
@ -181,31 +180,14 @@ final class LegalpadDocumentManageController extends LegalpadController {
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY);
}
private function buildAddCommentView(
LegalpadDocument $document,
$comment_form_id) {
private function buildCommentView(LegalpadDocument $document, $timeline) {
$viewer = $this->getViewer();
$box = id(new LegalpadDocumentEditEngine())
->setViewer($viewer)
->buildEditEngineCommentView($document)
->setTransactionTimeline($timeline);
$draft = PhabricatorDraft::newFromUserAndKey($viewer, $document->getPHID());
$is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
$title = $is_serious
? pht('Add Comment')
: pht('Debate Legislation');
$form = id(new PhabricatorApplicationTransactionCommentView())
->setUser($viewer)
->setObjectPHID($document->getPHID())
->setFormID($comment_form_id)
->setHeaderText($title)
->setDraft($draft)
->setSubmitButtonName(pht('Add Comment'))
->setAction($this->getApplicationURI('/comment/'.$document->getID().'/'))
->setRequestURI($this->getRequest()->getRequestURI());
return $form;
return $box;
}
}

View file

@ -0,0 +1,169 @@
<?php
final class LegalpadDocumentEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'legalpad.document';
public function getEngineName() {
return pht('Legalpad');
}
public function getEngineApplicationClass() {
return 'PhabricatorLegalpadApplication';
}
public function getSummaryHeader() {
return pht('Configure Legalpad Forms');
}
public function getSummaryText() {
return pht('Configure creation and editing documents in Legalpad.');
}
public function isEngineConfigurable() {
return false;
}
protected function newEditableObject() {
$viewer = $this->getViewer();
$document = LegalpadDocument::initializeNewDocument($viewer);
$body = id(new LegalpadDocumentBody())
->setCreatorPHID($viewer->getPHID());
$document->attachDocumentBody($body);
$document->setDocumentBodyPHID(PhabricatorPHIDConstants::PHID_VOID);
return $document;
}
protected function newObjectQuery() {
return id(new LegalpadDocumentQuery())
->needDocumentBodies(true);
}
protected function getObjectCreateTitleText($object) {
return pht('Create New Document');
}
protected function getObjectEditTitleText($object) {
$body = $object->getDocumentBody();
$title = $body->getTitle();
return pht('Edit Document: %s', $title);
}
protected function getObjectEditShortText($object) {
$body = $object->getDocumentBody();
return $body->getTitle();
}
protected function getObjectCreateShortText() {
return pht('Create Document');
}
protected function getObjectName() {
return pht('Document');
}
protected function getObjectCreateCancelURI($object) {
return $this->getApplication()->getApplicationURI('/');
}
protected function getEditorURI() {
return $this->getApplication()->getApplicationURI('edit/');
}
protected function getObjectViewURI($object) {
$id = $object->getID();
return $this->getApplication()->getApplicationURI('view/'.$id.'/');
}
protected function getCreateNewObjectPolicy() {
return $this->getApplication()->getPolicy(
LegalpadCreateDocumentsCapability::CAPABILITY);
}
protected function buildCustomEditFields($object) {
$viewer = $this->getViewer();
$body = $object->getDocumentBody();
$document_body = $body->getText();
$is_create = $this->getIsCreate();
$is_admin = $viewer->getIsAdmin();
$fields = array();
$fields[] =
id(new PhabricatorTextEditField())
->setKey('title')
->setLabel(pht('Title'))
->setDescription(pht('Document Title.'))
->setConduitTypeDescription(pht('New document title.'))
->setValue($object->getTitle())
->setIsRequired(true)
->setTransactionType(
LegalpadDocumentTitleTransaction::TRANSACTIONTYPE);
if ($is_create) {
$fields[] =
id(new PhabricatorSelectEditField())
->setKey('signatureType')
->setLabel(pht('Who Should Sign?'))
->setDescription(pht('Type of signature required'))
->setConduitTypeDescription(pht('New document signature type.'))
->setValue($object->getSignatureType())
->setOptions(LegalpadDocument::getSignatureTypeMap())
->setTransactionType(
LegalpadDocumentSignatureTypeTransaction::TRANSACTIONTYPE);
$show_require = true;
} else {
$fields[] = id(new PhabricatorStaticEditField())
->setLabel(pht('Who Should Sign?'))
->setValue($object->getSignatureTypeName());
$individual = LegalpadDocument::SIGNATURE_TYPE_INDIVIDUAL;
$show_require = $object->getSignatureType() == $individual;
}
if ($show_require && $is_admin) {
$fields[] =
id(new PhabricatorBoolEditField())
->setKey('requireSignature')
->setOptions(
pht('No Signature Required'),
pht('Signature Required to use Phabricator'))
->setAsCheckbox(true)
->setTransactionType(
LegalpadDocumentRequireSignatureTransaction::TRANSACTIONTYPE)
->setDescription(pht('Marks this document as required signing.'))
->setConduitDescription(
pht('Marks this document as required signing.'))
->setValue($object->getRequireSignature());
}
$fields[] =
id(new PhabricatorRemarkupEditField())
->setKey('preamble')
->setLabel(pht('Preamble'))
->setDescription(pht('The preamble of the document.'))
->setConduitTypeDescription(pht('New document preamble.'))
->setValue($object->getPreamble())
->setTransactionType(
LegalpadDocumentPreambleTransaction::TRANSACTIONTYPE);
$fields[] =
id(new PhabricatorRemarkupEditField())
->setKey('text')
->setLabel(pht('Document Body'))
->setDescription(pht('The body of text of the document.'))
->setConduitTypeDescription(pht('New document body.'))
->setValue($document_body)
->setIsRequired(true)
->setTransactionType(
LegalpadDocumentTextTransaction::TRANSACTIONTYPE);
return $fields;
}
}

View file

@ -21,6 +21,14 @@ final class LegalpadDocumentEditor
return $types;
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this document.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
protected function applyFinalEffects(
PhabricatorLiskDAO $object,
array $xactions) {
@ -64,6 +72,37 @@ final class LegalpadDocumentEditor
return $xactions;
}
protected function validateAllTransactions(PhabricatorLiskDAO $object,
array $xactions) {
$errors = array();
$is_required = (bool)$object->getRequireSignature();
$document_type = $object->getSignatureType();
$individual = LegalpadDocument::SIGNATURE_TYPE_INDIVIDUAL;
foreach ($xactions as $xaction) {
switch ($xaction->getTransactionType()) {
case LegalpadDocumentRequireSignatureTransaction::TRANSACTIONTYPE:
$is_required = (bool)$xaction->getNewValue();
break;
case LegalpadDocumentSignatureTypeTransaction::TRANSACTIONTYPE:
$document_type = $xaction->getNewValue();
break;
}
}
if ($is_required && ($document_type != $individual)) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
LegalpadDocumentRequireSignatureTransaction::TRANSACTIONTYPE,
pht('Invalid'),
pht('Only documents with signature type "individual" may '.
'require signing to use Phabricator.'),
null);
}
return $errors;
}
/* -( Sending Mail )------------------------------------------------------- */

View file

@ -120,6 +120,10 @@ final class LegalpadDocument extends LegalpadDAO
return 'L'.$this->getID();
}
public function getViewURI() {
return '/'.$this->getMonogram();
}
public function getUserSignature($phid) {
return $this->assertAttachedKey($this->userSignatures, $phid);
}

View file

@ -6,15 +6,15 @@ final class LegalpadDocumentRequireSignatureTransaction
const TRANSACTIONTYPE = 'legalpad:require-signature';
public function generateOldValue($object) {
return $object->getRequireSignature();
return (int)$object->getRequireSignature();
}
public function applyInternalEffects($object, $value) {
$object->setRequireSignature($value);
$object->setRequireSignature((int)$value);
}
public function applyExternalEffects($object, $value) {
if (strlen($value)) {
if ($value) {
$session = new PhabricatorAuthSession();
queryfx(
$session->establishConnection('w'),
@ -25,6 +25,7 @@ final class LegalpadDocumentRequireSignatureTransaction
public function getTitle() {
$new = $this->getNewValue();
if ($new) {
return pht(
'%s set the document to require signatures.',
@ -51,6 +52,19 @@ final class LegalpadDocumentRequireSignatureTransaction
}
}
public function validateTransactions($object, array $xactions) {
$errors = array();
$is_admin = $this->getActor()->getIsAdmin();
if (!$is_admin) {
$errors[] = $this->newInvalidError(
pht('Only admins may require signature.'));
}
return $errors;
}
public function getIcon() {
return 'fa-pencil-square';
}

View file

@ -15,13 +15,13 @@ final class LegalpadDocumentSignatureTypeTransaction
public function getTitle() {
return pht(
'%s set the document signature type.',
'%s updated the document signature type.',
$this->renderAuthor());
}
public function getTitleForFeed() {
return pht(
'%s set the document signature type for %s.',
'%s updated the document signature type for %s.',
$this->renderAuthor(),
$this->renderObject());
}

View file

@ -17,9 +17,17 @@ final class LegalpadDocumentTextTransaction
}
public function getTitle() {
return pht(
'%s updated the document text.',
$this->renderAuthor());
$old = $this->getOldValue();
if (!strlen($old)) {
return pht(
'%s set the document text.',
$this->renderAuthor());
} else {
return pht(
'%s updated the document text.',
$this->renderAuthor());
}
}
public function getTitleForFeed() {

View file

@ -17,20 +17,37 @@ final class LegalpadDocumentTitleTransaction
}
public function getTitle() {
return pht(
'%s renamed this document from %s to %s.',
$this->renderAuthor(),
$this->renderOldValue(),
$this->renderNewValue());
$old = $this->getOldValue();
if (!strlen($old)) {
return pht(
'%s created this document.',
$this->renderAuthor());
} else {
return pht(
'%s renamed this document from %s to %s.',
$this->renderAuthor(),
$this->renderOldValue(),
$this->renderNewValue());
}
}
public function getTitleForFeed() {
return pht(
'%s renamed document %s from %s to %s.',
$this->renderAuthor(),
$this->renderObject(),
$this->renderOldValue(),
$this->renderNewValue());
$old = $this->getOldValue();
if (!strlen($old)) {
return pht(
'%s created %s.',
$this->renderAuthor(),
$this->renderObject());
} else {
return pht(
'%s renamed %s from %s to %s.',
$this->renderAuthor(),
$this->renderObject(),
$this->renderOldValue(),
$this->renderNewValue());
}
}
public function validateTransactions($object, array $xactions) {

View file

@ -0,0 +1,19 @@
<?php
final class MacroEditConduitAPIMethod
extends PhabricatorEditEngineAPIMethod {
public function getAPIMethodName() {
return 'macro.edit';
}
public function newEditEngine() {
return new PhabricatorMacroEditEngine();
}
public function getMethodSummary() {
return pht(
'Apply transactions to create a new macro or edit an existing one.');
}
}

View file

@ -50,7 +50,9 @@ final class PhabricatorMacroAudioController extends PhabricatorMacroController {
if ($file) {
if (!$file->isAudio()) {
$errors[] = pht('You must upload audio.');
$errors[] = pht(
'The file you uploaded is invalid: it is not recognizable as '.
'a valid audio file.');
$e_file = pht('Invalid');
} else {
$xactions[] = id(new PhabricatorMacroTransaction())
@ -59,7 +61,9 @@ final class PhabricatorMacroAudioController extends PhabricatorMacroController {
->setNewValue($file->getPHID());
}
} else {
$errors[] = pht('You must upload an audio file.');
$errors[] = pht(
'To change the audio for a macro, you must upload an audio '.
'file.');
$e_file = pht('Required');
}
}

View file

@ -21,6 +21,10 @@ final class PhabricatorMacroEditEngine
return 'PhabricatorMacroApplication';
}
public function isEngineConfigurable() {
return false;
}
protected function newEditableObject() {
$viewer = $this->getViewer();
return PhabricatorFileImageMacro::initializeNewFileImageMacro($viewer);
@ -35,7 +39,7 @@ final class PhabricatorMacroEditEngine
}
protected function getObjectEditTitleText($object) {
return pht('Edit %s', $object->getName());
return pht('Edit Macro %s', $object->getName());
}
protected function getObjectEditShortText($object) {
@ -63,6 +67,19 @@ final class PhabricatorMacroEditEngine
PhabricatorMacroManageCapability::CAPABILITY);
}
protected function willConfigureFields($object, array $fields) {
if ($this->getIsCreate()) {
$subscribers_field = idx($fields,
PhabricatorSubscriptionsEditEngineExtension::FIELDKEY);
if ($subscribers_field) {
// By default, hide the subscribers field when creating a macro
// because it makes the workflow SO HARD and wastes SO MUCH TIME.
$subscribers_field->setIsHidden(true);
}
}
return $fields;
}
protected function buildCustomEditFields($object) {
return array(
@ -70,9 +87,10 @@ final class PhabricatorMacroEditEngine
->setKey('name')
->setLabel(pht('Name'))
->setDescription(pht('Macro name.'))
->setConduitDescription(pht('Rename the macro.'))
->setConduitDescription(pht('Name of the macro.'))
->setConduitTypeDescription(pht('New macro name.'))
->setTransactionType(PhabricatorMacroNameTransaction::TRANSACTIONTYPE)
->setIsRequired(true)
->setValue($object->getName()),
id(new PhabricatorFileEditField())
->setKey('filePHID')
@ -80,7 +98,8 @@ final class PhabricatorMacroEditEngine
->setDescription(pht('Image file to import.'))
->setTransactionType(PhabricatorMacroFileTransaction::TRANSACTIONTYPE)
->setConduitDescription(pht('File PHID to import.'))
->setConduitTypeDescription(pht('File PHID.')),
->setConduitTypeDescription(pht('File PHID.'))
->setValue($object->getFilePHID()),
);
}

View file

@ -49,7 +49,7 @@ final class PhabricatorMacroFileTransaction
public function getTitleForFeed() {
return pht(
'%s changed the image for macro %s.',
'%s changed the image for %s.',
$this->renderAuthor(),
$this->renderObject());
}
@ -58,29 +58,37 @@ final class PhabricatorMacroFileTransaction
$errors = array();
$viewer = $this->getActor();
$old_phid = $object->getFilePHID();
foreach ($xactions as $xaction) {
$file_phid = $xaction->getNewValue();
if ($this->isEmptyTextTransaction($file_phid, $xactions)) {
$errors[] = $this->newRequiredError(
pht('Image macros must have a file.'));
if (!$old_phid) {
if ($this->isEmptyTextTransaction($file_phid, $xactions)) {
$errors[] = $this->newRequiredError(
pht('Image macros must have a file.'));
return $errors;
}
}
$file = id(new PhabricatorFileQuery())
->setViewer($viewer)
->withPHIDs(array($file_phid))
->executeOne();
// Only validate if file was uploaded
if ($file_phid) {
$file = id(new PhabricatorFileQuery())
->setViewer($viewer)
->withPHIDs(array($file_phid))
->executeOne();
if (!$file) {
$errors[] = $this->newInvalidError(
pht('"%s" is not a valid file PHID.',
$file_phid));
} else {
if (!$file->isViewableInBrowser()) {
$mime_type = $file->getMimeType();
if (!$file) {
$errors[] = $this->newInvalidError(
pht('File mime type of "%s" is not a valid viewable image.',
$mime_type));
pht('"%s" is not a valid file PHID.',
$file_phid));
} else {
if (!$file->isViewableImage()) {
$mime_type = $file->getMimeType();
$errors[] = $this->newInvalidError(
pht('File mime type of "%s" is not a valid viewable image.',
$mime_type));
}
}
}

View file

@ -23,7 +23,7 @@ final class PhabricatorMacroNameTransaction
public function getTitleForFeed() {
return pht(
'%s renamed %s macro %s to %s.',
'%s renamed %s from %s to %s.',
$this->renderAuthor(),
$this->renderObject(),
$this->renderOldValue(),
@ -37,6 +37,7 @@ final class PhabricatorMacroNameTransaction
if ($this->isEmptyTextTransaction($object->getName(), $xactions)) {
$errors[] = $this->newRequiredError(
pht('Macros must have a name.'));
return $errors;
}
$max_length = $object->getColumnMaximumByteLength('name');

View file

@ -32,7 +32,6 @@ final class PhabricatorApplicationEditController
if ($request->isFormPost()) {
$xactions = array();
$result = array();
$template = $application->getApplicationTransactionTemplate();
foreach ($application->getCapabilities() as $capability) {
if (!$application->isCapabilityEditable($capability)) {
@ -47,8 +46,6 @@ final class PhabricatorApplicationEditController
continue;
}
$result[$capability] = $new;
$xactions[] = id(clone $template)
->setTransactionType(
PhabricatorApplicationPolicyChangeTransaction::TRANSACTIONTYPE)
@ -58,25 +55,23 @@ final class PhabricatorApplicationEditController
->setNewValue($new);
}
if ($result) {
$editor = id(new PhabricatorApplicationEditor())
->setActor($user)
->setContentSourceFromRequest($request)
->setContinueOnNoEffect(true)
->setContinueOnMissingFields(true);
$editor = id(new PhabricatorApplicationEditor())
->setActor($user)
->setContentSourceFromRequest($request)
->setContinueOnNoEffect(true)
->setContinueOnMissingFields(true);
try {
$editor->applyTransactions($application, $xactions);
return id(new AphrontRedirectResponse())->setURI($view_uri);
} catch (PhabricatorApplicationTransactionValidationException $ex) {
$validation_exception = $ex;
}
return $this->newDialog()
->setTitle('Validation Failed')
->setValidationException($validation_exception)
->addCancelButton($view_uri);
try {
$editor->applyTransactions($application, $xactions);
return id(new AphrontRedirectResponse())->setURI($view_uri);
} catch (PhabricatorApplicationTransactionValidationException $ex) {
$validation_exception = $ex;
}
return $this->newDialog()
->setTitle(pht('Validation Failed'))
->setValidationException($validation_exception)
->addCancelButton($view_uri);
}
$descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions(

View file

@ -244,8 +244,8 @@ final class PassphraseCredentialEditController extends PassphraseController {
->setValue($v_name)
->setError($e_name))
->appendChild(
id(new AphrontFormTextAreaControl())
->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_SHORT)
id(new PhabricatorRemarkupControl())
->setUser($viewer)
->setName('description')
->setLabel(pht('Description'))
->setValue($v_desc))

View file

@ -17,17 +17,9 @@ final class PassphraseCredentialSecretIDTransaction
$object->setSecretID($value);
}
public function shouldHide() {
if (!$this->getOldValue()) {
return true;
}
return false;
}
public function getTitle() {
$old = $this->getOldValue();
if ($old === null) {
if (!$old) {
return pht(
'%s attached a new secret to this credential.',
$this->renderAuthor());
@ -53,4 +45,8 @@ final class PassphraseCredentialSecretIDTransaction
}
}
public function getIcon() {
return 'fa-key';
}
}

View file

@ -76,6 +76,7 @@ final class PhameBlogEditEngine
->setConduitDescription(pht('Retitle the blog.'))
->setConduitTypeDescription(pht('New blog title.'))
->setTransactionType(PhameBlogNameTransaction::TRANSACTIONTYPE)
->setIsRequired(true)
->setValue($object->getName()),
id(new PhabricatorTextEditField())
->setKey('subtitle')

View file

@ -98,6 +98,7 @@ final class PhamePostEditEngine
->setConduitDescription(pht('Retitle the post.'))
->setConduitTypeDescription(pht('New post title.'))
->setTransactionType(PhamePostTitleTransaction::TRANSACTIONTYPE)
->setIsRequired(true)
->setValue($object->getTitle()),
id(new PhabricatorTextEditField())
->setKey('subtitle')

View file

@ -88,7 +88,7 @@ final class PhamePostEditor
} else {
foreach ($xactions as $xaction) {
switch ($xaction->getTransactionType()) {
case PhamePostTransaction::TYPE_VISIBILITY:
case PhamePostVisibilityTransaction::TRANSACTIONTYPE:
if (!$object->isDraft() && !$object->isArchived()) {
$body->addRemarkupSection(null, $object->getBody());
}

View file

@ -26,14 +26,14 @@ final class PhameBlogTransaction
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
$tags[] = self::MAILTAG_SUBSCRIBERS;
break;
case self::TYPE_NAME:
case self::TYPE_SUBTITLE:
case self::TYPE_DESCRIPTION:
case self::TYPE_FULLDOMAIN:
case self::TYPE_PARENTSITE:
case self::TYPE_PARENTDOMAIN:
case self::TYPE_PROFILEIMAGE:
case self::TYPE_HEADERIMAGE:
case PhameBlogNameTransaction::TRANSACTIONTYPE:
case PhameBlogSubtitleTransaction::TRANSACTIONTYPE:
case PhameBlogDescriptionTransaction::TRANSACTIONTYPE:
case PhameBlogFullDomainTransaction::TRANSACTIONTYPE:
case PhameBlogParentSiteTransaction::TRANSACTIONTYPE:
case PhameBlogParentDomainTransaction::TRANSACTIONTYPE:
case PhameBlogProfileImageTransaction::TRANSACTIONTYPE:
case PhameBlogHeaderImageTransaction::TRANSACTIONTYPE:
$tags[] = self::MAILTAG_DETAILS;
break;
default:

View file

@ -34,9 +34,9 @@ final class PhamePostTransaction
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
$tags[] = self::MAILTAG_SUBSCRIBERS;
break;
case self::TYPE_TITLE:
case self::TYPE_SUBTITLE:
case self::TYPE_BODY:
case PhamePostTitleTransaction::TRANSACTIONTYPE:
case PhamePostSubtitleTransaction::TRANSACTIONTYPE:
case PhamePostBodyTransaction::TRANSACTIONTYPE:
$tags[] = self::MAILTAG_CONTENT;
break;
default:

View file

@ -32,7 +32,7 @@ final class PholioMockArchiveController
$xactions = array();
$xactions[] = id(new PholioTransaction())
->setTransactionType(PholioTransaction::TYPE_STATUS)
->setTransactionType(PholioMockStatusTransaction::TRANSACTIONTYPE)
->setNewValue($new_status);
id(new PholioMockEditor())

View file

@ -65,8 +65,8 @@ final class PholioMockEditController extends PholioController {
if ($request->isFormPost()) {
$xactions = array();
$type_name = PholioTransaction::TYPE_NAME;
$type_desc = PholioTransaction::TYPE_DESCRIPTION;
$type_name = PholioMockNameTransaction::TRANSACTIONTYPE;
$type_desc = PholioMockDescriptionTransaction::TRANSACTIONTYPE;
$type_view = PhabricatorTransactions::TYPE_VIEW_POLICY;
$type_edit = PhabricatorTransactions::TYPE_EDIT_POLICY;
$type_cc = PhabricatorTransactions::TYPE_SUBSCRIBERS;
@ -88,11 +88,6 @@ final class PholioMockEditController extends PholioController {
$mock_xactions[$type_cc] = array('=' => $v_cc);
$mock_xactions[$type_space] = $v_space;
if (!strlen($request->getStr('name'))) {
$e_name = pht('Required');
$errors[] = pht('You must give the mock a name.');
}
$file_phids = $request->getArr('file_phids');
if ($file_phids) {
$files = id(new PhabricatorFileQuery())
@ -173,12 +168,12 @@ final class PholioMockEditController extends PholioController {
$posted_mock_images[] = $add_image;
} else {
$xactions[] = id(new PholioTransaction())
->setTransactionType(PholioTransaction::TYPE_IMAGE_NAME)
->setTransactionType(PholioImageNameTransaction::TRANSACTIONTYPE)
->setNewValue(
array($existing_image->getPHID() => $title));
$xactions[] = id(new PholioTransaction())
->setTransactionType(
PholioTransaction::TYPE_IMAGE_DESCRIPTION)
PholioImageDescriptionTransaction::TRANSACTIONTYPE)
->setNewValue(
array($existing_image->getPHID() => $description));
$xactions[] = id(new PholioTransaction())

View file

@ -29,14 +29,9 @@ final class PholioMockEditor extends PhabricatorApplicationTransactionEditor {
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
$types[] = PholioTransaction::TYPE_NAME;
$types[] = PholioTransaction::TYPE_DESCRIPTION;
$types[] = PholioTransaction::TYPE_STATUS;
$types[] = PholioTransaction::TYPE_INLINE;
$types[] = PholioTransaction::TYPE_IMAGE_FILE;
$types[] = PholioTransaction::TYPE_IMAGE_NAME;
$types[] = PholioTransaction::TYPE_IMAGE_DESCRIPTION;
$types[] = PholioTransaction::TYPE_IMAGE_REPLACE;
$types[] = PholioTransaction::TYPE_IMAGE_SEQUENCE;
@ -48,33 +43,9 @@ final class PholioMockEditor extends PhabricatorApplicationTransactionEditor {
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PholioTransaction::TYPE_NAME:
return $object->getName();
case PholioTransaction::TYPE_DESCRIPTION:
return $object->getDescription();
case PholioTransaction::TYPE_STATUS:
return $object->getStatus();
case PholioTransaction::TYPE_IMAGE_FILE:
$images = $object->getImages();
return mpull($images, 'getPHID');
case PholioTransaction::TYPE_IMAGE_NAME:
$name = null;
$phid = null;
$image = $this->getImageForXaction($object, $xaction);
if ($image) {
$name = $image->getName();
$phid = $image->getPHID();
}
return array($phid => $name);
case PholioTransaction::TYPE_IMAGE_DESCRIPTION:
$description = null;
$phid = null;
$image = $this->getImageForXaction($object, $xaction);
if ($image) {
$description = $image->getDescription();
$phid = $image->getPHID();
}
return array($phid => $description);
case PholioTransaction::TYPE_IMAGE_REPLACE:
$raw = $xaction->getNewValue();
return $raw->getReplacesImagePHID();
@ -95,11 +66,6 @@ final class PholioMockEditor extends PhabricatorApplicationTransactionEditor {
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PholioTransaction::TYPE_NAME:
case PholioTransaction::TYPE_DESCRIPTION:
case PholioTransaction::TYPE_STATUS:
case PholioTransaction::TYPE_IMAGE_NAME:
case PholioTransaction::TYPE_IMAGE_DESCRIPTION:
case PholioTransaction::TYPE_IMAGE_SEQUENCE:
return $xaction->getNewValue();
case PholioTransaction::TYPE_IMAGE_REPLACE:
@ -204,26 +170,6 @@ final class PholioMockEditor extends PhabricatorApplicationTransactionEditor {
$this->setNewImages($new_images);
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PholioTransaction::TYPE_NAME:
$object->setName($xaction->getNewValue());
if ($object->getOriginalName() === null) {
$object->setOriginalName($xaction->getNewValue());
}
break;
case PholioTransaction::TYPE_DESCRIPTION:
$object->setDescription($xaction->getNewValue());
break;
case PholioTransaction::TYPE_STATUS:
$object->setStatus($xaction->getNewValue());
break;
}
}
private function getImageForXaction(
PholioMock $mock,
PhabricatorApplicationTransaction $xaction) {
@ -270,18 +216,6 @@ final class PholioMockEditor extends PhabricatorApplicationTransactionEditor {
}
$object->attachImages($images);
break;
case PholioTransaction::TYPE_IMAGE_NAME:
$image = $this->getImageForXaction($object, $xaction);
$value = (string)head($xaction->getNewValue());
$image->setName($value);
$image->save();
break;
case PholioTransaction::TYPE_IMAGE_DESCRIPTION:
$image = $this->getImageForXaction($object, $xaction);
$value = (string)head($xaction->getNewValue());
$image->setDescription($value);
$image->save();
break;
case PholioTransaction::TYPE_IMAGE_SEQUENCE:
$image = $this->getImageForXaction($object, $xaction);
$value = (int)head($xaction->getNewValue());
@ -310,10 +244,6 @@ final class PholioMockEditor extends PhabricatorApplicationTransactionEditor {
$type = $u->getTransactionType();
switch ($type) {
case PholioTransaction::TYPE_NAME:
case PholioTransaction::TYPE_DESCRIPTION:
case PholioTransaction::TYPE_STATUS:
return $v;
case PholioTransaction::TYPE_IMAGE_REPLACE:
$u_img = $u->getNewValue();
$v_img = $v->getNewValue();
@ -323,8 +253,6 @@ final class PholioMockEditor extends PhabricatorApplicationTransactionEditor {
break;
case PholioTransaction::TYPE_IMAGE_FILE:
return $this->mergePHIDOrEdgeTransactions($u, $v);
case PholioTransaction::TYPE_IMAGE_NAME:
case PholioTransaction::TYPE_IMAGE_DESCRIPTION:
case PholioTransaction::TYPE_IMAGE_SEQUENCE:
$raw_new_value_u = $u->getNewValue();
$raw_new_value_v = $v->getNewValue();

View file

@ -22,9 +22,9 @@ final class PhabricatorPholioMockTestDataGenerator
// Accumulate Transactions
$changes = array();
$changes[PholioTransaction::TYPE_NAME] =
$changes[PholioMockNameTransaction::TRANSACTIONTYPE] =
$this->generateTitle();
$changes[PholioTransaction::TYPE_DESCRIPTION] =
$changes[PholioMockDescriptionTransaction::TRANSACTIONTYPE] =
$this->generateDescription();
$changes[PhabricatorTransactions::TYPE_VIEW_POLICY] =
PhabricatorPolicies::POLICY_PUBLIC;

View file

@ -1,16 +1,9 @@
<?php
final class PholioTransaction extends PhabricatorApplicationTransaction {
// Edits to the high level mock
const TYPE_NAME = 'name';
const TYPE_DESCRIPTION = 'description';
const TYPE_STATUS = 'status';
final class PholioTransaction extends PhabricatorModularTransaction {
// Edits to images within the mock
const TYPE_IMAGE_FILE = 'image-file';
const TYPE_IMAGE_NAME= 'image-name';
const TYPE_IMAGE_DESCRIPTION = 'image-description';
const TYPE_IMAGE_REPLACE = 'image-replace';
const TYPE_IMAGE_SEQUENCE = 'image-sequence';
@ -26,6 +19,10 @@ final class PholioTransaction extends PhabricatorApplicationTransaction {
return 'pholio';
}
public function getBaseTransactionClass() {
return 'PholioTransactionType';
}
public function getApplicationTransactionType() {
return PholioMockPHIDType::TYPECONST;
}
@ -53,8 +50,8 @@ final class PholioTransaction extends PhabricatorApplicationTransaction {
$phids[] = $new;
$phids[] = $old;
break;
case self::TYPE_IMAGE_DESCRIPTION:
case self::TYPE_IMAGE_NAME:
case PholioImageDescriptionTransaction::TRANSACTIONTYPE:
case PholioImageNameTransaction::TRANSACTIONTYPE:
case self::TYPE_IMAGE_SEQUENCE:
$phids[] = key($new);
break;
@ -67,11 +64,6 @@ final class PholioTransaction extends PhabricatorApplicationTransaction {
$old = $this->getOldValue();
switch ($this->getTransactionType()) {
case self::TYPE_DESCRIPTION:
return ($old === null);
case self::TYPE_IMAGE_NAME:
case self::TYPE_IMAGE_DESCRIPTION:
return ($old === array(null => null));
// this is boring / silly to surface; changing sequence is NBD
case self::TYPE_IMAGE_SEQUENCE:
return true;
@ -88,16 +80,6 @@ final class PholioTransaction extends PhabricatorApplicationTransaction {
switch ($this->getTransactionType()) {
case self::TYPE_INLINE:
return 'fa-comment';
case self::TYPE_NAME:
case self::TYPE_DESCRIPTION:
case self::TYPE_STATUS:
if ($new == PholioMock::STATUS_CLOSED) {
return 'fa-ban';
} else {
return 'fa-check';
}
case self::TYPE_IMAGE_NAME:
case self::TYPE_IMAGE_DESCRIPTION:
case self::TYPE_IMAGE_SEQUENCE:
return 'fa-pencil';
case self::TYPE_IMAGE_FILE:
@ -115,13 +97,13 @@ final class PholioTransaction extends PhabricatorApplicationTransaction {
case PhabricatorTransactions::TYPE_COMMENT:
$tags[] = self::MAILTAG_COMMENT;
break;
case self::TYPE_STATUS:
case PholioMockStatusTransaction::TRANSACTIONTYPE:
$tags[] = self::MAILTAG_STATUS;
break;
case self::TYPE_NAME:
case self::TYPE_DESCRIPTION:
case self::TYPE_IMAGE_NAME:
case self::TYPE_IMAGE_DESCRIPTION:
case PholioMockNameTransaction::TRANSACTIONTYPE:
case PholioMockDescriptionTransaction::TRANSACTIONTYPE:
case PholioImageNameTransaction::TRANSACTIONTYPE:
case PholioImageDescriptionTransaction::TRANSACTIONTYPE:
case self::TYPE_IMAGE_SEQUENCE:
case self::TYPE_IMAGE_FILE:
case self::TYPE_IMAGE_REPLACE:
@ -142,36 +124,6 @@ final class PholioTransaction extends PhabricatorApplicationTransaction {
$type = $this->getTransactionType();
switch ($type) {
case self::TYPE_NAME:
if ($old === null) {
return pht(
'%s created "%s".',
$this->renderHandleLink($author_phid),
$new);
} else {
return pht(
'%s renamed this mock from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
}
break;
case self::TYPE_DESCRIPTION:
return pht(
"%s updated the mock's description.",
$this->renderHandleLink($author_phid));
break;
case self::TYPE_STATUS:
if ($new == PholioMock::STATUS_CLOSED) {
return pht(
'%s closed this mock.',
$this->renderHandleLink($author_phid));
} else {
return pht(
'%s opened this mock.',
$this->renderHandleLink($author_phid));
}
break;
case self::TYPE_INLINE:
$count = 1;
foreach ($this->getTransactionGroup() as $xaction) {
@ -218,21 +170,6 @@ final class PholioTransaction extends PhabricatorApplicationTransaction {
$this->renderHandleList($rem));
}
break;
case self::TYPE_IMAGE_NAME:
return pht(
'%s renamed an image (%s) from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$this->renderHandleLink(key($new)),
reset($old),
reset($new));
break;
case self::TYPE_IMAGE_DESCRIPTION:
return pht(
'%s updated an image\'s (%s) description.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink(key($new)));
break;
case self::TYPE_IMAGE_SEQUENCE:
return pht(
'%s updated an image\'s (%s) sequence.',
@ -253,40 +190,6 @@ final class PholioTransaction extends PhabricatorApplicationTransaction {
$type = $this->getTransactionType();
switch ($type) {
case self::TYPE_NAME:
if ($old === null) {
return pht(
'%s created %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
} else {
return pht(
'%s renamed %s from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid),
$old,
$new);
}
break;
case self::TYPE_DESCRIPTION:
return pht(
'%s updated the description for %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
break;
case self::TYPE_STATUS:
if ($new == PholioMock::STATUS_CLOSED) {
return pht(
'%s closed a mock %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
} else {
return pht(
'%s opened a mock %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
}
break;
case self::TYPE_INLINE:
return pht(
'%s added an inline comment to %s.',
@ -300,18 +203,6 @@ final class PholioTransaction extends PhabricatorApplicationTransaction {
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
break;
case self::TYPE_IMAGE_NAME:
return pht(
'%s updated the image names of %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
break;
case self::TYPE_IMAGE_DESCRIPTION:
return pht(
'%s updated image descriptions of %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
break;
case self::TYPE_IMAGE_SEQUENCE:
return pht(
'%s updated image sequence of %s.',
@ -323,62 +214,11 @@ final class PholioTransaction extends PhabricatorApplicationTransaction {
return parent::getTitleForFeed();
}
public function getRemarkupBodyForFeed(PhabricatorFeedStory $story) {
$text = null;
switch ($this->getTransactionType()) {
case self::TYPE_NAME:
if ($this->getOldValue() === null) {
$mock = $story->getPrimaryObject();
$text = $mock->getDescription();
}
break;
case self::TYPE_INLINE:
$text = $this->getComment()->getContent();
break;
}
return $text;
}
public function hasChangeDetails() {
switch ($this->getTransactionType()) {
case self::TYPE_DESCRIPTION:
case self::TYPE_IMAGE_DESCRIPTION:
return true;
}
return parent::hasChangeDetails();
}
public function renderChangeDetails(PhabricatorUser $viewer) {
$old = $this->getOldValue();
$new = $this->getNewValue();
if ($this->getTransactionType() ==
self::TYPE_IMAGE_DESCRIPTION) {
$old = reset($old);
$new = reset($new);
}
return $this->renderTextCorpusChangeDetails(
$viewer,
$old,
$new);
}
public function getColor() {
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case self::TYPE_STATUS:
if ($new == PholioMock::STATUS_CLOSED) {
return PhabricatorTransactions::COLOR_INDIGO;
} else {
return PhabricatorTransactions::COLOR_GREEN;
}
case self::TYPE_NAME:
if ($old === null) {
return PhabricatorTransactions::COLOR_GREEN;
}
case self::TYPE_IMAGE_REPLACE:
return PhabricatorTransactions::COLOR_YELLOW;
case self::TYPE_IMAGE_FILE:
@ -396,16 +236,4 @@ final class PholioTransaction extends PhabricatorApplicationTransaction {
return parent::getColor();
}
public function getNoEffectDescription() {
switch ($this->getTransactionType()) {
case self::TYPE_IMAGE_NAME:
return pht('The image title was not updated.');
case self::TYPE_IMAGE_DESCRIPTION:
return pht('The image description was not updated.');
case self::TYPE_IMAGE_SEQUENCE:
return pht('The image sequence was not updated.');
}
return parent::getNoEffectDescription();
}
}

View file

@ -0,0 +1,76 @@
<?php
final class PholioImageDescriptionTransaction
extends PholioImageTransactionType {
const TRANSACTIONTYPE = 'image-description';
public function generateOldValue($object) {
$description = null;
$phid = null;
$image = $this->getImageForXaction($object);
if ($image) {
$description = $image->getDescription();
$phid = $image->getPHID();
}
return array($phid => $description);
}
public function applyInternalEffects($object, $value) {
$image = $this->getImageForXaction($object);
$value = (string)head($this->getNewValue());
$image->setDescription($value);
$image->save();
}
public function getTitle() {
$new = $this->getNewValue();
return pht(
'%s updated an image\'s (%s) description.',
$this->renderAuthor(),
$this->renderHandle(head_key($new)));
}
public function getTitleForFeed() {
return pht(
'%s updated image descriptions of %s.',
$this->renderAuthor(),
$this->renderObject());
}
public function mergeTransactions(
$object,
PhabricatorApplicationTransaction $u,
PhabricatorApplicationTransaction $v) {
$raw_new_value_u = $u->getNewValue();
$raw_new_value_v = $v->getNewValue();
$phid_u = head_key($raw_new_value_u);
$phid_v = head_key($raw_new_value_v);
if ($phid_u == $phid_v) {
return $v;
}
return null;
}
public function shouldHide() {
$old = $this->getOldValue();
return ($old === array(null => null));
}
public function hasChangeDetailView() {
return true;
}
public function newChangeDetailView() {
$viewer = $this->getViewer();
return id(new PhabricatorApplicationTransactionTextDiffDetailView())
->setViewer($viewer)
->setOldText(head($this->getOldValue()))
->setNewText(head($this->getNewValue()));
}
}

View file

@ -0,0 +1,85 @@
<?php
final class PholioImageNameTransaction
extends PholioImageTransactionType {
const TRANSACTIONTYPE = 'image-name';
public function generateOldValue($object) {
$name = null;
$phid = null;
$image = $this->getImageForXaction($object);
if ($image) {
$name = $image->getName();
$phid = $image->getPHID();
}
return array($phid => $name);
}
public function applyInternalEffects($object, $value) {
$image = $this->getImageForXaction($object);
$value = (string)head($this->getNewValue());
$image->setName($value);
$image->save();
}
public function getTitle() {
$old = $this->getOldValue();
$new = $this->getNewValue();
return pht(
'%s renamed an image (%s) from %s to %s.',
$this->renderAuthor(),
$this->renderHandle(key($new)),
$this->renderValue($old),
$this->renderValue($new));
}
public function getTitleForFeed() {
return pht(
'%s updated the image names of %s.',
$this->renderAuthor(),
$this->renderObject());
}
public function mergeTransactions(
$object,
PhabricatorApplicationTransaction $u,
PhabricatorApplicationTransaction $v) {
$raw_new_value_u = $u->getNewValue();
$raw_new_value_v = $v->getNewValue();
$phid_u = head_key($raw_new_value_u);
$phid_v = head_key($raw_new_value_v);
if ($phid_u == $phid_v) {
return $v;
}
return null;
}
public function shouldHide() {
$old = $this->getOldValue();
return ($old === array(null => null));
}
public function validateTransactions($object, array $xactions) {
$errors = array();
$max_length = $object->getColumnMaximumByteLength('name');
foreach ($xactions as $xaction) {
$new_value = head(array_values($xaction->getNewValue()));
$new_length = strlen($new_value);
if ($new_length > $max_length) {
$errors[] = $this->newInvalidError(
pht(
'Mock image names must not be longer than %s character(s).',
new PhutilNumber($max_length)));
}
}
return $errors;
}
}

View file

@ -0,0 +1,18 @@
<?php
abstract class PholioImageTransactionType
extends PholioTransactionType {
protected function getImageForXaction(PholioMock $mock) {
$raw_new_value = $this->getNewValue();
$image_phid = head_key($raw_new_value);
$images = $mock->getImages();
foreach ($images as $image) {
if ($image->getPHID() == $image_phid) {
return $image;
}
}
return null;
}
}

View file

@ -0,0 +1,47 @@
<?php
final class PholioMockDescriptionTransaction
extends PholioMockTransactionType {
const TRANSACTIONTYPE = 'description';
public function generateOldValue($object) {
return $object->getDescription();
}
public function applyInternalEffects($object, $value) {
$object->setDescription($value);
}
public function getTitle() {
return pht(
"%s updated the mock's description.",
$this->renderAuthor());
}
public function getTitleForFeed() {
return pht(
'%s updated the description for %s.',
$this->renderAuthor(),
$this->renderObject());
}
public function shouldHide() {
$old = $this->getOldValue();
return ($old === null);
}
public function hasChangeDetailView() {
return true;
}
public function newChangeDetailView() {
$viewer = $this->getViewer();
return id(new PhabricatorApplicationTransactionTextDiffDetailView())
->setViewer($viewer)
->setOldText($this->getOldValue())
->setNewText($this->getNewValue());
}
}

View file

@ -0,0 +1,88 @@
<?php
final class PholioMockNameTransaction
extends PholioMockTransactionType {
const TRANSACTIONTYPE = 'name';
public function generateOldValue($object) {
return $object->getName();
}
public function applyInternalEffects($object, $value) {
$object->setName($value);
if ($object->getOriginalName() === null) {
$object->setOriginalName($this->getNewValue());
}
}
public function getTitle() {
$old = $this->getOldValue();
$new = $this->getNewValue();
if ($old === null) {
return pht(
'%s created %s.',
$this->renderAuthor(),
$this->renderValue($new));
} else {
return pht(
'%s renamed this mock from %s to %s.',
$this->renderAuthor(),
$this->renderValue($old),
$this->renderValue($new));
}
}
public function getTitleForFeed() {
$old = $this->getOldValue();
$new = $this->getNewValue();
if ($old === null) {
return pht(
'%s created %s.',
$this->renderAuthor(),
$this->renderObject());
} else {
return pht(
'%s renamed %s from %s to %s.',
$this->renderAuthor(),
$this->renderObject(),
$this->renderValue($old),
$this->renderValue($new));
}
}
public function getColor() {
$old = $this->getOldValue();
if ($old === null) {
return PhabricatorTransactions::COLOR_GREEN;
}
return parent::getColor();
}
public function validateTransactions($object, array $xactions) {
$errors = array();
if ($this->isEmptyTextTransaction($object->getName(), $xactions)) {
$errors[] = $this->newRequiredError(pht('Mocks 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(
'Mock names must not be longer than %s character(s).',
new PhutilNumber($max_length)));
}
}
return $errors;
}
}

View file

@ -0,0 +1,66 @@
<?php
final class PholioMockStatusTransaction
extends PholioMockTransactionType {
const TRANSACTIONTYPE = 'status';
public function generateOldValue($object) {
return $object->getStatus();
}
public function applyInternalEffects($object, $value) {
$object->setStatus($value);
}
public function getTitle() {
$new = $this->getNewValue();
if ($new == PholioMock::STATUS_CLOSED) {
return pht(
'%s closed this mock.',
$this->renderAuthor());
} else {
return pht(
'%s opened this mock.',
$this->renderAuthor());
}
}
public function getTitleForFeed() {
$new = $this->getNewValue();
if ($new == PholioMock::STATUS_CLOSED) {
return pht(
'%s closed mock %s.',
$this->renderAuthor(),
$this->renderObject());
} else {
return pht(
'%s opened mock %s.',
$this->renderAuthor(),
$this->renderObject());
}
}
public function getIcon() {
$new = $this->getNewValue();
if ($new == PholioMock::STATUS_CLOSED) {
return 'fa-ban';
} else {
return 'fa-check';
}
}
public function getColor() {
$new = $this->getNewValue();
if ($new == PholioMock::STATUS_CLOSED) {
return PhabricatorTransactions::COLOR_INDIGO;
} else {
return PhabricatorTransactions::COLOR_GREEN;
}
}
}

View file

@ -0,0 +1,4 @@
<?php
abstract class PholioMockTransactionType
extends PholioTransactionType {}

View file

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

View file

@ -65,6 +65,11 @@ final class PhortuneMerchantEditEngine
return false;
}
protected function getCreateNewObjectPolicy() {
return $this->getApplication()->getPolicy(
PhortuneMerchantCapability::CAPABILITY);
}
protected function buildCustomEditFields($object) {
$viewer = $this->getViewer();

View file

@ -71,7 +71,7 @@ final class PonderAnswerEditor extends PonderEditor {
foreach ($xactions as $xaction) {
$type = $xaction->getTransactionType();
$new = $xaction->getNewValue();
if ($type == PonderAnswerTransaction::TYPE_CONTENT) {
if ($type == PonderAnswerContentTransaction::TRANSACTIONTYPE) {
$body->addRawSection($new);
}
}

View file

@ -28,6 +28,7 @@ final class PhabricatorProjectBoardBackgroundController
$this->setProject($board);
$id = $board->getID();
$view_uri = $this->getApplicationURI("board/{$id}/");
$manage_uri = $this->getApplicationURI("board/{$id}/manage/");
if ($request->isFormPost()) {
@ -47,7 +48,7 @@ final class PhabricatorProjectBoardBackgroundController
->applyTransactions($board, $xactions);
return id(new AphrontRedirectResponse())
->setURI($manage_uri);
->setURI($view_uri);
}
$nav = $this->getProfileMenu();

View file

@ -31,112 +31,58 @@ final class PhabricatorProjectBoardManageController
$board_id = $board->getID();
$header = $this->buildHeaderView($board);
$actions = $this->buildActionView($board);
$properties = $this->buildPropertyView($board);
$properties->setActionList($actions);
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(pht('Workboard'), "/project/board/{$board_id}/");
$crumbs->addTextCrumb(pht('Manage'));
$box = id(new PHUIObjectBoxView())
->setHeader($header)
->addPropertyList($properties);
$crumbs->setBorder(true);
$nav = $this->getProfileMenu();
$columns_list = $this->buildColumnsList($board, $columns);
$view = id(new PHUITwoColumnView())
->setHeader($header)
->setFooter($columns_list);
$title = array(
pht('Manage Workboard'),
$board->getDisplayName(),
);
$columns_list = $this->buildColumnsList($board, $columns);
return $this->newPage()
->setTitle($title)
->setNavigation($nav)
->setCrumbs($crumbs)
->appendChild(
array(
$box,
$columns_list,
));
->appendChild($view);
}
private function buildHeaderView(PhabricatorProject $board) {
$viewer = $this->getRequest()->getUser();
$header = id(new PHUIHeaderView())
->setUser($viewer)
->setHeader(pht('Workboard: %s', $board->getDisplayName()));
return $header;
}
private function buildActionView(PhabricatorProject $board) {
$viewer = $this->getRequest()->getUser();
$id = $board->getID();
$actions = id(new PhabricatorActionListView())
->setUser($viewer);
$viewer = $this->getViewer();
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$board,
PhabricatorPolicyCapability::CAN_EDIT);
$reorder_uri = $this->getApplicationURI("board/{$id}/reorder/");
$actions->addAction(
id(new PhabricatorActionView())
->setIcon('fa-exchange')
->setName(pht('Reorder Columns'))
->setHref($reorder_uri)
->setDisabled(!$can_edit)
->setWorkflow(true));
$background_uri = $this->getApplicationURI("board/{$id}/background/");
$actions->addAction(
id(new PhabricatorActionView())
->setIcon('fa-paint-brush')
->setName(pht('Change Background Color'))
->setHref($background_uri)
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit));
$id = $board->getID();
$disable_uri = $this->getApplicationURI("board/{$id}/disable/");
$actions->addAction(
id(new PhabricatorActionView())
->setIcon('fa-ban')
->setName(pht('Disable Board'))
->setHref($disable_uri)
->setDisabled(!$can_edit)
->setWorkflow(true));
$button = id(new PHUIButtonView())
->setTag('a')
->setIcon('fa-ban')
->setText(pht('Disable Board'))
->setHref($disable_uri)
->setDisabled(!$can_edit)
->setWorkflow(true);
return $actions;
}
private function buildPropertyView(
PhabricatorProject $board) {
$viewer = $this->getRequest()->getUser();
$properties = id(new PHUIPropertyListView())
$header = id(new PHUIHeaderView())
->setHeader(pht('Workboard: %s', $board->getDisplayName()))
->setUser($viewer)
->setObject($board);
->setPolicyObject($board)
->setProfileHeader(true)
->addActionLink($button);
$background = $board->getDisplayWorkboardBackgroundColor();
if ($background !== null) {
$map = PhabricatorProjectWorkboardBackgroundColor::getOptions();
$map = ipull($map, 'name');
$name = idx($map, $background, $background);
$properties->addProperty(pht('Background Color'), $name);
}
return $properties;
return $header;
}
private function buildColumnsList(
@ -165,6 +111,11 @@ final class PhabricatorProjectBoardManageController
if ($column->isHidden()) {
$item->setDisabled(true);
$item->addAttribute(pht('Hidden'));
$item->setImageIcon('fa-columns grey');
} else {
$item->addAttribute(pht('Visible'));
$item->setImageIcon('fa-columns');
}
$view->addItem($item);

View file

@ -23,13 +23,13 @@ final class PhabricatorProjectBoardReorderController
$this->setProject($project);
$project_id = $project->getID();
$manage_uri = $this->getApplicationURI("board/{$project_id}/manage/");
$view_uri = $this->getApplicationURI("board/{$project_id}/");
$reorder_uri = $this->getApplicationURI("board/{$project_id}/reorder/");
if ($request->isFormPost()) {
// User clicked "Done", make sure the page reloads to show the new
// column order.
return id(new AphrontRedirectResponse())->setURI($manage_uri);
return id(new AphrontRedirectResponse())->setURI($view_uri);
}
$columns = id(new PhabricatorProjectColumnQuery())

View file

@ -705,10 +705,21 @@ final class PhabricatorProjectBoardViewController
->setDisabled(!$can_edit)
->setWorkflow(true);
$reorder_uri = $this->getApplicationURI("board/{$id}/reorder/");
$manage_items[] = id(new PhabricatorActionView())
->setIcon('fa-pencil')
->setName(pht('Manage Board'))
->setHref($manage_uri);
->setIcon('fa-exchange')
->setName(pht('Reorder Columns'))
->setHref($reorder_uri)
->setDisabled(!$can_edit)
->setWorkflow(true);
$background_uri = $this->getApplicationURI("board/{$id}/background/");
$manage_items[] = id(new PhabricatorActionView())
->setIcon('fa-paint-brush')
->setName(pht('Change Background Color'))
->setHref($background_uri)
->setDisabled(!$can_edit)
->setWorkflow(false);
if ($show_hidden) {
$hidden_uri = $this->getURIWithState()
@ -727,6 +738,12 @@ final class PhabricatorProjectBoardViewController
->setName($hidden_text)
->setHref($hidden_uri);
$manage_uri = $this->getApplicationURI("board/{$id}/manage/");
$manage_items[] = id(new PhabricatorActionView())
->setIcon('fa-gear')
->setName(pht('Manage Workboard'))
->setHref($manage_uri);
$batch_edit_uri = $request->getRequestURI();
$batch_edit_uri->setQueryParam('batch', self::BATCH_EDIT_ALL);
$can_batch_edit = PhabricatorPolicyFilter::hasCapability(
@ -734,12 +751,6 @@ final class PhabricatorProjectBoardViewController
PhabricatorApplication::getByClass('PhabricatorManiphestApplication'),
ManiphestBulkEditCapability::CAPABILITY);
$manage_items[] = id(new PhabricatorActionView())
->setIcon('fa-list-ul')
->setName(pht('Batch Edit Visible Tasks...'))
->setHref($batch_edit_uri)
->setDisabled(!$can_batch_edit);
$manage_menu = id(new PhabricatorActionListView())
->setUser($viewer);
foreach ($manage_items as $item) {
@ -837,6 +848,16 @@ final class PhabricatorProjectBoardViewController
->setHref($batch_edit_uri)
->setDisabled(!$can_batch_edit);
// Column Related Actions Below
//
$edit_uri = 'board/'.$this->id.'/edit/'.$column->getID().'/';
$column_items[] = id(new PhabricatorActionView())
->setName(pht('Edit Column'))
->setIcon('fa-pencil')
->setHref($this->getApplicationURI($edit_uri))
->setDisabled(!$can_edit)
->setWorkflow(true);
$can_hide = ($can_edit && !$column->isDefaultColumn());
$hide_uri = 'board/'.$this->id.'/hide/'.$column->getID().'/';
$hide_uri = $this->getApplicationURI($hide_uri);
@ -858,6 +879,12 @@ final class PhabricatorProjectBoardViewController
->setWorkflow(true);
}
$details_uri = 'board/'.$this->id.'/column/'.$column->getID().'/';
$column_items[] = id(new PhabricatorActionView())
->setName(pht('Column History'))
->setIcon('fa-columns')
->setHref($this->getApplicationURI($details_uri));
$column_menu = id(new PhabricatorActionListView())
->setUser($viewer);
foreach ($column_items as $item) {

View file

@ -103,7 +103,7 @@ final class PhabricatorProjectColumnDetailController
->setIcon('fa-pencil')
->setHref($this->getApplicationURI($base_uri.'edit/'.$id.'/'))
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit));
->setWorkflow(true));
return $actions;
}

View file

@ -51,12 +51,7 @@ final class PhabricatorProjectColumnEditController
$validation_exception = null;
$base_uri = '/board/'.$project_id.'/';
if ($is_new) {
// we want to go back to the board
$view_uri = $this->getApplicationURI($base_uri);
} else {
$view_uri = $this->getApplicationURI($base_uri.'column/'.$id.'/');
}
$view_uri = $this->getApplicationURI($base_uri);
if ($request->isFormPost()) {
$v_name = $request->getStr('name');

View file

@ -21,8 +21,7 @@ final class PhabricatorProjectManageController
$header = id(new PHUIHeaderView())
->setHeader(pht('Project History'))
->setUser($viewer)
->setPolicyObject($project)
->setImage($picture);
->setPolicyObject($project);
if ($project->getStatus() == PhabricatorProjectStatus::STATUS_ACTIVE) {
$header->setStatus('fa-check', 'bluegrey', pht('Active'));
@ -45,10 +44,14 @@ final class PhabricatorProjectManageController
$crumbs->addTextCrumb(pht('Manage'));
$crumbs->setBorder(true);
require_celerity_resource('project-view-css');
$manage = id(new PHUITwoColumnView())
->setHeader($header)
->setCurtain($curtain)
->addPropertySection(pht('Details'), $properties)
->addClass('project-view-home')
->addClass('project-view-people-home')
->setMainColumn(
array(
$timeline,

View file

@ -29,7 +29,6 @@ final class PhabricatorProjectProfileController
->setHeader(array($project->getDisplayName(), $tag))
->setUser($viewer)
->setPolicyObject($project)
->setImage($picture)
->setProfileHeader(true);
if ($project->getStatus() == PhabricatorProjectStatus::STATUS_ACTIVE) {
@ -92,6 +91,7 @@ final class PhabricatorProjectProfileController
$home = id(new PHUITwoColumnView())
->setHeader($header)
->addClass('project-view-home')
->addClass('project-view-people-home')
->setMainColumn(
array(
$properties,

View file

@ -20,6 +20,10 @@ final class PhabricatorProjectProfileMenuEngine
protected function getBuiltinProfileItems($object) {
$items = array();
$items[] = $this->newItem()
->setBuiltinKey(PhabricatorProject::ITEM_PICTURE)
->setMenuItemKey(PhabricatorProjectPictureProfileMenuItem::MENUITEMKEY);
$items[] = $this->newItem()
->setBuiltinKey(PhabricatorProject::ITEM_PROFILE)
->setMenuItemKey(PhabricatorProjectDetailsProfileMenuItem::MENUITEMKEY);

View file

@ -46,15 +46,15 @@ final class PhabricatorProjectDetailsProfileMenuItem
$project = $config->getProfileObject();
$id = $project->getID();
$picture = $project->getProfileImageURI();
$name = $project->getName();
$icon = $project->getDisplayIconIcon();
$href = "/project/profile/{$id}/";
$item = $this->newItem()
->setHref($href)
->setName($name)
->setProfileImage($picture);
->setIcon($icon);
return array(
$item,

View file

@ -0,0 +1,69 @@
<?php
final class PhabricatorProjectPictureProfileMenuItem
extends PhabricatorProfileMenuItem {
const MENUITEMKEY = 'project.picture';
public function getMenuItemTypeName() {
return pht('Project Picture');
}
private function getDefaultName() {
return pht('Project Picture');
}
public function canHideMenuItem(
PhabricatorProfileMenuItemConfiguration $config) {
return false;
}
public function getDisplayName(
PhabricatorProfileMenuItemConfiguration $config) {
return $this->getDefaultName();
}
public function buildEditEngineFields(
PhabricatorProfileMenuItemConfiguration $config) {
return array();
}
protected function newNavigationMenuItems(
PhabricatorProfileMenuItemConfiguration $config) {
$project = $config->getProfileObject();
require_celerity_resource('people-picture-menu-item-css');
$picture = $project->getProfileImageURI();
$href = $project->getProfileURI();
$classes = array();
$classes[] = 'people-menu-image';
if ($project->isArchived()) {
$classes[] = 'phui-image-disabled';
}
$photo = phutil_tag(
'img',
array(
'src' => $picture,
'class' => implode(' ', $classes),
));
$view = phutil_tag_div('people-menu-image-container', $photo);
$view = phutil_tag(
'a',
array(
'href' => $href,
),
$view);
$item = $this->newItem()
->appendChild($view);
return array(
$item,
);
}
}

View file

@ -128,6 +128,10 @@ final class PhabricatorProjectSearchEngine
$names['joined'] = pht('Joined');
}
if ($this->requireViewer()->isLoggedIn()) {
$names['watching'] = pht('Watching');
}
$names['active'] = pht('Active');
$names['all'] = pht('All');
@ -153,6 +157,10 @@ final class PhabricatorProjectSearchEngine
return $query
->setParameter('memberPHIDs', array($viewer_phid))
->setParameter('status', 'active');
case 'watching':
return $query
->setParameter('watcherPHIDs', array($viewer_phid))
->setParameter('status', 'active');
}
return parent::buildSavedQueryFromBuiltin($query_key);

View file

@ -49,6 +49,7 @@ final class PhabricatorProject extends PhabricatorProjectDAO
const TABLE_DATASOURCE_TOKEN = 'project_datasourcetoken';
const ITEM_PICTURE = 'project.picture';
const ITEM_PROFILE = 'project.profile';
const ITEM_POINTS = 'project.points';
const ITEM_WORKBOARD = 'project.workboard';

View file

@ -68,7 +68,13 @@ final class PhabricatorSlowvoteEditController
}
if ($is_new) {
$responses = array_filter($responses);
// NOTE: Make sure common and useful response "0" is preserved.
foreach ($responses as $key => $response) {
if (!strlen($response)) {
unset($responses[$key]);
}
}
if (empty($responses)) {
$errors[] = pht('You must offer at least one response.');
$e_response = pht('Required');
@ -139,13 +145,14 @@ final class PhabricatorSlowvoteEditController
}
return id(new AphrontRedirectResponse())
->setURI('/V'.$poll->getID());
->setURI($poll->getURI());
} else {
$poll->setViewPolicy($v_view_policy);
}
}
$form = id(new AphrontFormView())
->setAction($request->getrequestURI())
->setUser($viewer)
->appendChild(
id(new AphrontFormTextControl())

View file

@ -35,9 +35,9 @@ final class PhabricatorSlowvotePollController
));
}
$header_icon = $poll->getIsClosed() ? 'fa-ban' : 'fa-circle-o';
$header_icon = $poll->getIsClosed() ? 'fa-ban' : 'fa-square-o';
$header_name = $poll->getIsClosed() ? pht('Closed') : pht('Open');
$header_color = $poll->getIsClosed() ? 'dark' : 'bluegrey';
$header_color = $poll->getIsClosed() ? 'indigo' : 'bluegrey';
$header = id(new PHUIHeaderView())
->setHeader($poll->getQuestion())
@ -89,7 +89,7 @@ final class PhabricatorSlowvotePollController
$is_closed = $poll->getIsClosed();
$close_poll_text = $is_closed ? pht('Reopen Poll') : pht('Close Poll');
$close_poll_icon = $is_closed ? 'fa-play-circle-o' : 'fa-ban';
$close_poll_icon = $is_closed ? 'fa-check' : 'fa-ban';
$curtain->addAction(
id(new PhabricatorActionView())

View file

@ -11,6 +11,14 @@ final class PhabricatorSlowvoteEditor
return pht('Slowvote');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this poll.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;

View file

@ -55,6 +55,7 @@ final class PhabricatorSlowvoteSearchEngine
id(new PhabricatorSearchCheckboxesField())
->setKey('statuses')
->setLabel(pht('Statuses'))
->setOptions(array(
'open' => pht('Open'),
'closed' => pht('Closed'),

View file

@ -112,6 +112,10 @@ final class PhabricatorSlowvotePoll extends PhabricatorSlowvoteDAO
return 'V'.$this->getID();
}
public function getURI() {
return '/'.$this->getMonogram();
}
public function save() {
if (!$this->getMailKey()) {
$this->setMailKey(Filesystem::readRandomCharacters(20));

View file

@ -36,15 +36,21 @@ final class PhabricatorSlowvoteDescriptionTransaction
}
}
public function hasChangeDetails() {
public function hasChangeDetailView() {
return true;
}
public function getMailDiffSectionHeader() {
return pht('CHANGES TO POLL DESCRIPTION');
}
public function newChangeDetailView() {
return $this->renderTextCorpusChangeDetails(
$this->getViewer(),
$this->getOldValue(),
$this->getNewValue());
$viewer = $this->getViewer();
return id(new PhabricatorApplicationTransactionTextDiffDetailView())
->setViewer($viewer)
->setOldText($this->getOldValue())
->setNewText($this->getNewValue());
}
public function newRemarkupChanges() {

View file

@ -4,6 +4,7 @@ final class PhabricatorSubscriptionsEditEngineExtension
extends PhabricatorEditEngineExtension {
const EXTENSIONKEY = 'subscriptions.subscribers';
const FIELDKEY = 'subscriberPHIDs';
const EDITKEY_ADD = 'subscribers.add';
const EDITKEY_SET = 'subscribers.set';
@ -42,7 +43,7 @@ final class PhabricatorSubscriptionsEditEngineExtension
}
$subscribers_field = id(new PhabricatorSubscribersEditField())
->setKey('subscriberPHIDs')
->setKey(self::FIELDKEY)
->setLabel(pht('Subscribers'))
->setEditTypeKey('subscribers')
->setAliases(array('subscriber', 'subscribers'))

View file

@ -30,15 +30,47 @@ final class PHUIFormFileControl
'chunkThreshold' => PhabricatorFileStorageEngine::getChunkThreshold(),
));
return phutil_tag(
'input',
array(
'type' => 'file',
'multiple' => $this->getAllowMultiple() ? 'multiple' : null,
'name' => $this->getName().'.raw',
'id' => $file_id,
'disabled' => $this->getDisabled() ? 'disabled' : null,
));
// If the control has a value, add a hidden input which submits it as a
// default. This allows the file control to mean "don't change anything",
// instead of "remove the file", if the user submits the form without
// touching it.
// This also allows the input to "hold" the value of an uploaded file if
// there is another error in the form: when you submit the form but are
// stopped because of an unrelated error, submitting it again will keep
// the value around (if you don't upload a new file) instead of requiring
// you to pick the file again.
// TODO: This works alright, but is a bit of a hack, and the UI should
// provide the user better feedback about whether the state of the control
// is "keep the value the same" or "remove the value", and about whether
// or not the control is "holding" a value from a previous submission.
$default_input = null;
$default_value = $this->getValue();
if ($default_value !== null) {
$default_input = phutil_tag(
'input',
array(
'type' => 'hidden',
'name' => $this->getName().'_default',
'value' => $default_value,
));
}
return array(
phutil_tag(
'input',
array(
'type' => 'file',
'multiple' => $this->getAllowMultiple() ? 'multiple' : null,
'name' => $this->getName().'_raw',
'id' => $file_id,
'disabled' => $this->getDisabled() ? 'disabled' : null,
)),
$default_input,
);
}
}