Completed
Pull Request — master (#624)
by
unknown
120:49 queued 119:07
created

GroupHelper::getActivities()   B

Complexity

Conditions 4
Paths 5

Size

Total Lines 26
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 4.0023

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 26
ccs 18
cts 19
cp 0.9474
rs 8.5806
cc 4
eloc 16
nc 5
nop 0
crap 4.0023
1
<?php
2
/**
3
 * @author Joas Schilling <[email protected]>
4
 *
5
 * @copyright Copyright (c) 2016, ownCloud, Inc.
6
 * @license AGPL-3.0
7
 *
8
 * This code is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Affero General Public License, version 3,
10
 * as published by the Free Software Foundation.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
 * GNU Affero General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Affero General Public License, version 3,
18
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
19
 *
20
 */
21
22
namespace OCA\Activity;
23
24
use OCA\Activity\Parameter\Collection;
25
use OCA\Activity\Parameter\IParameter;
26
use OCP\Activity\IEvent;
27
use OCP\Activity\IManager;
28
use OCP\IL10N;
29
30
class GroupHelper {
31
	/** @var array */
32
	protected $activities = array();
33
34
	/** @var array */
35
	protected $openGroup = array();
36
37
	/** @var string */
38
	protected $groupKey = '';
39
40
	/** @var int */
41
	protected $groupTime = 0;
42
43
	/** @var bool */
44
	protected $allowGrouping;
45
46
	/** @var \OCP\Activity\IManager */
47
	protected $activityManager;
48
49
	/** @var \OCA\Activity\DataHelper */
50
	protected $dataHelper;
51
52
	/**
53
	 * @param \OCP\Activity\IManager $activityManager
54
	 * @param \OCA\Activity\DataHelper $dataHelper
55
	 * @param bool $allowGrouping
56
	 */
57 31
	public function __construct(IManager $activityManager, DataHelper $dataHelper, $allowGrouping) {
58 31
		$this->allowGrouping = $allowGrouping;
59
60 31
		$this->activityManager = $activityManager;
61 31
		$this->dataHelper = $dataHelper;
62 31
	}
63
64
	/**
65
	 * @param string $user
66
	 */
67 6
	public function setUser($user) {
68 6
		$this->dataHelper->setUser($user);
69 6
	}
70
71
	/**
72
	 * @param IL10N $l
73
	 */
74 1
	public function setL10n(IL10N $l) {
75 1
		$this->dataHelper->setL10n($l);
76 1
	}
77
78
	/**
79
	 * Add an activity to the internal array
80
	 *
81
	 * @param array $activity
82
	 */
83 12
	public function addActivity($activity) {
84 12
		$activity['activity_id'] = (int) $activity['activity_id'];
85 12
		$activity['timestamp'] = (int) $activity['timestamp'];
86 12
		$activity['object_id'] = (int) $activity['object_id'];
87 12
		$activity['object_name'] = (string) $activity['file'];
88 12
		unset($activity['priority']);
89 12
		unset($activity['file']);
90
91 12
		$event = $this->getEventFromArray(array_merge($activity, [
92 12
			'subjectparams' => [],
93 12
			'messageparams' => [],
94 12
		]));
95
96 12
		$activity['subjectparams_array'] = $this->dataHelper->getParameters($event, 'subject', $activity['subjectparams']);
97 12
		$activity['messageparams_array'] = $this->dataHelper->getParameters($event, 'message', $activity['messageparams']);
98
99 12
		$groupKey = $this->getGroupKey($activity);
100 12
		if ($groupKey === false) {
101 5
			$this->closeOpenGroup();
102 5
			$this->activities[] = $activity;
103 5
			return;
104
		}
105
106
		// Only group when the event has the same group key
107
		// and the time difference is not bigger than 3 days.
108 8
		if ($groupKey === $this->groupKey &&
109 4
			abs($activity['timestamp'] - $this->groupTime) < (3 * 24 * 60 * 60)
110 8
			&& (!isset($this->openGroup['activity_ids']) || sizeof($this->openGroup['activity_ids']) <= 5)
111 8
		) {
112 2
			$groupOnParameter = $this->getGroupParameter($activity);
113 2
			if ($groupOnParameter !== false) {
114
				// aggregate all parameter values outside of $groupOnParameter
115 2
				$subjectParams = json_decode($activity['subjectparams'], true);
116
				foreach ($subjectParams as $parameter => $subjectParam) {
117
					if ($parameter === $groupOnParameter) {
118
						// exclude $groupOnParameter
119
						continue;
120
					}
121
122
					/** @var IParameter $parameterInstance */
123
					$parameterInstance = $this->openGroup['subjectparams_array'][$parameter];
124
125
					// convert parameter to collection as we have a second value coming in
126
					if (!($parameterInstance instanceof Collection)) {
127
						$collection = $this->dataHelper->createCollection();
128
						$collection->addParameter($parameterInstance);
129
						$parameterInstance = $collection;
130
					}
131
132
					/** @var Collection $parameterInstance */
133
					$parameterInstance->addParameter($activity['subjectparams_array'][$parameter]);
134
					$this->openGroup['subjectparams_array'][$parameter] = $parameterInstance;
135
				}
136
137
				if (!isset($this->openGroup['activity_ids'])) {
138
					$this->openGroup['activity_ids'] = [(int) $this->openGroup['activity_id']];
139
					$this->openGroup['files'] = [
140
						$this->openGroup['object_id'] => $this->openGroup['object_name']
141
					];
142
				}
143
				$this->openGroup['activity_ids'][] = (int) $activity['activity_id'];
144
145
				$this->openGroup['files'][$activity['object_id']] = $activity['object_name'];
146
			}
147
		} else {
148 6
			$this->closeOpenGroup();
149
150 6
			$this->groupKey = $groupKey;
151 6
			$this->groupTime = $activity['timestamp'];
152 6
			$this->openGroup = $activity;
153
		}
154 6
	}
155
156
	/**
157
	 * Closes the currently open group and adds it to the list of activities
158
	 */
159 13
	protected function closeOpenGroup() {
160 13
		if (!empty($this->openGroup)) {
161 7
			$this->activities[] = $this->openGroup;
162 7
		}
163
164 13
		$this->openGroup = [];
165 13
		$this->groupKey = '';
166 13
		$this->groupTime = 0;
167 13
	}
168
169
	/**
170
	 * Get grouping key for an activity
171
	 *
172
	 * @param array $activity
173
	 * @return false|string False, if grouping is not allowed, grouping key otherwise
174
	 */
175 7
	protected function getGroupKey($activity) {
176 7
		$parameterIndex = $this->getGroupParameter($activity);
177 7
		if ($parameterIndex === false) {
178 4
			return false;
179
		}
180
181
		// FIXME
182
		// Non-local users are currently not distinguishable, so grouping them might
183
		// remove the information how many different users performed the same action.
184
		// So we do not group them anymore, until we found another solution.
185 4
		if ($activity['user'] === '') {
186 1
			return false;
187
		}
188
189
		// need to also group on subjectparams value
190 3
		$subjectParams = json_decode($activity['subjectparams'], true);
191 2
		$groupByParam = $subjectParams[$parameterIndex];
192 2
		$paramsKey = md5(json_encode($groupByParam));
193
194 2
		return $activity['app'] . '|' . $activity['user'] . '|' . $activity['subject'] . '|' . $activity['object_type'] . '|' . $paramsKey;
195
	}
196
197
	/**
198
	 * Get the parameter which is the varying part
199
	 *
200
	 * @param array $activity
201
	 * @return bool|int False if the activity should not be grouped, parameter position otherwise
202
	 */
203 8
	protected function getGroupParameter($activity) {
204 8
		if (!$this->allowGrouping) {
205 2
			return false;
206
		}
207
208
		// Allow other apps to group their notifications
209 6
		return $this->activityManager->getGroupParameter($activity);
210
	}
211
212
	/**
213
	 * Get the prepared activities
214
	 *
215
	 * @return array translated activities ready for use
216
	 */
217 8
	public function getActivities() {
218 8
		$this->closeOpenGroup();
219
220 8
		$return = array();
221 8
		foreach ($this->activities as $activity) {
222 6
			$this->activityManager->setFormattingObject($activity['object_type'], $activity['object_id']);
223 6
			$activity = $this->dataHelper->formatStrings($activity, 'subject');
224 6
			$activity = $this->dataHelper->formatStrings($activity, 'message');
225
226 6
			foreach ($activity['subjectparams'] as $i => $param) {
0 ignored issues
show
Bug introduced by
The expression $activity['subjectparams'] of type string is not traversable.
Loading history...
227
				/** @var IParameter $param */
228 4
				$activity['subjectparams'][$i] = $param->getParameterInfo();
229 6
			}
230 6
			foreach ($activity['messageparams'] as $i => $param) {
0 ignored issues
show
Bug introduced by
The expression $activity['messageparams'] of type string is not traversable.
Loading history...
231
				/** @var IParameter $param */
232
				$activity['messageparams'][$i] = $param->getParameterInfo();
233 6
			}
234
235 6
			$activity['typeicon'] = $this->activityManager->getTypeIcon($activity['type']);
236 6
			$return[] = $activity;
237 8
		}
238 8
		$this->activityManager->setFormattingObject('', 0);
239 8
		$this->activities = [];
240
241 8
		return $return;
242
	}
243
244
	/**
245
	 * @param array $activity
246
	 * @return IEvent
247
	 */
248 6
	public function getEventFromArray(array $activity) {
249 6
		$event = $this->activityManager->generateEvent();
250 6
		$event->setApp($activity['app'])
251 6
			->setType($activity['type'])
252 6
			->setAffectedUser($activity['affecteduser'])
253 6
			->setAuthor($activity['user'])
254 6
			->setTimestamp($activity['timestamp'])
255 6
			->setSubject($activity['subject'], $activity['subjectparams'])
256 6
			->setMessage($activity['message'], $activity['messageparams'])
257 6
			->setObject($activity['object_type'], $activity['object_id'], $activity['object_name'])
258 6
			->setLink($activity['link']);
259
260 6
		return $event;
261
	}
262
}
263