@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.

Merge branch 'master' into redesign-2015

+227 -33
+10 -6
src/applications/differential/query/DifferentialRevisionQuery.php
··· 771 771 $this->updatedEpochMax); 772 772 } 773 773 774 + // NOTE: Although the status constants are integers in PHP, the column is a 775 + // string column in MySQL, and MySQL won't use keys on string columns if 776 + // you put integers in the query. 777 + 774 778 switch ($this->status) { 775 779 case self::STATUS_ANY: 776 780 break; 777 781 case self::STATUS_OPEN: 778 782 $where[] = qsprintf( 779 783 $conn_r, 780 - 'r.status IN (%Ld)', 784 + 'r.status IN (%Ls)', 781 785 DifferentialRevisionStatus::getOpenStatuses()); 782 786 break; 783 787 case self::STATUS_NEEDS_REVIEW: 784 788 $where[] = qsprintf( 785 789 $conn_r, 786 - 'r.status IN (%Ld)', 790 + 'r.status IN (%Ls)', 787 791 array( 788 792 ArcanistDifferentialRevisionStatus::NEEDS_REVIEW, 789 793 )); ··· 791 795 case self::STATUS_NEEDS_REVISION: 792 796 $where[] = qsprintf( 793 797 $conn_r, 794 - 'r.status IN (%Ld)', 798 + 'r.status IN (%Ls)', 795 799 array( 796 800 ArcanistDifferentialRevisionStatus::NEEDS_REVISION, 797 801 )); ··· 799 803 case self::STATUS_ACCEPTED: 800 804 $where[] = qsprintf( 801 805 $conn_r, 802 - 'r.status IN (%Ld)', 806 + 'r.status IN (%Ls)', 803 807 array( 804 808 ArcanistDifferentialRevisionStatus::ACCEPTED, 805 809 )); ··· 807 811 case self::STATUS_CLOSED: 808 812 $where[] = qsprintf( 809 813 $conn_r, 810 - 'r.status IN (%Ld)', 814 + 'r.status IN (%Ls)', 811 815 DifferentialRevisionStatus::getClosedStatuses()); 812 816 break; 813 817 case self::STATUS_ABANDONED: 814 818 $where[] = qsprintf( 815 819 $conn_r, 816 - 'r.status IN (%Ld)', 820 + 'r.status IN (%Ls)', 817 821 array( 818 822 ArcanistDifferentialRevisionStatus::ABANDONED, 819 823 ));
+8
src/applications/differential/storage/DifferentialRevision.php
··· 102 102 'repositoryPHID' => array( 103 103 'columns' => array('repositoryPHID'), 104 104 ), 105 + // If you (or a project you are a member of) is reviewing a significant 106 + // fraction of the revisions on an install, the result set of open 107 + // revisions may be smaller than the result set of revisions where you 108 + // are a reviewer. In these cases, this key is better than keys on the 109 + // edge table. 110 + 'key_status' => array( 111 + 'columns' => array('status', 'phid'), 112 + ), 105 113 ), 106 114 ) + parent::getConfiguration(); 107 115 }
+31
src/applications/policy/__tests__/PhabricatorPolicyTestCase.php
··· 353 353 $this->assertEqual(array(), $result); 354 354 } 355 355 356 + public function testPolicyStrength() { 357 + $public = PhabricatorPolicyQuery::getGlobalPolicy( 358 + PhabricatorPolicies::POLICY_PUBLIC); 359 + $user = PhabricatorPolicyQuery::getGlobalPolicy( 360 + PhabricatorPolicies::POLICY_USER); 361 + $admin = PhabricatorPolicyQuery::getGlobalPolicy( 362 + PhabricatorPolicies::POLICY_ADMIN); 363 + $noone = PhabricatorPolicyQuery::getGlobalPolicy( 364 + PhabricatorPolicies::POLICY_NOONE); 365 + 366 + $this->assertFalse($public->isStrongerThan($public)); 367 + $this->assertFalse($public->isStrongerThan($user)); 368 + $this->assertFalse($public->isStrongerThan($admin)); 369 + $this->assertFalse($public->isStrongerThan($noone)); 370 + 371 + $this->assertTrue($user->isStrongerThan($public)); 372 + $this->assertFalse($user->isStrongerThan($user)); 373 + $this->assertFalse($user->isStrongerThan($admin)); 374 + $this->assertFalse($user->isStrongerThan($noone)); 375 + 376 + $this->assertTrue($admin->isStrongerThan($public)); 377 + $this->assertTrue($admin->isStrongerThan($user)); 378 + $this->assertFalse($admin->isStrongerThan($admin)); 379 + $this->assertFalse($admin->isStrongerThan($noone)); 380 + 381 + $this->assertTrue($noone->isStrongerThan($public)); 382 + $this->assertTrue($noone->isStrongerThan($user)); 383 + $this->assertTrue($noone->isStrongerThan($admin)); 384 + $this->assertFalse($admin->isStrongerThan($noone)); 385 + } 386 + 356 387 357 388 /** 358 389 * Test an object for visibility across multiple user specifications.
+98 -27
src/applications/policy/controller/PhabricatorPolicyExplainController.php
··· 69 69 $capability_name = $capobj->getCapabilityName(); 70 70 } 71 71 72 - $space_info = null; 73 - if ($object instanceof PhabricatorSpacesInterface) { 74 - if (PhabricatorSpacesNamespaceQuery::getViewerSpacesExist($viewer)) { 75 - $space_phid = PhabricatorSpacesNamespaceQuery::getObjectSpacePHID( 76 - $object); 77 - 78 - $handles = $viewer->loadHandles(array($space_phid)); 72 + $dialog = id(new AphrontDialogView()) 73 + ->setUser($viewer) 74 + ->setClass('aphront-access-dialog'); 79 75 80 - $space_info = array( 81 - pht( 82 - 'This object is in %s, and can only be seen by users with '. 83 - 'access to that space.', 84 - $handles[$space_phid]->renderLink()), 85 - phutil_tag('br'), 86 - phutil_tag('br'), 87 - ); 88 - } 89 - } 76 + $this->appendSpaceInformation($dialog, $object, $policy, $capability); 90 77 91 - $content = array( 92 - $space_info, 93 - pht('Users with the "%s" capability:', $capability_name), 94 - $auto_info, 95 - ); 78 + $intro = pht( 79 + 'Users with the "%s" capability for this object:', 80 + $capability_name); 96 81 97 82 $object_name = pht( 98 83 '%s %s', 99 84 $handle->getTypeName(), 100 85 $handle->getObjectName()); 101 86 102 - $dialog = id(new AphrontDialogView()) 103 - ->setUser($viewer) 104 - ->setClass('aphront-access-dialog') 87 + return $dialog 105 88 ->setTitle(pht('Policy Details: %s', $object_name)) 106 - ->appendChild($content) 89 + ->appendParagraph($intro) 90 + ->appendChild($auto_info) 107 91 ->addCancelButton($object_uri, pht('Done')); 92 + } 93 + 94 + private function appendSpaceInformation( 95 + AphrontDialogView $dialog, 96 + PhabricatorPolicyInterface $object, 97 + PhabricatorPolicy $policy, 98 + $capability) { 99 + $viewer = $this->getViewer(); 100 + 101 + if (!($object instanceof PhabricatorSpacesInterface)) { 102 + return; 103 + } 108 104 109 - return id(new AphrontDialogResponse())->setDialog($dialog); 105 + if (!PhabricatorSpacesNamespaceQuery::getSpacesExist($viewer)) { 106 + return; 107 + } 108 + 109 + // NOTE: We're intentionally letting users through here, even if they only 110 + // have access to one space. The intent is to help users in "space jail" 111 + // understand who objects they create are visible to: 112 + 113 + $space_phid = PhabricatorSpacesNamespaceQuery::getObjectSpacePHID( 114 + $object); 115 + 116 + $handles = $viewer->loadHandles(array($space_phid)); 117 + $doc_href = PhabricatorEnv::getDoclink('Spaces User Guide'); 118 + 119 + $dialog->appendParagraph( 120 + array( 121 + pht( 122 + 'This object is in %s, and can only be seen or edited by users with '. 123 + 'access to view objects in the space.', 124 + $handles[$space_phid]->renderLink()), 125 + ' ', 126 + phutil_tag( 127 + 'strong', 128 + array(), 129 + phutil_tag( 130 + 'a', 131 + array( 132 + 'href' => $doc_href, 133 + 'target' => '_blank', 134 + ), 135 + pht('Learn More'))), 136 + )); 137 + 138 + $spaces = PhabricatorSpacesNamespaceQuery::getViewerSpaces($viewer); 139 + $space = idx($spaces, $space_phid); 140 + if (!$space) { 141 + return; 142 + } 143 + 144 + $space_policies = PhabricatorPolicyQuery::loadPolicies($viewer, $space); 145 + $space_policy = idx($space_policies, PhabricatorPolicyCapability::CAN_VIEW); 146 + if (!$space_policy) { 147 + return; 148 + } 149 + 150 + $space_explanation = PhabricatorPolicy::getPolicyExplanation( 151 + $viewer, 152 + $space_policy->getPHID()); 153 + $items = array(); 154 + $items[] = $space_explanation; 155 + 156 + foreach ($items as $key => $item) { 157 + $items[$key] = phutil_tag('li', array(), $item); 158 + } 159 + 160 + $dialog->appendParagraph(pht('Users who can see objects in this space:')); 161 + $dialog->appendChild(phutil_tag('ul', array(), $items)); 162 + 163 + $view_capability = PhabricatorPolicyCapability::CAN_VIEW; 164 + if ($capability == $view_capability) { 165 + $stronger = $space_policy->isStrongerThan($policy); 166 + if ($stronger) { 167 + $dialog->appendParagraph( 168 + pht( 169 + 'The space this object is in has a more restrictive view '. 170 + 'policy ("%s") than the object does ("%s"), so the space\'s '. 171 + 'view policy is shown as a hint instead of the object policy.', 172 + $space_policy->getShortName(), 173 + $policy->getShortName())); 174 + } 175 + } 176 + 177 + $dialog->appendParagraph( 178 + pht( 179 + 'After a user passes space policy checks, they must still pass '. 180 + 'object policy checks.')); 110 181 } 111 182 112 183 }
+54
src/applications/policy/storage/PhabricatorPolicy.php
··· 362 362 } 363 363 364 364 365 + /** 366 + * Return `true` if this policy is stronger (more restrictive) than some 367 + * other policy. 368 + * 369 + * Because policies are complicated, determining which policies are 370 + * "stronger" is not trivial. This method uses a very coarse working 371 + * definition of policy strength which is cheap to compute, unambiguous, 372 + * and intuitive in the common cases. 373 + * 374 + * This method returns `true` if the //class// of this policy is stronger 375 + * than the other policy, even if the policies are (or might be) the same in 376 + * practice. For example, "Members of Project X" is considered a stronger 377 + * policy than "All Users", even though "Project X" might (in some rare 378 + * cases) contain every user. 379 + * 380 + * Generally, the ordering here is: 381 + * 382 + * - Public 383 + * - All Users 384 + * - (Everything Else) 385 + * - No One 386 + * 387 + * In the "everything else" bucket, we can't make any broad claims about 388 + * which policy is stronger (and we especially can't make those claims 389 + * cheaply). 390 + * 391 + * Even if we fully evaluated each policy, the two policies might be 392 + * "Members of X" and "Members of Y", each of which permits access to some 393 + * set of unique users. In this case, neither is strictly stronger than 394 + * the other. 395 + * 396 + * @param PhabricatorPolicy Other policy. 397 + * @return bool `true` if this policy is more restrictive than the other 398 + * policy. 399 + */ 400 + public function isStrongerThan(PhabricatorPolicy $other) { 401 + $this_policy = $this->getPHID(); 402 + $other_policy = $other->getPHID(); 403 + 404 + $strengths = array( 405 + PhabricatorPolicies::POLICY_PUBLIC => -2, 406 + PhabricatorPolicies::POLICY_USER => -1, 407 + // (Default policies have strength 0.) 408 + PhabricatorPolicies::POLICY_NOONE => 1, 409 + ); 410 + 411 + $this_strength = idx($strengths, $this->getPHID(), 0); 412 + $other_strength = idx($strengths, $other->getPHID(), 0); 413 + 414 + return ($this_strength > $other_strength); 415 + } 416 + 417 + 418 + 365 419 /* -( PhabricatorPolicyInterface )----------------------------------------- */ 366 420 367 421
+26
src/view/phui/PHUIHeaderView.php
··· 355 355 return null; 356 356 } 357 357 358 + // If an object is in a Space with a strictly stronger (more restrictive) 359 + // policy, we show the more restrictive policy. This better aligns the 360 + // UI hint with the actual behavior. 361 + 362 + // NOTE: We'll do this even if the viewer has access to only one space, and 363 + // show them information about the existence of spaces if they click 364 + // through. 365 + if ($object instanceof PhabricatorSpacesInterface) { 366 + $space_phid = PhabricatorSpacesNamespaceQuery::getObjectSpacePHID( 367 + $object); 368 + 369 + $spaces = PhabricatorSpacesNamespaceQuery::getViewerSpaces($viewer); 370 + $space = idx($spaces, $space_phid); 371 + if ($space) { 372 + $space_policies = PhabricatorPolicyQuery::loadPolicies( 373 + $viewer, 374 + $space); 375 + $space_policy = idx($space_policies, $view_capability); 376 + if ($space_policy) { 377 + if ($space_policy->isStrongerThan($policy)) { 378 + $policy = $space_policy; 379 + } 380 + } 381 + } 382 + } 383 + 358 384 $phid = $object->getPHID(); 359 385 360 386 $icon = id(new PHUIIconView())