1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
|
<?php
namespace MediaWiki\Extension\AbuseFilter\Filter;
use Wikimedia\Assert\Assert;
/**
* Immutable value object that represents a single filter. This object can be used to represent
* filters that do not necessarily exist in the database. You'll usually want to use subclasses.
*/
class AbstractFilter {
/** @var Specs */
protected $specs;
/** @var Flags */
protected $flags;
/**
* @var array[]|null Actions and parameters, can be lazy-loaded with $actionsCallback
*/
protected $actions;
/**
* @var callable|null
* @todo Evaluate whether this can be avoided, e.g. by using a JOIN. This property also makes
* the class not serializable.
*/
protected $actionsCallback;
/**
* @param Specs $specs
* @param Flags $flags
* @param callable|array[] $actions Array with params or callable that will return them
* @phan-param array[]|callable():array[] $actions
*/
public function __construct(
Specs $specs,
Flags $flags,
$actions
) {
$this->specs = clone $specs;
$this->flags = clone $flags;
Assert::parameterType( 'callable|array', $actions, '$actions' );
if ( is_callable( $actions ) ) {
$this->actionsCallback = $actions;
} elseif ( is_array( $actions ) ) {
$this->setActions( $actions );
}
}
/**
* @return Specs
*/
public function getSpecs(): Specs {
return clone $this->specs;
}
/**
* @return Flags
*/
public function getFlags(): Flags {
return clone $this->flags;
}
/**
* @return string
*/
public function getRules(): string {
return $this->specs->getRules();
}
/**
* @return string
*/
public function getComments(): string {
return $this->specs->getComments();
}
/**
* @return string
*/
public function getName(): string {
return $this->specs->getName();
}
/**
* @note Callers should not rely on the order, because it's nondeterministic.
* @return string[]
*/
public function getActionsNames(): array {
return $this->specs->getActionsNames();
}
/**
* @return string
*/
public function getGroup(): string {
return $this->specs->getGroup();
}
/**
* @return bool
*/
public function isEnabled(): bool {
return $this->flags->getEnabled();
}
/**
* @return bool
*/
public function isDeleted(): bool {
return $this->flags->getDeleted();
}
/**
* @return bool
*/
public function isHidden(): bool {
return $this->flags->getHidden();
}
/**
* @return bool
*/
public function isProtected(): bool {
return $this->flags->getProtected();
}
/**
* @return int
*/
public function getPrivacyLevel(): int {
return $this->flags->getPrivacyLevel();
}
/**
* @return bool
*/
public function isGlobal(): bool {
return $this->flags->getGlobal();
}
/**
* @return array[]
*/
public function getActions(): array {
if ( $this->actions === null ) {
$this->setActions( call_user_func( $this->actionsCallback ) );
// This is to ease testing
$this->actionsCallback = null;
}
return $this->actions;
}
/**
* @param array $actions
*/
protected function setActions( array $actions ): void {
$this->actions = $actions;
$this->specs->setActionsNames( array_keys( $actions ) );
}
/**
* Make sure we don't leave any (writeable) reference
*/
public function __clone() {
$this->specs = clone $this->specs;
$this->flags = clone $this->flags;
}
}
|