Correct Aphlict websocket URI construction after PHP8 compatibility changes
[phabricator.git] / src / applications / policy / rule / PhabricatorPolicyRule.php
blob2f9fac9cfbec6cdf1e174457ac2dd9244055560c
1 <?php
3 /**
4 * @task objectpolicy Implementing Object Policies
5 */
6 abstract class PhabricatorPolicyRule extends Phobject {
8 const CONTROL_TYPE_TEXT = 'text';
9 const CONTROL_TYPE_SELECT = 'select';
10 const CONTROL_TYPE_TOKENIZER = 'tokenizer';
11 const CONTROL_TYPE_NONE = 'none';
13 abstract public function getRuleDescription();
15 public function willApplyRules(
16 PhabricatorUser $viewer,
17 array $values,
18 array $objects) {
19 return;
22 abstract public function applyRule(
23 PhabricatorUser $viewer,
24 $value,
25 PhabricatorPolicyInterface $object);
27 public function getValueControlType() {
28 return self::CONTROL_TYPE_TEXT;
31 public function getValueControlTemplate() {
32 return null;
35 /**
36 * Return `true` if this rule can be applied to the given object.
38 * Some policy rules may only operation on certain kinds of objects. For
39 * example, a "task author" rule can only operate on tasks.
41 public function canApplyToObject(PhabricatorPolicyInterface $object) {
42 return true;
45 protected function getDatasourceTemplate(
46 PhabricatorTypeaheadDatasource $datasource) {
48 return array(
49 'markup' => new AphrontTokenizerTemplateView(),
50 'uri' => $datasource->getDatasourceURI(),
51 'placeholder' => $datasource->getPlaceholderText(),
52 'browseURI' => $datasource->getBrowseURI(),
56 public function getRuleOrder() {
57 return 500;
60 public function getValueForStorage($value) {
61 return $value;
64 public function getValueForDisplay(PhabricatorUser $viewer, $value) {
65 return $value;
68 public function getRequiredHandlePHIDsForSummary($value) {
69 $phids = array();
71 switch ($this->getValueControlType()) {
72 case self::CONTROL_TYPE_TOKENIZER:
73 $phids = $value;
74 break;
75 case self::CONTROL_TYPE_TEXT:
76 case self::CONTROL_TYPE_SELECT:
77 case self::CONTROL_TYPE_NONE:
78 default:
79 if (phid_get_type($value) !=
80 PhabricatorPHIDConstants::PHID_TYPE_UNKNOWN) {
81 $phids = array($value);
82 } else {
83 $phids = array();
85 break;
88 return $phids;
91 /**
92 * Return `true` if the given value creates a rule with a meaningful effect.
93 * An example of a rule with no meaningful effect is a "users" rule with no
94 * users specified.
96 * @return bool True if the value creates a meaningful rule.
98 public function ruleHasEffect($value) {
99 return true;
103 /* -( Transaction Hints )-------------------------------------------------- */
107 * Tell policy rules about upcoming transaction effects.
109 * Before transaction effects are applied, we try to stop users from making
110 * edits which will lock them out of objects. We can't do this perfectly,
111 * since they can set a policy to "the moon is full" moments before it wanes,
112 * but we try to prevent as many mistakes as possible.
114 * Some policy rules depend on complex checks against object state which
115 * we can't set up ahead of time. For example, subscriptions require database
116 * writes.
118 * In cases like this, instead of doing writes, you can pass a hint about an
119 * object to a policy rule. The rule can then look for hints and use them in
120 * rendering a verdict about whether the user will be able to see the object
121 * or not after applying the policy change.
123 * @param PhabricatorPolicyInterface Object to pass a hint about.
124 * @param PhabricatorPolicyRule Rule to pass hint to.
125 * @param wild Hint.
126 * @return void
128 public static function passTransactionHintToRule(
129 PhabricatorPolicyInterface $object,
130 PhabricatorPolicyRule $rule,
131 $hint) {
133 $cache = PhabricatorCaches::getRequestCache();
134 $cache->setKey(self::getObjectPolicyCacheKey($object, $rule), $hint);
137 final protected function getTransactionHint(
138 PhabricatorPolicyInterface $object) {
140 $cache = PhabricatorCaches::getRequestCache();
141 return $cache->getKey(self::getObjectPolicyCacheKey($object, $this));
144 private static function getObjectPolicyCacheKey(
145 PhabricatorPolicyInterface $object,
146 PhabricatorPolicyRule $rule) {
148 // NOTE: This is quite a bit of a hack, but we don't currently have a
149 // better way to carry hints from the TransactionEditor into PolicyRules
150 // about pending policy changes.
152 // Put some magic secret unique value on each object so we can pass
153 // information about it by proxy. This allows us to test if pending
154 // edits to an object will cause policy violations or not, before allowing
155 // those edits to go through.
157 // Some better approaches might be:
158 // - Use traits to give `PhabricatorPolicyInterface` objects real
159 // storage (requires PHP 5.4.0).
160 // - Wrap policy objects in a container with extra storage which the
161 // policy filter knows how to unbox (lots of work).
163 // When this eventually gets cleaned up, the corresponding hack in
164 // LiskDAO->__set() should also be cleaned up.
165 static $id = 0;
166 if (!isset($object->_hashKey)) {
167 @$object->_hashKey = 'object.id('.(++$id).')';
170 return $object->_hashKey;
174 /* -( Implementing Object Policies )--------------------------------------- */
178 * Return a unique string like "maniphest.author" to expose this rule as an
179 * object policy.
181 * Object policy rules, like "Task Author", are more advanced than basic
182 * policy rules (like "All Users") but not as powerful as custom rules.
184 * @return string Unique identifier for this rule.
185 * @task objectpolicy
187 public function getObjectPolicyKey() {
188 return null;
191 final public function getObjectPolicyFullKey() {
192 $key = $this->getObjectPolicyKey();
194 if (!$key) {
195 throw new Exception(
196 pht(
197 'This policy rule (of class "%s") does not have an associated '.
198 'object policy key.',
199 get_class($this)));
202 return PhabricatorPolicyQuery::OBJECT_POLICY_PREFIX.$key;
205 public function getObjectPolicyName() {
206 throw new PhutilMethodNotImplementedException();
209 public function getObjectPolicyShortName() {
210 return $this->getObjectPolicyName();
213 public function getObjectPolicyIcon() {
214 return 'fa-cube';
217 public function getPolicyExplanation() {
218 throw new PhutilMethodNotImplementedException();