gamify-1.1.x-dev/src/WatchdogService.php
src/WatchdogService.php
<?php
namespace Drupal\gamify;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Database\Connection;
use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\KeyValueStore\KeyValueFactory;
use Drupal\Core\KeyValueStore\KeyValueStoreInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\eca\Event\TriggerEvent;
use Drupal\gamify\Traits\DbLogResultTrait;
use Drupal\gamify\Traits\GamifyDbLogTrait;
use Drupal\gamify\Traits\GamifyEntityLogTrait;
use Drupal\user\Entity\User;
use Psr\Log\LoggerInterface;
/**
* Services around the gamify usage of the watchdog.
*/
class WatchdogService {
use StringTranslationTrait;
use GamifyEntityLogTrait;
use GamifyDbLogTrait;
use DbLogResultTrait;
const KEY_VALUE_COLLECTION = 'gamify-execution';
/**
* Drupal\Core\Database\Connection definition.
*
* @var \Drupal\Core\Database\Connection
*/
protected Connection $database;
/**
* Drupal\Core\KeyValueStore\KeyValueStoreInterface definition.
*
* @var \Drupal\Core\KeyValueStore\KeyValueStoreInterface|mixed
*/
protected KeyValueStoreInterface $keyValueStore;
/**
* Drupal\Component\Datetime\TimeInterface definition.
*
* @var \Drupal\Component\Datetime\TimeInterface
*/
protected TimeInterface $time;
/**
* Drupal\Core\Logger\LoggerChannelInterface definition.
*
* @var \Psr\Log\LoggerInterface|\Drupal\Core\Logger\LoggerChannelInterface
*/
protected LoggerInterface $logger;
/**
* Drupal\Core\Logger\LoggerChannelInterface definition.
*
* @var \Drupal\Core\Datetime\DateFormatterInterface
*/
protected DateFormatterInterface $dateFormatter;
/**
* Constructs a new WatchdogService object.
*/
public function __construct(Connection $database, KeyValueFactory $key_value, TimeInterface $time, LoggerChannelFactoryInterface $logger, DateFormatterInterface $date_formatter) {
$this->database = $database;
$this->keyValueStore = $key_value->get(self::KEY_VALUE_COLLECTION);
$this->time = $time;
$this->logger = $logger->get('gamify');
$this->dateFormatter = $date_formatter;
}
/**
* Inits evaluation run of log entries.
*
* @param string $trigger
* An ID just for documentation of errors.
*/
public function initRun(string $trigger = 'default'): void {
// @todo Debug with $last_run = 0 to multiple run same logs.
$last_run = 0; //(int) $this->keyValueStore->get('last_run') ?? 0;
$now = $this->time->getRequestTime();
$this->logger->debug(new TranslatableMarkup('Init Gamify watchdog service from @trigger. Last run was @last_run.', [
'@trigger' => $trigger,
'@last_run' => $this->dateFormatter->format($last_run, 'short')
]));
try {
$conditions = ['timestamp' => ['value' => $last_run, 'operator' => '>']];
$user_entries = $this->loadUserEntries($conditions);
$event_dispatcher = \Drupal::service('eca.trigger_event');
foreach ($user_entries as $uid => $entries) {
if ($user = $uid ? User::load($uid) : NULL) {
/** @var TriggerEvent $event_dispatcher */
$event_dispatcher->dispatchFromPlugin('gamify:recent_logs', $user, $last_run, $entries);
}
}
}
catch (\Exception $e) {
$msg = $this->t('Gamify watchdog evaluation run failed at @perc (Trigger: @trigger, From: @from, To: @to).', [
'@trigger' => $trigger,
'@from' => $last_run,
'@to' => $now,
])->render();
$this->logger->error($msg . $e->getMessage());
// Stop execution to not set the new marker for next run.
return;
}
$this->keyValueStore->set('last_run', $now);
}
/**
* Get watchdog entries grouped by user.
*
* @return array[]
* Returns array keyed by user id contains watchdog entries.
*
* @throws \Exception
*/
public function loadUserEntries(array $conditions = []): array {
$user_entries = [];
try {
foreach ($this->loadEntries($conditions, TRUE) as $wid => $log) {
$user_entries[$log['uid']][$wid] = $log;
}
}
catch (\Exception $e) {
$this->logger->error("Couldn't load gamify_log entries.\n" . $e->getMessage());
}
return $user_entries;
}
/**
* Search for continued series in given log entries by time interval.
*
* @param array $entries
* Entries to search.
* @param string $filter
* Filter string to match with the log hash.
*
* @return array
* An array of all series found.
*/
public function filter(array $entries, string $filter): array {
if (trim($filter) === '') {
return $entries;
}
$is_pattern = str_starts_with($filter, '/')
&& str_ends_with($filter, '/')
&& (@preg_match($filter, NULL) !== FALSE);
return array_filter($entries, function ($obj) use ($filter, $is_pattern) {
$message = is_object($obj) ? $obj->message : $obj['message'];
if (isset($message)) {
if ($is_pattern) {
return !!preg_match($filter, $message);
}
else {
return str_contains($message, $filter);
}
}
return FALSE;
});
}
}
