gamify-1.1.x-dev/src/Plugin/Action/LogsFilter.php
src/Plugin/Action/LogsFilter.php
<?php
namespace Drupal\gamify\Plugin\Action;
use Drupal\Core\Form\FormStateInterface;
use Drupal\eca\Plugin\Action\ConfigurableActionBase;
/**
* Provide all tamper plugins as ECA actions.
*
* @Action(
* id = "gamify_filter_logs",
* label = @Translation("Gamify: Logs Filter (by RegEx or search string).")
* )
*/
class LogsFilter extends ConfigurableActionBase {
/**
* {@inheritdoc}
*
* @throws \Drupal\Component\Plugin\Exception\PluginException | \Drupal\Core\TypedData\Exception\MissingDataException
*/
public function execute(): void {
$dataKey = $this->configuration['eca_data'] ?? NULL;
$data = $dataKey ? $this->tokenServices->getTokenData($dataKey)->toArray() : NULL;
$interim_result = [];
if (is_array($data ?? NULL)) {
// Set parameter bag distilled from previous query.
$parameterKey = $this->configuration['filter_params'] ?? NULL;
$parameter = $parameterKey ? $this->tokenServices->getTokenData($parameterKey)->toArray() : NULL;
$pattern = $this->configuration['filter_pattern'];
// Check if we have to work with params from ResultRegExDistiller.
if (is_array($parameter)) {
// Using params => +1 loop more because have to handle each param set.
foreach ($parameter as $params_key => $params) {
$matches = $params['matches'] ?? NULL;
if ($matches && $prepared_pattern = $this->preparePattern($pattern, $matches)) {
if ($search_result = $this->searchEntries($data, $prepared_pattern)) {
$interim_result[$params_key] = $search_result;
}
}
}
}
elseif ($prepared_pattern = $this->preparePattern($pattern, [])) {
if ($search_result = $this->searchEntries($data, $prepared_pattern)) {
$interim_result[] = $search_result;
}
}
}
$this->tokenServices->addTokenData($this->configuration['eca_token_name'], $interim_result);
}
/**
* {@inheritdoc}
*/
public function defaultConfiguration(): array {
return [
'eca_data' => '',
'filter_pattern' => '',
'filter_params' => '',
'eca_token_name' => '',
];
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state): array {
$form['eca_data'] = [
'#type' => 'textfield',
'#title' => $this->t('Log entries to be filtered'),
'#description' => $this->t('This field supports tokens.'),
'#default_value' => $this->configuration['eca_data'],
'#required' => TRUE,
'#weight' => 10,
];
$form['filter_pattern'] = [
'#type' => 'textfield',
'#title' => $this->t('Filter pattern'),
'#description' => $this->t('Filter logs by RegEx or search string. If you are using filter parameters (see field below), use $0, $1, ... as placeholder where to insert.'),
'#default_value' => $this->configuration['filter_pattern'],
'#required' => TRUE,
'#weight' => 20,
];
$form['filter_params'] = [
'#type' => 'textfield',
'#title' => $this->t('Filter parameters'),
'#description' => $this->t('Token for replacement params from action "Logs params distiller".'),
'#default_value' => $this->configuration['filter_params'],
'#weight' => 30,
];
$form['eca_token_name'] = [
'#type' => 'textfield',
'#title' => $this->t('Result token name'),
'#description' => $this->t('Provide a token name under which the tampered result will be made available for subsequent actions.'),
'#default_value' => $this->configuration['eca_token_name'],
'#required' => TRUE,
'#weight' => 40,
];
return parent::buildConfigurationForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitConfigurationForm(array &$form, FormStateInterface $form_state): void {
$this->configuration['eca_data'] = $form_state->getValue('eca_data');
$this->configuration['filter_pattern'] = $form_state->getValue('filter_pattern');
$this->configuration['filter_params'] = $form_state->getValue('filter_params');
$this->configuration['eca_token_name'] = $form_state->getValue('eca_token_name');
parent::submitConfigurationForm($form, $form_state);
}
/**
* Prepare search pattern.
*
* @param string $pattern
* The search pattern, optional with placeholders ($1, $2, ...) for params.
* @param array $params
* The params are the match result from a ResultRegExDistiller.
*
* @return mixed
* Prepared search pattern.
*/
protected function preparePattern(string $pattern, array $params): mixed {
$is_regex = (str_starts_with($pattern, '/') && str_ends_with($pattern, '/'));
if (count($params)) {
$replacer = [];
foreach ($params as $key => $param) {
$replacer["$$key"] = ($is_regex) ? preg_quote($param) : $param;
}
$pattern = str_replace(array_keys($replacer), $replacer, $pattern);
}
if ($is_regex && @preg_match($pattern, NULL) === FALSE) {
return FALSE;
}
return ($is_regex)
? $pattern
: explode('|', $pattern);
}
/**
* Searches for entries, where log_hash matching the pattern.
*
* @param array[] $entries
* Entries from log with at least a log_hash property.
* @param mixed $pattern
* Search pattern. RegEx OR array of search strings where each string must
* match the log hash of an entry.
*
* @return array|null
* Result array of entries filtered by the pattern.
*/
protected function searchEntries(array $entries, mixed $pattern): ?array {
$result = [];
foreach ($entries as $result_key => $prev_result) {
$matched = FALSE;
// If preparePattern returns array => String search.
if (is_array($pattern)) {
foreach ($pattern as $str) {
$matched = str_contains($prev_result['log_hash'], $str);
if (!$matched) {
break;
}
}
}
// If preparePattern returns string => RegEx.
elseif (is_string($pattern)) {
$matched = preg_match($pattern, $prev_result['log_hash']);
}
if ($matched) {
$result[$result_key] = $prev_result;
}
}
return count($result) ? $result : NULL;
}
}
