Skip to content
Snippets Groups Projects

Issue #2986466: Add support for a wildcard parameter and a case-sensitive option

3 files
+ 192
25
Compare changes
  • Side-by-side
  • Inline
Files
3
@@ -18,6 +18,20 @@ use Symfony\Component\HttpFoundation\RequestStack;
*/
class RequestParam extends ConditionPluginBase implements ContainerFactoryPluginInterface {
/**
* The wildcard token.
*
* @var string
*/
const TOKEN_WILDCARD = '*';
/**
* The wildcard exclusion token.
*
* @var string
*/
const TOKEN_WILDCARD_EXCLUSION = '\\';
/**
* The request stack.
*
@@ -57,7 +71,10 @@ class RequestParam extends ConditionPluginBase implements ContainerFactoryPlugin
* {@inheritdoc}
*/
public function defaultConfiguration() {
return ['request_param' => ''] + parent::defaultConfiguration();
return [
'request_param' => '',
'case_sensitive' => FALSE,
] + parent::defaultConfiguration();
}
/**
@@ -68,11 +85,21 @@ class RequestParam extends ConditionPluginBase implements ContainerFactoryPlugin
'#type' => 'textarea',
'#title' => $this->t('Query Parameters'),
'#default_value' => $this->configuration['request_param'],
'#description' => $this->t("Specify the request parameters. Enter one parameter per line. Examples: %example_1 and %example_2.", [
'#description' => $this->t("Specify the request parameters. Enter one parameter per line. The '*' character acts as a wildcard. Examples: %example_1, %example_2, %example_3 and %example_4.", [
'%example_1' => 'visibility=show',
'%example_2' => 'visibility[]=show',
'%example_3' => 'page=* (all pages)',
'%example_4' => 'page=*\0,1,2 (all pages but the first three)',
]),
];
$form['case_sensitive'] = [
'#type' => 'checkbox',
'#title' => $this->t('Case sensitive'),
'#default_value' => $this->configuration['case_sensitive'],
'#description' => $this->t('Apply case sensitive evaluation.'),
];
return parent::buildConfigurationForm($form, $form_state);
}
@@ -81,6 +108,7 @@ class RequestParam extends ConditionPluginBase implements ContainerFactoryPlugin
*/
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
$this->configuration['request_param'] = $form_state->getValue('request_param');
$this->configuration['case_sensitive'] = (bool) $form_state->getValue('case_sensitive');
parent::submitConfigurationForm($form, $form_state);
}
@@ -100,38 +128,110 @@ class RequestParam extends ConditionPluginBase implements ContainerFactoryPlugin
* {@inheritdoc}
*/
public function evaluate() {
// Convert params to lowercase.
$params = mb_strtolower($this->configuration['request_param']);
if (!$params) {
// Evaluate to TRUE if no parameters are available.
$parameters = $this->getConfiguredParameters();
if (empty($parameters)) {
return TRUE;
}
$request = $this->requestStack->getCurrentRequest();
parse_str(preg_replace('/\n|\r\n?/', '&', $params), $request_params);
if (!empty($request_params)) {
foreach ($request_params as $key => $values) {
if (!is_array($values)) {
$values = [$values];
}
$query_param_value = $request->get($key);
if (!isset($query_param_value)) {
continue;
}
if (is_array($query_param_value)) {
foreach ($query_param_value as $array_value) {
if (in_array($array_value, $values)) {
return TRUE;
}
}
}
elseif (in_array($query_param_value, $values)) {
// Evaluate all parameters separately, until we find a match.
foreach ($parameters as $key => $values) {
foreach ((array) $values as $value) {
if ($this->evaluateParameter($key, $value)) {
return TRUE;
}
}
}
// No matches at all, this condition failed for the current request.
return FALSE;
}
/**
* Evaluates the condition for a single parameter.
*
* @param string $key
* The parameter key to compare.
* @param string $value
* The parameter values to compare.
*
* @return bool
* Returns TRUE if the given value appears in the current request.
*/
protected function evaluateParameter($key, $value) {
$request_values = $this->getRequestValues($key);
// Check if the parameter appears in the request.
if (empty($request_values)) {
return FALSE;
}
// Check for the presence of a wildcard (e.g. '*').
if (strpos($value, self::TOKEN_WILDCARD) !== FALSE) {
// Check for the presence of exclusions (e.g. '*\0,1,2').
if (strpos($value, self::TOKEN_WILDCARD_EXCLUSION) !== FALSE) {
[, $list] = explode(self::TOKEN_WILDCARD_EXCLUSION, $value);
$exclusions = explode(',', $list);
foreach ($exclusions as $exclusion) {
if (in_array($exclusion, $request_values, TRUE)) {
return FALSE;
}
}
}
return TRUE;
}
// Check if the given value is present in the request.
return in_array($value, $request_values, TRUE);
}
/**
* Get the configured parameters.
*
* @return array
* The configured parameters with their corresponding values.
*/
protected function getConfiguredParameters() {
// Get the parameters from configuration.
$request_param = $this->configuration['request_param'];
// Check if there are any parameters configured.
if (!$request_param) {
return [];
}
// If not case-sensitive, convert all parameters to lowercase.
if (!$this->configuration['case_sensitive']) {
$request_param = mb_strtolower($request_param);
}
// Parse the query string into parameters.
$query = preg_replace('/\n|\r\n?/', '&', $request_param);
parse_str($query, $parameters);
return $parameters;
}
/**
* Get the values for a given request parameter.
*
* @param string $key
* The parameter key.
*
* @return array
* The values for the given parameter in the current request.
*/
protected function getRequestValues($key) {
$values = (array) ($this->requestStack->getCurrentRequest()->query->all()[$key] ?? []);
// If not case-sensitive, convert all values to lowercase.
if (!$this->configuration['case_sensitive']) {
$values = array_map('mb_strtolower', $values);
}
return $values;
}
/**
* {@inheritdoc}
*/
Loading