Skip to content
Snippets Groups Projects
Commit 3b114f65 authored by Steven Ayers's avatar Steven Ayers Committed by Steven Ayers
Browse files

Issue #3087315 by bluegeek9: Filter/filter config anonymous users & paths

parent 2901c695
Branches
Tags
1 merge request!60Issue #3087315: Filter/filter config anonymous users & paths
......@@ -8,6 +8,12 @@ visitors.config:
chart_width:
type: integer
label: 'chart width'
excluded_pages:
type: string
label: 'which pages from logs'
negate_pages:
type: boolean
label: 'exclude or include pages'
exclude_user1:
type: boolean
label: 'exclude user1'
......
......@@ -6,15 +6,18 @@ use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Controller\TitleResolverInterface;
use Drupal\Core\Database\Connection;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Path\PathMatcherInterface;
use Drupal\Core\Routing\AdminContext;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\State\StateInterface;
use Drupal\Core\Url;
use Drupal\path_alias\AliasManagerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\TerminateEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Drupal\Core\State\StateInterface;
use Drupal\Core\Path\CurrentPathStack;
/**
* Store visitors data when a request terminates.
......@@ -102,8 +105,22 @@ class KernelTerminateSubscriber implements EventSubscriberInterface {
* The module handler object.
* @param \Drupal\Core\State\StateInterface $state
* The state service.
* @param \Drupal\Core\Path\PathMatcherInterface $path_matcher
* The path matcher service.
* @param \Drupal\path_alias\AliasManagerInterface $alias_manager
* An alias manager to find the alias for the current system path.
*/
public function __construct(AccountInterface $current_user, Connection $database, RouteMatchInterface $route_match, TitleResolverInterface $title_resolver, ConfigFactoryInterface $config_factory, AdminContext $admin_context, ModuleHandlerInterface $module_handler, StateInterface $state) {
public function __construct(AccountInterface $current_user,
Connection $database,
RouteMatchInterface $route_match,
TitleResolverInterface $title_resolver,
ConfigFactoryInterface $config_factory,
AdminContext $admin_context,
ModuleHandlerInterface $module_handler,
StateInterface $state,
PathMatcherInterface $path_matcher,
AliasManagerInterface $alias_manager,
CurrentPathStack $current_path) {
$this->currentUser = $current_user;
$this->database = $database;
$this->routeMatch = $route_match;
......@@ -112,6 +129,11 @@ class KernelTerminateSubscriber implements EventSubscriberInterface {
$this->adminContext = $admin_context;
$this->moduleHandler = $module_handler;
$this->state = $state;
$this->pathMatcher = $path_matcher;
$this->aliasManager = $alias_manager;
$this->currentPath = $current_path;
$this->config = $this->configFactory->get('visitors.config');
}
/**
......@@ -125,9 +147,11 @@ class KernelTerminateSubscriber implements EventSubscriberInterface {
return NULL;
}
$this->request = $event->getRequest();
$config = $this->configFactory->get('visitors.config');
$exclude_user1 = $config->get('exclude_user1');
$excluded_roles = array_values($config->get('excluded_roles') ?? []);
$path = Url::fromRoute('<current>')->toString();
$exclude_user1 = $this->config->get('exclude_user1', FALSE);
$excluded_roles = array_values($this->config->get('excluded_roles', []));
$negate_pages = $this->config->get('negate_pages', TRUE);
$skip_because_user1 = $this->currentUser->id() == 1 && $exclude_user1;
if ($skip_because_user1) {
......@@ -142,6 +166,17 @@ class KernelTerminateSubscriber implements EventSubscriberInterface {
}
}
$is_match = $this->routeMatches();
if ($negate_pages) {
$skip_because_path = !$is_match;
}
else {
$skip_because_path = $is_match;
}
if ($skip_because_path) {
return NULL;
}
$ip_str = $this->getIpStr();
$fields = [
'visitors_uid' => $this->currentUser->id(),
......@@ -149,7 +184,7 @@ class KernelTerminateSubscriber implements EventSubscriberInterface {
'visitors_date_time' => time(),
'visitors_url' => $this->getUrl(),
'visitors_referer' => $this->getReferer(),
'visitors_path' => Url::fromRoute('<current>')->toString(),
'visitors_path' => $path,
'visitors_title' => $this->getTitle(),
'visitors_user_agent' => $this->getUserAgent(),
];
......@@ -180,6 +215,27 @@ class KernelTerminateSubscriber implements EventSubscriberInterface {
}
}
/**
*
*/
protected function routeMatches() {
// Convert path to lowercase. This allows comparison of the same path
// with different case. Ex: /Page, /page, /PAGE.
$pages = mb_strtolower($this->config->get('excluded_pages'));
if (!$pages) {
return TRUE;
}
// $request = $this->request->getCurrentRequest();
// Compare the lowercase path alias (if any) and internal path.
$path = $this->currentPath->getPath($this->request);
// Do not trim a trailing slash if that is the complete path.
$path = $path === '/' ? $path : rtrim($path, '/');
$path_alias = mb_strtolower($this->aliasManager->getAliasByPath($path));
return $this->pathMatcher->matchPath($path_alias, $pages) || (($path != $path_alias) && $this->pathMatcher->matchPath($path, $pages));
}
/**
* Registers the methods in this class that should be listeners.
*
......
......@@ -44,7 +44,7 @@ class DateFilter extends FormBase {
if (!isset($_SESSION['visitors_from'])) {
$_SESSION['visitors_from'] = [
'month' => date('n'),
'day' => 1,
'day' => '1',
'year' => date('Y'),
];
}
......@@ -290,7 +290,7 @@ class DateFilter extends FormBase {
protected function getMinYear() {
$query = \Drupal::database()->select('visitors');
$query->addExpression('MIN(visitors_date_time)');
$min_timestamp = $query->execute()->fetchField();
$min_timestamp = $query->execute()->fetchField() ?? strtotime('last month');
$timezone = date_default_timezone_get();
......
......@@ -22,6 +22,16 @@ class Settings extends ConfigFormBase {
*/
const SETTINGS = 'visitors.config';
/**
* Shows this block on every page except the listed pages.
*/
const PATH_NOTLISTED = 0;
/**
* Shows this block on only the listed pages.
*/
const PATH_LISTED = 1;
/**
* An extension discovery instance.
......@@ -93,21 +103,6 @@ class Settings extends ConfigFormBase {
$roles[$name] = $role->label();
}
$form['excluded_roles'] = [
'#type' => 'checkboxes',
'#options' => $roles,
'#title' => $this->t('Exclude users with roles from statistics'),
'#default_value' => $config->get('excluded_roles'),
'#description' => $this->t('Exclude hits of users with role(s) from statistics.'),
];
$form['exclude_user1'] = [
'#type' => 'checkbox',
'#title' => $this->t('Exclude user1 from statistics'),
'#default_value' => $config->get('exclude_user1'),
'#description' => $this->t('Exclude hits of user1 from statistics.'),
];
$all_themes = $this->themeList->getList();
$default_theme = $system_config->get('default');
$admin_theme = $system_config->get('admin');
......@@ -185,6 +180,57 @@ class Settings extends ConfigFormBase {
'#default_tab' => 'edit-publication',
];
$form['page'] = [
'#type' => 'details',
'#title' => $this->t('Pages'),
'#description' => $this->t('Which pages to log.'),
'#group' => 'information',
];
$options = [
self::PATH_NOTLISTED => $this->t('All pages except those listed'),
self::PATH_LISTED => $this->t('Only the listed pages'),
];
$form['page']['excluded_pages'] = [
'#type' => 'textarea',
'#default_value' => $config->get('excluded_pages'),
'#description' => $this->t("Specify pages by using their paths. Enter one path per line. The '*' character is a wildcard. An example path is %user-wildcard for every user page. %front is the front page.", [
'%user-wildcard' => '/user/*',
'%front' => '<front>',
]),
];
$form['page']['negate_pages'] = [
'#type' => 'radios',
'#options' => $options,
'#default_value' => $config->get('negate_pages') ?: self::PATH_NOTLISTED,
];
$form['role'] = [
'#type' => 'details',
'#title' => $this->t('Roles'),
'#group' => 'information',
];
$form['role']['excluded_roles'] = [
'#type' => 'checkboxes',
'#options' => $roles,
'#title' => $this->t('Exclude users with roles from statistics'),
'#default_value' => $config->get('excluded_roles'),
'#description' => $this->t('Exclude hits of users with role(s) from statistics.'),
];
$form['user'] = [
'#type' => 'details',
'#title' => $this->t('Users'),
'#group' => 'information',
];
$form['user']['exclude_user1'] = [
'#type' => 'checkbox',
'#title' => $this->t('Exclude user1 from statistics'),
'#default_value' => $config->get('exclude_user1'),
'#description' => $this->t('Exclude hits of user1 from statistics.'),
];
$form['block'] = [
'#type' => 'details',
'#title' => $this->t('Default Block'),
......@@ -290,6 +336,7 @@ class Settings extends ConfigFormBase {
->set('show_since_date', $values['show_since_date'])
->set('exclude_user1', $values['exclude_user1'])
->set('excluded_roles', $values['excluded_roles'])
->set('excluded_pages', $values['excluded_pages'])
->set('theme', $values['theme'])
->set('items_per_page', $values['items_per_page'])
->set('flush_log_timer', $values['flush_log_timer'])
......
......@@ -10,6 +10,9 @@ services:
- '@router.admin_context'
- '@module_handler'
- '@state'
- '@path.matcher'
- '@path_alias.manager'
- '@path.current'
tags:
- { name: event_subscriber }
visitors.negotiator:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment