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

Configure Feed

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

Give Phortune merchants explicit members

Summary:
Ref T2787. Make this a little more concrete with explicit membership instead of a general edit policy. In particular, we need to know who to email when orders happen, and can't reasonably do that with an edit policy.

I imagine this might eventually get more nuanced (e.g., users who can only approve orders vs users who can manage the merchant itself) but that's a long ways away.

Test Plan: {F216284}

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T2787

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

+216 -21
+2
resources/sql/autopatches/20141011.phortunemerchedit.sql
··· 1 + ALTER TABLE {$NAMESPACE}_phortune.phortune_merchant 2 + DROP editPolicy;
+4
src/__phutil_library_map__.php
··· 2582 2582 'PhortuneErrCode' => 'applications/phortune/constants/PhortuneErrCode.php', 2583 2583 'PhortuneLandingController' => 'applications/phortune/controller/PhortuneLandingController.php', 2584 2584 'PhortuneMemberHasAccountEdgeType' => 'applications/phortune/edge/PhortuneMemberHasAccountEdgeType.php', 2585 + 'PhortuneMemberHasMerchantEdgeType' => 'applications/phortune/edge/PhortuneMemberHasMerchantEdgeType.php', 2585 2586 'PhortuneMerchant' => 'applications/phortune/storage/PhortuneMerchant.php', 2586 2587 'PhortuneMerchantCapability' => 'applications/phortune/capability/PhortuneMerchantCapability.php', 2587 2588 'PhortuneMerchantController' => 'applications/phortune/controller/PhortuneMerchantController.php', 2588 2589 'PhortuneMerchantEditController' => 'applications/phortune/controller/PhortuneMerchantEditController.php', 2589 2590 'PhortuneMerchantEditor' => 'applications/phortune/editor/PhortuneMerchantEditor.php', 2591 + 'PhortuneMerchantHasMemberEdgeType' => 'applications/phortune/edge/PhortuneMerchantHasMemberEdgeType.php', 2590 2592 'PhortuneMerchantListController' => 'applications/phortune/controller/PhortuneMerchantListController.php', 2591 2593 'PhortuneMerchantPHIDType' => 'applications/phortune/phid/PhortuneMerchantPHIDType.php', 2592 2594 'PhortuneMerchantQuery' => 'applications/phortune/query/PhortuneMerchantQuery.php', ··· 5644 5646 'PhortuneErrCode' => 'PhortuneConstants', 5645 5647 'PhortuneLandingController' => 'PhortuneController', 5646 5648 'PhortuneMemberHasAccountEdgeType' => 'PhabricatorEdgeType', 5649 + 'PhortuneMemberHasMerchantEdgeType' => 'PhabricatorEdgeType', 5647 5650 'PhortuneMerchant' => array( 5648 5651 'PhortuneDAO', 5649 5652 'PhabricatorPolicyInterface', ··· 5652 5655 'PhortuneMerchantController' => 'PhortuneController', 5653 5656 'PhortuneMerchantEditController' => 'PhortuneMerchantController', 5654 5657 'PhortuneMerchantEditor' => 'PhabricatorApplicationTransactionEditor', 5658 + 'PhortuneMerchantHasMemberEdgeType' => 'PhabricatorEdgeType', 5655 5659 'PhortuneMerchantListController' => 'PhortuneMerchantController', 5656 5660 'PhortuneMerchantPHIDType' => 'PhabricatorPHIDType', 5657 5661 'PhortuneMerchantQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
+1 -5
src/applications/phortune/controller/PhortuneAccountListController.php
··· 18 18 19 19 $merchants = id(new PhortuneMerchantQuery()) 20 20 ->setViewer($viewer) 21 - ->requireCapabilities( 22 - array( 23 - PhabricatorPolicyCapability::CAN_VIEW, 24 - PhabricatorPolicyCapability::CAN_EDIT, 25 - )) 21 + ->withMemberPHIDs(array($viewer->getPHID())) 26 22 ->execute(); 27 23 28 24 $title = pht('Accounts');
+23 -10
src/applications/phortune/controller/PhortuneMerchantEditController.php
··· 32 32 PhortuneMerchantCapability::CAPABILITY); 33 33 34 34 $merchant = PhortuneMerchant::initializeNewMerchant($viewer); 35 + $merchant->attachMemberPHIDs(array($viewer->getPHID())); 35 36 $is_new = true; 36 37 } 37 38 ··· 52 53 $e_name = true; 53 54 $v_name = $merchant->getName(); 54 55 $v_desc = $merchant->getDescription(); 56 + $v_members = $merchant->getMemberPHIDs(); 57 + $e_members = null; 55 58 56 59 $validation_exception = null; 57 60 if ($request->isFormPost()) { ··· 59 62 $v_desc = $request->getStr('desc'); 60 63 $v_view = $request->getStr('viewPolicy'); 61 64 $v_edit = $request->getStr('editPolicy'); 65 + $v_members = $request->getArr('memberPHIDs'); 62 66 63 67 $type_name = PhortuneMerchantTransaction::TYPE_NAME; 64 68 $type_desc = PhortuneMerchantTransaction::TYPE_DESCRIPTION; 69 + $type_edge = PhabricatorTransactions::TYPE_EDGE; 65 70 $type_view = PhabricatorTransactions::TYPE_VIEW_POLICY; 66 - $type_edit = PhabricatorTransactions::TYPE_EDIT_POLICY; 71 + 72 + $edge_members = PhortuneMerchantHasMemberEdgeType::EDGECONST; 67 73 68 74 $xactions = array(); 69 75 ··· 80 86 ->setNewValue($v_view); 81 87 82 88 $xactions[] = id(new PhortuneMerchantTransaction()) 83 - ->setTransactionType($type_edit) 84 - ->setNewValue($v_edit); 89 + ->setTransactionType($type_edge) 90 + ->setMetadataValue('edge:type', $edge_members) 91 + ->setNewValue( 92 + array( 93 + '=' => array_fuse($v_members), 94 + )); 85 95 86 96 $editor = id(new PhortuneMerchantEditor()) 87 97 ->setActor($viewer) ··· 98 108 $validation_exception = $ex; 99 109 100 110 $e_name = $ex->getShortMessage($type_name); 111 + $e_mbmers = $ex->getShortMessage($type_edge); 101 112 102 113 $merchant->setViewPolicy($v_view); 103 - $merchant->setEditPolicy($v_edit); 104 114 } 105 115 } 106 116 ··· 108 118 ->setViewer($viewer) 109 119 ->setObject($merchant) 110 120 ->execute(); 121 + 122 + $member_handles = $this->loadViewerHandles($v_members); 111 123 112 124 $form = id(new AphrontFormView()) 113 125 ->setUser($viewer) ··· 123 135 ->setLabel(pht('Description')) 124 136 ->setValue($v_desc)) 125 137 ->appendChild( 138 + id(new AphrontFormTokenizerControl()) 139 + ->setDatasource(new PhabricatorPeopleDatasource()) 140 + ->setLabel(pht('Members')) 141 + ->setName('memberPHIDs') 142 + ->setValue($member_handles) 143 + ->setError($e_members)) 144 + ->appendChild( 126 145 id(new AphrontFormPolicyControl()) 127 146 ->setName('viewPolicy') 128 147 ->setPolicyObject($merchant) 129 148 ->setCapability(PhabricatorPolicyCapability::CAN_VIEW) 130 - ->setPolicies($policies)) 131 - ->appendChild( 132 - id(new AphrontFormPolicyControl()) 133 - ->setName('editPolicy') 134 - ->setPolicyObject($merchant) 135 - ->setCapability(PhabricatorPolicyCapability::CAN_EDIT) 136 149 ->setPolicies($policies)) 137 150 ->appendChild( 138 151 id(new AphrontFormSubmitControl())
+6
src/applications/phortune/controller/PhortuneMerchantViewController.php
··· 140 140 141 141 $view->addProperty(pht('Status'), $status_view); 142 142 143 + $this->loadHandles($merchant->getMemberPHIDs()); 144 + 145 + $view->addProperty( 146 + pht('Members'), 147 + $this->renderHandlesForPHIDs($merchant->getMemberPHIDs())); 148 + 143 149 $view->invokeWillRenderEvent(); 144 150 145 151 $description = $merchant->getDescription();
+12
src/applications/phortune/edge/PhortuneMemberHasMerchantEdgeType.php
··· 1 + <?php 2 + 3 + final class PhortuneMemberHasMerchantEdgeType 4 + extends PhabricatorEdgeType { 5 + 6 + const EDGECONST = 54; 7 + 8 + public function getInverseEdgeConstant() { 9 + return PhortuneMerchantHasMemberEdgeType::EDGECONST; 10 + } 11 + 12 + }
+101
src/applications/phortune/edge/PhortuneMerchantHasMemberEdgeType.php
··· 1 + <?php 2 + 3 + final class PhortuneMerchantHasMemberEdgeType extends PhabricatorEdgeType { 4 + 5 + const EDGECONST = 53; 6 + 7 + public function getInverseEdgeConstant() { 8 + return PhortuneMemberHasMerchantEdgeType::EDGECONST; 9 + } 10 + 11 + public function getTransactionAddString( 12 + $actor, 13 + $add_count, 14 + $add_edges) { 15 + 16 + return pht( 17 + '%s added %s merchant member(s): %s.', 18 + $actor, 19 + $add_count, 20 + $add_edges); 21 + } 22 + 23 + public function getTransactionRemoveString( 24 + $actor, 25 + $rem_count, 26 + $rem_edges) { 27 + 28 + return pht( 29 + '%s removed %s merchant member(s): %s.', 30 + $actor, 31 + $rem_count, 32 + $rem_edges); 33 + } 34 + 35 + public function getTransactionEditString( 36 + $actor, 37 + $total_count, 38 + $add_count, 39 + $add_edges, 40 + $rem_count, 41 + $rem_edges) { 42 + 43 + return pht( 44 + '%s edited %s merchant member(s), added %s: %s; removed %s: %s.', 45 + $actor, 46 + $total_count, 47 + $add_count, 48 + $add_edges, 49 + $rem_count, 50 + $rem_edges); 51 + } 52 + 53 + public function getFeedAddString( 54 + $actor, 55 + $object, 56 + $add_count, 57 + $add_edges) { 58 + 59 + return pht( 60 + '%s added %s merchant member(s) to %s: %s.', 61 + $actor, 62 + $add_count, 63 + $object, 64 + $add_edges); 65 + } 66 + 67 + public function getFeedRemoveString( 68 + $actor, 69 + $object, 70 + $rem_count, 71 + $rem_edges) { 72 + 73 + return pht( 74 + '%s removed %s merchant member(s) from %s: %s.', 75 + $actor, 76 + $rem_count, 77 + $object, 78 + $rem_edges); 79 + } 80 + 81 + public function getFeedEditString( 82 + $actor, 83 + $object, 84 + $total_count, 85 + $add_count, 86 + $add_edges, 87 + $rem_count, 88 + $rem_edges) { 89 + 90 + return pht( 91 + '%s edited %s merchant member(s) for %s, added %s: %s; removed %s: %s.', 92 + $actor, 93 + $total_count, 94 + $object, 95 + $add_count, 96 + $add_edges, 97 + $rem_count, 98 + $rem_edges); 99 + } 100 + 101 + }
+4 -1
src/applications/phortune/editor/PhortuneMerchantEditor.php
··· 17 17 $types[] = PhortuneMerchantTransaction::TYPE_NAME; 18 18 $types[] = PhortuneMerchantTransaction::TYPE_DESCRIPTION; 19 19 $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; 20 - $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; 20 + $types[] = PhabricatorTransactions::TYPE_EDGE; 21 21 22 22 return $types; 23 23 } ··· 59 59 case PhortuneMerchantTransaction::TYPE_DESCRIPTION: 60 60 $object->setDescription($xaction->getNewValue()); 61 61 return; 62 + case PhabricatorTransactions::TYPE_EDGE: 63 + return; 62 64 } 63 65 64 66 return parent::applyCustomInternalTransaction($object, $xaction); ··· 71 73 switch ($xaction->getTransactionType()) { 72 74 case PhortuneMerchantTransaction::TYPE_NAME: 73 75 case PhortuneMerchantTransaction::TYPE_DESCRIPTION: 76 + case PhabricatorTransactions::TYPE_EDGE: 74 77 return; 75 78 } 76 79
+44 -1
src/applications/phortune/query/PhortuneMerchantQuery.php
··· 5 5 6 6 private $ids; 7 7 private $phids; 8 + private $memberPHIDs; 8 9 9 10 public function withIDs(array $ids) { 10 11 $this->ids = $ids; ··· 13 14 14 15 public function withPHIDs(array $phids) { 15 16 $this->phids = $phids; 17 + return $this; 18 + } 19 + 20 + public function withMemberPHIDs(array $member_phids) { 21 + $this->memberPHIDs = $member_phids; 16 22 return $this; 17 23 } 18 24 ··· 22 28 23 29 $rows = queryfx_all( 24 30 $conn, 25 - 'SELECT * FROM %T %Q %Q %Q', 31 + 'SELECT m.* FROM %T m %Q %Q %Q %Q', 26 32 $table->getTableName(), 33 + $this->buildJoinClause($conn), 27 34 $this->buildWhereClause($conn), 28 35 $this->buildOrderClause($conn), 29 36 $this->buildLimitClause($conn)); ··· 31 38 return $table->loadAllFromArray($rows); 32 39 } 33 40 41 + protected function willFilterPage(array $merchants) { 42 + $query = id(new PhabricatorEdgeQuery()) 43 + ->withSourcePHIDs(mpull($merchants, 'getPHID')) 44 + ->withEdgeTypes(array(PhortuneMerchantHasMemberEdgeType::EDGECONST)); 45 + $query->execute(); 46 + 47 + foreach ($merchants as $merchant) { 48 + $member_phids = $query->getDestinationPHIDs(array($merchant->getPHID())); 49 + $member_phids = array_reverse($member_phids); 50 + $merchant->attachMemberPHIDs($member_phids); 51 + } 52 + 53 + return $merchants; 54 + } 55 + 34 56 private function buildWhereClause(AphrontDatabaseConnection $conn) { 35 57 $where = array(); 36 58 ··· 48 70 $this->phids); 49 71 } 50 72 73 + if ($this->memberPHIDs !== null) { 74 + $where[] = qsprintf( 75 + $conn, 76 + 'e.dst IN (%Ls)', 77 + $this->memberPHIDs); 78 + } 79 + 51 80 $where[] = $this->buildPagingClause($conn); 52 81 53 82 return $this->formatWhereClause($where); 83 + } 84 + 85 + private function buildJoinClause(AphrontDatabaseConnection $conn) { 86 + $joins = array(); 87 + 88 + if ($this->memberPHIDs !== null) { 89 + $joins[] = qsprintf( 90 + $conn, 91 + 'LEFT JOIN %T e ON m.phid = e.src AND e.type = %d', 92 + PhabricatorEdgeConfig::TABLE_NAME_EDGE, 93 + PhortuneMerchantHasMemberEdgeType::EDGECONST); 94 + } 95 + 96 + return implode(' ', $joins); 54 97 } 55 98 56 99 public function getQueryApplicationClass() {
+19 -4
src/applications/phortune/storage/PhortuneMerchant.php
··· 5 5 6 6 protected $name; 7 7 protected $viewPolicy; 8 - protected $editPolicy; 9 8 protected $description; 9 + 10 + private $memberPHIDs = self::ATTACHABLE; 10 11 11 12 public static function initializeNewMerchant(PhabricatorUser $actor) { 12 13 return id(new PhortuneMerchant()) 13 14 ->setViewPolicy(PhabricatorPolicies::getMostOpenPolicy()) 14 - ->setEditPolicy($actor->getPHID()); 15 + ->attachMemberPHIDs(array()); 15 16 } 16 17 17 18 public function getConfiguration() { ··· 29 30 PhortuneMerchantPHIDType::TYPECONST); 30 31 } 31 32 33 + public function getMemberPHIDs() { 34 + return $this->assertAttached($this->memberPHIDs); 35 + } 36 + 37 + public function attachMemberPHIDs(array $member_phids) { 38 + $this->memberPHIDs = $member_phids; 39 + return $this; 40 + } 41 + 32 42 33 43 /* -( PhabricatorPolicyInterface )----------------------------------------- */ 34 44 ··· 45 55 case PhabricatorPolicyCapability::CAN_VIEW: 46 56 return $this->getViewPolicy(); 47 57 case PhabricatorPolicyCapability::CAN_EDIT: 48 - return $this->getEditPolicy(); 58 + return PhabricatorPolicies::POLICY_NOONE; 49 59 } 50 60 } 51 61 52 62 public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { 63 + $members = array_fuse($this->getMemberPHIDs()); 64 + if (isset($members[$viewer->getPHID()])) { 65 + return true; 66 + } 67 + 53 68 return false; 54 69 } 55 70 56 71 public function describeAutomaticCapability($capability) { 57 - return null; 72 + return pht("A merchant's members an always view and edit it."); 58 73 } 59 74 60 75 }