mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-24 06:20:56 +01:00
Add "does not match regexp" to Herald
Summary: Fixes T10330. - Anywhere we support "matches regexp", also allow "does not match regexp". Although you can sometimes write a clever negative regexp, these rules are better expressed with "does not match <simple regexp>" anyway, and sometimes no regexp will work. - Always allow "does not contain" when we support "contains". - Fix some JS issues with certain rules affecting custom fields. Test Plan: - Wrote an "Affected files do not match regexp" rule that required every diff to touch "MANUALCHANGELOG.md". - Tried to diff without the file; rejected. - Tried to diff with the file; accepted. - Wrote a bunch of "contains" and "does not contain" rules against text fields and custom fields, then edited tasks to trigger/observe them. - Swapped the editor into custom text, user, remarkup, etc fields, no more JS errors. {F1105172} Reviewers: chad Reviewed By: chad Maniphest Tasks: T10330 Differential Revision: https://secure.phabricator.com/D15254
This commit is contained in:
parent
8661170819
commit
8934dee543
10 changed files with 78 additions and 8 deletions
|
@ -14,6 +14,7 @@ abstract class HeraldAdapter extends Phobject {
|
||||||
const CONDITION_IS_ME = 'me';
|
const CONDITION_IS_ME = 'me';
|
||||||
const CONDITION_IS_NOT_ME = '!me';
|
const CONDITION_IS_NOT_ME = '!me';
|
||||||
const CONDITION_REGEXP = 'regexp';
|
const CONDITION_REGEXP = 'regexp';
|
||||||
|
const CONDITION_NOT_REGEXP = '!regexp';
|
||||||
const CONDITION_RULE = 'conditions';
|
const CONDITION_RULE = 'conditions';
|
||||||
const CONDITION_NOT_RULE = '!conditions';
|
const CONDITION_NOT_RULE = '!conditions';
|
||||||
const CONDITION_EXISTS = 'exists';
|
const CONDITION_EXISTS = 'exists';
|
||||||
|
@ -322,6 +323,7 @@ abstract class HeraldAdapter extends Phobject {
|
||||||
self::CONDITION_IS_ME => pht('is myself'),
|
self::CONDITION_IS_ME => pht('is myself'),
|
||||||
self::CONDITION_IS_NOT_ME => pht('is not myself'),
|
self::CONDITION_IS_NOT_ME => pht('is not myself'),
|
||||||
self::CONDITION_REGEXP => pht('matches regexp'),
|
self::CONDITION_REGEXP => pht('matches regexp'),
|
||||||
|
self::CONDITION_NOT_REGEXP => pht('does not match regexp'),
|
||||||
self::CONDITION_RULE => pht('matches:'),
|
self::CONDITION_RULE => pht('matches:'),
|
||||||
self::CONDITION_NOT_RULE => pht('does not match:'),
|
self::CONDITION_NOT_RULE => pht('does not match:'),
|
||||||
self::CONDITION_EXISTS => pht('exists'),
|
self::CONDITION_EXISTS => pht('exists'),
|
||||||
|
@ -364,16 +366,18 @@ abstract class HeraldAdapter extends Phobject {
|
||||||
|
|
||||||
switch ($condition_type) {
|
switch ($condition_type) {
|
||||||
case self::CONDITION_CONTAINS:
|
case self::CONDITION_CONTAINS:
|
||||||
// "Contains" can take an array of strings, as in "Any changed
|
case self::CONDITION_NOT_CONTAINS:
|
||||||
// filename" for diffs.
|
// "Contains and "does not contain" can take an array of strings, as in
|
||||||
|
// "Any changed filename" for diffs.
|
||||||
|
|
||||||
|
$result_if_match = ($condition_type == self::CONDITION_CONTAINS);
|
||||||
|
|
||||||
foreach ((array)$field_value as $value) {
|
foreach ((array)$field_value as $value) {
|
||||||
if (stripos($value, $condition_value) !== false) {
|
if (stripos($value, $condition_value) !== false) {
|
||||||
return true;
|
return $result_if_match;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return !$result_if_match;
|
||||||
case self::CONDITION_NOT_CONTAINS:
|
|
||||||
return (stripos($field_value, $condition_value) === false);
|
|
||||||
case self::CONDITION_IS:
|
case self::CONDITION_IS:
|
||||||
return ($field_value == $condition_value);
|
return ($field_value == $condition_value);
|
||||||
case self::CONDITION_IS_NOT:
|
case self::CONDITION_IS_NOT:
|
||||||
|
@ -427,6 +431,9 @@ abstract class HeraldAdapter extends Phobject {
|
||||||
case self::CONDITION_NEVER:
|
case self::CONDITION_NEVER:
|
||||||
return false;
|
return false;
|
||||||
case self::CONDITION_REGEXP:
|
case self::CONDITION_REGEXP:
|
||||||
|
case self::CONDITION_NOT_REGEXP:
|
||||||
|
$result_if_match = ($condition_type == self::CONDITION_REGEXP);
|
||||||
|
|
||||||
foreach ((array)$field_value as $value) {
|
foreach ((array)$field_value as $value) {
|
||||||
// We add the 'S' flag because we use the regexp multiple times.
|
// We add the 'S' flag because we use the regexp multiple times.
|
||||||
// It shouldn't cause any troubles if the flag is already there
|
// It shouldn't cause any troubles if the flag is already there
|
||||||
|
@ -437,10 +444,10 @@ abstract class HeraldAdapter extends Phobject {
|
||||||
pht('Regular expression is not valid!'));
|
pht('Regular expression is not valid!'));
|
||||||
}
|
}
|
||||||
if ($result) {
|
if ($result) {
|
||||||
return true;
|
return $result_if_match;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return !$result_if_match;
|
||||||
case self::CONDITION_REGEXP_PAIR:
|
case self::CONDITION_REGEXP_PAIR:
|
||||||
// Match a JSON-encoded pair of regular expressions against a
|
// Match a JSON-encoded pair of regular expressions against a
|
||||||
// dictionary. The first regexp must match the dictionary key, and the
|
// dictionary. The first regexp must match the dictionary key, and the
|
||||||
|
@ -509,6 +516,7 @@ abstract class HeraldAdapter extends Phobject {
|
||||||
|
|
||||||
switch ($condition_type) {
|
switch ($condition_type) {
|
||||||
case self::CONDITION_REGEXP:
|
case self::CONDITION_REGEXP:
|
||||||
|
case self::CONDITION_NOT_REGEXP:
|
||||||
$ok = @preg_match($condition_value, '');
|
$ok = @preg_match($condition_value, '');
|
||||||
if ($ok === false) {
|
if ($ok === false) {
|
||||||
throw new HeraldInvalidConditionException(
|
throw new HeraldInvalidConditionException(
|
||||||
|
|
|
@ -47,6 +47,7 @@ abstract class HeraldField extends Phobject {
|
||||||
HeraldAdapter::CONDITION_IS,
|
HeraldAdapter::CONDITION_IS,
|
||||||
HeraldAdapter::CONDITION_IS_NOT,
|
HeraldAdapter::CONDITION_IS_NOT,
|
||||||
HeraldAdapter::CONDITION_REGEXP,
|
HeraldAdapter::CONDITION_REGEXP,
|
||||||
|
HeraldAdapter::CONDITION_NOT_REGEXP,
|
||||||
);
|
);
|
||||||
case self::STANDARD_PHID:
|
case self::STANDARD_PHID:
|
||||||
return array(
|
return array(
|
||||||
|
@ -76,12 +77,16 @@ abstract class HeraldField extends Phobject {
|
||||||
case self::STANDARD_TEXT_LIST:
|
case self::STANDARD_TEXT_LIST:
|
||||||
return array(
|
return array(
|
||||||
HeraldAdapter::CONDITION_CONTAINS,
|
HeraldAdapter::CONDITION_CONTAINS,
|
||||||
|
HeraldAdapter::CONDITION_NOT_CONTAINS,
|
||||||
HeraldAdapter::CONDITION_REGEXP,
|
HeraldAdapter::CONDITION_REGEXP,
|
||||||
|
HeraldAdapter::CONDITION_NOT_REGEXP,
|
||||||
);
|
);
|
||||||
case self::STANDARD_TEXT_MAP:
|
case self::STANDARD_TEXT_MAP:
|
||||||
return array(
|
return array(
|
||||||
HeraldAdapter::CONDITION_CONTAINS,
|
HeraldAdapter::CONDITION_CONTAINS,
|
||||||
|
HeraldAdapter::CONDITION_NOT_CONTAINS,
|
||||||
HeraldAdapter::CONDITION_REGEXP,
|
HeraldAdapter::CONDITION_REGEXP,
|
||||||
|
HeraldAdapter::CONDITION_NOT_REGEXP,
|
||||||
HeraldAdapter::CONDITION_REGEXP_PAIR,
|
HeraldAdapter::CONDITION_REGEXP_PAIR,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1446,5 +1446,19 @@ abstract class PhabricatorCustomField extends Phobject {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getHeraldFieldStandardType() {
|
||||||
|
if ($this->proxy) {
|
||||||
|
return $this->proxy->getHeraldFieldStandardType();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getHeraldDatasource() {
|
||||||
|
if ($this->proxy) {
|
||||||
|
return $this->proxy->getHeraldDatasource();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,8 +65,20 @@ final class PhabricatorCustomFieldHeraldField extends HeraldField {
|
||||||
return $this->getCustomField()->getHeraldFieldConditions();
|
return $this->getCustomField()->getHeraldFieldConditions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getHeraldFieldStandardType() {
|
||||||
|
return $this->getCustomField()->getHeraldFieldStandardType();
|
||||||
|
}
|
||||||
|
|
||||||
public function getHeraldFieldValueType($condition) {
|
public function getHeraldFieldValueType($condition) {
|
||||||
|
if ($this->getHeraldFieldStandardType()) {
|
||||||
|
return parent::getHeraldFieldValueType($condition);
|
||||||
|
}
|
||||||
|
|
||||||
return $this->getCustomField()->getHeraldFieldValueType($condition);
|
return $this->getCustomField()->getHeraldFieldValueType($condition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getDatasource() {
|
||||||
|
return $this->getCustomField()->getHeraldDatasource();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,6 +129,10 @@ final class PhabricatorStandardCustomFieldBool
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getHeraldFieldStandardType() {
|
||||||
|
return HeraldField::STANDARD_BOOL;
|
||||||
|
}
|
||||||
|
|
||||||
protected function getHTTPParameterType() {
|
protected function getHTTPParameterType() {
|
||||||
return new AphrontBoolHTTPParameterType();
|
return new AphrontBoolHTTPParameterType();
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,9 +77,14 @@ final class PhabricatorStandardCustomFieldLink
|
||||||
HeraldAdapter::CONDITION_IS,
|
HeraldAdapter::CONDITION_IS,
|
||||||
HeraldAdapter::CONDITION_IS_NOT,
|
HeraldAdapter::CONDITION_IS_NOT,
|
||||||
HeraldAdapter::CONDITION_REGEXP,
|
HeraldAdapter::CONDITION_REGEXP,
|
||||||
|
HeraldAdapter::CONDITION_NOT_REGEXP,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getHeraldFieldStandardType() {
|
||||||
|
return HeraldField::STANDARD_TEXT;
|
||||||
|
}
|
||||||
|
|
||||||
protected function getHTTPParameterType() {
|
protected function getHTTPParameterType() {
|
||||||
return new AphrontStringHTTPParameterType();
|
return new AphrontStringHTTPParameterType();
|
||||||
}
|
}
|
||||||
|
|
|
@ -241,6 +241,10 @@ abstract class PhabricatorStandardCustomFieldPHIDs
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getHeraldFieldStandardType() {
|
||||||
|
return HeraldField::STANDARD_PHID_NULLABLE;
|
||||||
|
}
|
||||||
|
|
||||||
public function getHeraldFieldValue() {
|
public function getHeraldFieldValue() {
|
||||||
// If the field has a `null` value, make sure we hand an `array()` to
|
// If the field has a `null` value, make sure we hand an `array()` to
|
||||||
// Herald.
|
// Herald.
|
||||||
|
|
|
@ -92,9 +92,14 @@ final class PhabricatorStandardCustomFieldRemarkup
|
||||||
HeraldAdapter::CONDITION_IS,
|
HeraldAdapter::CONDITION_IS,
|
||||||
HeraldAdapter::CONDITION_IS_NOT,
|
HeraldAdapter::CONDITION_IS_NOT,
|
||||||
HeraldAdapter::CONDITION_REGEXP,
|
HeraldAdapter::CONDITION_REGEXP,
|
||||||
|
HeraldAdapter::CONDITION_NOT_REGEXP,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getHeraldFieldStandardType() {
|
||||||
|
return HeraldField::STANDARD_TEXT;
|
||||||
|
}
|
||||||
|
|
||||||
protected function getHTTPParameterType() {
|
protected function getHTTPParameterType() {
|
||||||
return new AphrontStringHTTPParameterType();
|
return new AphrontStringHTTPParameterType();
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,9 +60,14 @@ final class PhabricatorStandardCustomFieldText
|
||||||
HeraldAdapter::CONDITION_IS,
|
HeraldAdapter::CONDITION_IS,
|
||||||
HeraldAdapter::CONDITION_IS_NOT,
|
HeraldAdapter::CONDITION_IS_NOT,
|
||||||
HeraldAdapter::CONDITION_REGEXP,
|
HeraldAdapter::CONDITION_REGEXP,
|
||||||
|
HeraldAdapter::CONDITION_NOT_REGEXP,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getHeraldFieldStandardType() {
|
||||||
|
return HeraldField::STANDARD_TEXT;
|
||||||
|
}
|
||||||
|
|
||||||
protected function getHTTPParameterType() {
|
protected function getHTTPParameterType() {
|
||||||
return new AphrontStringHTTPParameterType();
|
return new AphrontStringHTTPParameterType();
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,4 +44,12 @@ abstract class PhabricatorStandardCustomFieldTokenizer
|
||||||
->setDatasource($this->getDatasource());
|
->setDatasource($this->getDatasource());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getHeraldFieldStandardType() {
|
||||||
|
return HeraldField::STANDARD_PHID_LIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getHeraldDatasource() {
|
||||||
|
return $this->getDatasource();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue