summaryrefslogtreecommitdiffstats
path: root/modules-available/statistics/inc/statisticsfilterset.inc.php
blob: 5840821b661942fb44735cf6355ab688d02fe5bf (plain) (blame)
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
<?php

class StatisticsFilterSet
{
	/**
	 * @var \DatabaseFilter[]
	 */
	private $filters;

	private $cache = false;

	/**
	 * @param DatabaseFilter[] $filters
	 */
	public function __construct(array $filters)
	{
		$this->filters = $filters;
	}

	public function makeFragments(&$where, &$join, &$args)
	{
		if ($this->cache !== false) {
			$where = $this->cache['where'];
			$join = $this->cache['join'];
			$args = $this->cache['args'];
			return;
		}
		/* generate where clause & arguments */
		$where = '';
		$joins = [];
		$args = [];
		if (empty($this->filters)) {
			$where = ' 1 ';
		} else {
			foreach ($this->filters as $filter) {
				$sep = ($where != '' ? ' AND ' : '');
				$where .= $sep . $filter->whereClause($args, $joins);
			}
		}
		$join = implode(' ', array_unique($joins));
		$this->cache = compact('where', 'join', 'args');
	}

	/**
	 * Are there any "specific filters" in place?
	 * We consider filters specific that filter by precise information like
	 * CPU model, IP address, MAC address, etc. In those cases we might not
	 * want to filter non-client machines in the summary view, for example.
	 */
	public function hasSpecificFilters(): bool
	{
		$ignored = ['firstseen', 'lastseen', 'lastboot', 'runtime', 'state'];
		foreach ($this->filters as $key => $_) {
			if (!in_array($key, $ignored))
				return true;
		}
		return false;
	}

	public function filterNonClients()
	{
		if (Module::get('runmode') === false || $this->hasFilter('IsClientStatisticsFilter') !== null)
			return;
		$this->cache = false;
		// Runmode module exists, add filter
		$this->filters[] = (new IsClientStatisticsFilter())->bind('=', true);
	}

	/**
	 * @param string $type filter type (class name)
	 * @return ?DatabaseFilter The filter, null if not found
	 */
	public function hasFilter(string $type): ?DatabaseFilter
	{
		foreach ($this->filters as $filter) {
			if ($filter->isClass($type)) {
				return $filter;
			}
		}
		return null;
	}

	/**
	 * @param string $type filter type key/id
	 * @return ?DatabaseFilter The filter, null if not found
	 */
	public function hasFilterKey(string $type): ?DatabaseFilter
	{
		if (isset($this->filters[$type]))
			return $this->filters[$type];
		return null;
	}

	/**
	 * Add a location filter based on the allowed permissions for the given permission.
	 * Returns false if the user doesn't have the given permission for any location.
	 *
	 * @param string $permission permission to use
	 * @return bool false if no permission for any location, true otherwise
	 */
	public function setAllowedLocationsFromPermission(string $permission): bool
	{
		if (!Module::isAvailable('locations'))
			return true;
		$locs = User::getAllowedLocations($permission);
		if (empty($locs))
			return false;
		if (in_array(0, $locs)) {
			if (!isset($this->filters['permissions']))
				return true;
			unset($this->filters['permissions']);
		} else {
			$this->filters['permissions'] = StatisticsFilter::$columns['location']->bind('=', $locs);
		}
		$this->cache = false;
		return true;
	}

	/**
	 * @return false|array
	 */
	public function getAllowedLocations()
	{
		if (isset($this->filters['permissions']) && is_array($this->filters['permissions']->argument))
			return (array)$this->filters['permissions']->argument;
		return false;
	}

	public function suitableForUsageGraph(): bool
	{
		foreach ($this->filters as $filter) {
			switch ($filter->getClass()) {
			case 'LocationStatisticsFilter':
			case 'IsClientStatisticsFilter':
				break;
			case 'DateStatisticsFilter':
				if ($filter->op !== '>' && $filter->op !== '>=')
					return false;
				if (strtotime($filter->argument) + 3*86400 > time())
					return false;
				break;
			case 'RuntimeStatisticsFilter':
				if ($filter->op !== '>' && $filter->op !== '>=')
					return false;
				if ($filter->argument < 3 * 24)
					return false;
				break;
			default:
				return false;
			}
		}
		return true;
	}

}