summaryrefslogtreecommitdiffstats
path: root/modules-available/statistics/inc/statisticsfilterset.inc.php
blob: 26595e937c692b200248391e4def8a2a01b69ded (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
<?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');
	}

	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;
	}

}