Complex classes like Data often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Data, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
40 | class Data { |
||
41 | /** @var IManager */ |
||
42 | protected $activityManager; |
||
43 | |||
44 | /** @var IDBConnection */ |
||
45 | protected $connection; |
||
46 | |||
47 | /** @var IUserSession */ |
||
48 | protected $userSession; |
||
49 | |||
50 | /** |
||
51 | * @param IManager $activityManager |
||
52 | * @param IDBConnection $connection |
||
53 | * @param IUserSession $userSession |
||
54 | */ |
||
55 | 67 | public function __construct(IManager $activityManager, IDBConnection $connection, IUserSession $userSession) { |
|
60 | |||
61 | protected $notificationTypes = array(); |
||
62 | |||
63 | /** |
||
64 | * @param IL10N $l |
||
65 | * @return array Array "stringID of the type" => "translated string description for the setting" |
||
66 | * or Array "stringID of the type" => [ |
||
67 | * 'desc' => "translated string description for the setting" |
||
68 | * 'methods' => [\OCP\Activity\IExtension::METHOD_*], |
||
69 | * ] |
||
70 | */ |
||
71 | 8 | public function getNotificationTypes(IL10N $l) { |
|
81 | |||
82 | /** |
||
83 | * Send an event into the activity stream |
||
84 | * |
||
85 | * @param IEvent $event |
||
86 | * @return bool |
||
87 | */ |
||
88 | 4 | public function send(IEvent $event) { |
|
132 | |||
133 | /** |
||
134 | * Send an event as email |
||
135 | * |
||
136 | * @param IEvent $event |
||
137 | * @param int $latestSendTime Activity $timestamp + batch setting of $affectedUser |
||
138 | * @return bool |
||
139 | */ |
||
140 | 4 | public function storeMail(IEvent $event, $latestSendTime) { |
|
170 | |||
171 | /** |
||
172 | * Read a list of events from the activity stream |
||
173 | * |
||
174 | * @param GroupHelper $groupHelper Allows activities to be grouped |
||
175 | * @param UserSettings $userSettings Gets the settings of the user |
||
176 | * @param string $user User for whom we display the stream |
||
177 | * |
||
178 | * @param int $since The integer ID of the last activity that has been seen. |
||
179 | * @param int $limit How many activities should be returned |
||
180 | * @param string $sort Should activities be given ascending or descending |
||
181 | * |
||
182 | * @param string $filter Filter the activities |
||
183 | * @param string $objectType Allows to filter the activities to a given object. May only appear together with $objectId |
||
184 | * @param int $objectId Allows to filter the activities to a given object. May only appear together with $objectType |
||
185 | * |
||
186 | * @return array |
||
187 | * |
||
188 | * @throws \OutOfBoundsException if the user (Code: 1) or the since (Code: 2) is invalid |
||
189 | * @throws \BadMethodCallException if the user has selected to display no types for this filter (Code: 3) |
||
190 | */ |
||
191 | 15 | public function get(GroupHelper $groupHelper, UserSettings $userSettings, $user, $since, $limit, $sort, $filter, $objectType = '', $objectId = 0) { |
|
192 | // get current user |
||
193 | 15 | if ($user === '') { |
|
194 | 1 | throw new \OutOfBoundsException('Invalid user', 1); |
|
195 | } |
||
196 | 14 | $groupHelper->setUser($user); |
|
197 | |||
198 | 14 | $enabledNotifications = $userSettings->getNotificationTypes($user, 'stream'); |
|
199 | 14 | $enabledNotifications = $this->activityManager->filterNotificationTypes($enabledNotifications, $filter); |
|
200 | 14 | $enabledNotifications = array_unique($enabledNotifications); |
|
201 | |||
202 | // We don't want to display any activities |
||
203 | 14 | if (empty($enabledNotifications)) { |
|
204 | 1 | throw new \BadMethodCallException('No settings enabled', 3); |
|
205 | } |
||
206 | |||
207 | 13 | $query = $this->connection->getQueryBuilder(); |
|
208 | 13 | $query->select('*') |
|
209 | 13 | ->from('activity'); |
|
210 | |||
211 | 13 | $query->where($query->expr()->eq('affecteduser', $query->createNamedParameter($user))) |
|
212 | 13 | ->andWhere($query->expr()->in('type', $query->createNamedParameter($enabledNotifications, \Doctrine\DBAL\Connection::PARAM_STR_ARRAY))); |
|
213 | 13 | if ($filter === 'self') { |
|
214 | 2 | $query->andWhere($query->expr()->eq('user', $query->createNamedParameter($user))); |
|
215 | |||
216 | 11 | } else if ($filter === 'by' || $filter === 'all' && !$userSettings->getUserSetting($user, 'setting', 'self')) { |
|
217 | 2 | $query->andWhere($query->expr()->neq('user', $query->createNamedParameter($user))); |
|
218 | |||
219 | 9 | } else if ($filter === 'filter') { |
|
220 | 2 | if (!$userSettings->getUserSetting($user, 'setting', 'self')) { |
|
221 | 2 | $query->andWhere($query->expr()->neq('user', $query->createNamedParameter($user))); |
|
222 | } |
||
223 | |||
224 | 2 | $query->andWhere($query->expr()->eq('object_type', $query->createNamedParameter($objectType))); |
|
225 | 2 | $query->andWhere($query->expr()->eq('object_id', $query->createNamedParameter($objectId))); |
|
226 | } |
||
227 | |||
228 | 13 | list($condition, $params) = $this->activityManager->getQueryForFilter($filter); |
|
229 | 13 | if (!is_null($condition)) { |
|
230 | // Strip away ' and ' |
||
231 | $condition = substr($condition, 5); |
||
232 | |||
233 | if (is_array($params)) { |
||
234 | // Replace ? placeholders with named parameters |
||
235 | foreach ($params as $param) { |
||
236 | $pos = strpos($condition, '?'); |
||
237 | if ($pos !== false) { |
||
238 | $condition = substr($condition, 0, $pos) . $query->createNamedParameter($param) . substr($condition, $pos + 1); |
||
239 | } |
||
240 | } |
||
241 | } |
||
242 | |||
243 | $query->andWhere($query->createFunction($condition)); |
||
244 | } |
||
245 | |||
246 | /** |
||
247 | * Order and specify the offset |
||
248 | */ |
||
249 | 13 | $sqlSort = ($sort === 'asc') ? 'ASC' : 'DESC'; |
|
250 | 13 | $headers = $this->setOffsetFromSince($query, $user, $since, $sqlSort); |
|
251 | 13 | $query->orderBy('timestamp', $sqlSort) |
|
252 | 13 | ->addOrderBy('activity_id', $sqlSort); |
|
253 | |||
254 | 13 | $query->setMaxResults($limit + 1); |
|
255 | |||
256 | 13 | $result = $query->execute(); |
|
257 | 13 | $hasMore = false; |
|
258 | 13 | while ($row = $result->fetch()) { |
|
259 | 12 | if ($limit === 0) { |
|
260 | 10 | $hasMore = true; |
|
261 | 10 | break; |
|
262 | } |
||
263 | 12 | $headers['X-Activity-Last-Given'] = (int) $row['activity_id']; |
|
264 | 12 | $groupHelper->addActivity($row); |
|
265 | 12 | $limit--; |
|
266 | } |
||
267 | 13 | $result->closeCursor(); |
|
268 | |||
269 | 13 | return ['data' => $groupHelper->getActivities(), 'has_more' => $hasMore, 'headers' => $headers]; |
|
270 | } |
||
271 | |||
272 | /** |
||
273 | * @param IQueryBuilder $query |
||
274 | * @param string $user |
||
275 | * @param int $since |
||
276 | * @param string $sort |
||
277 | * |
||
278 | * @return array Headers that should be set on the response |
||
279 | * |
||
280 | * @throws \OutOfBoundsException If $since is not owned by $user |
||
281 | */ |
||
282 | 18 | protected function setOffsetFromSince(IQueryBuilder $query, $user, $since, $sort) { |
|
283 | 18 | if ($since) { |
|
284 | 5 | $queryBuilder = $this->connection->getQueryBuilder(); |
|
285 | 5 | $queryBuilder->select('*') |
|
286 | 5 | ->from('activity') |
|
287 | 5 | ->where($queryBuilder->expr()->eq('activity_id', $queryBuilder->createNamedParameter((int) $since))); |
|
288 | 5 | $result = $queryBuilder->execute(); |
|
289 | 5 | $activity = $result->fetch(); |
|
290 | 5 | $result->closeCursor(); |
|
291 | |||
292 | 5 | if ($activity) { |
|
293 | 4 | if ($activity['affecteduser'] !== $user) { |
|
294 | 1 | throw new \OutOfBoundsException('Invalid since', 2); |
|
295 | } |
||
296 | 3 | $timestamp = (int) $activity['timestamp']; |
|
297 | |||
298 | 3 | if ($sort === 'DESC') { |
|
299 | 2 | $query->andWhere($query->expr()->lte('timestamp', $query->createNamedParameter($timestamp))); |
|
300 | 2 | $query->andWhere($query->expr()->lt('activity_id', $query->createNamedParameter($since))); |
|
301 | } else { |
||
302 | 1 | $query->andWhere($query->expr()->gte('timestamp', $query->createNamedParameter($timestamp))); |
|
303 | 1 | $query->andWhere($query->expr()->gt('activity_id', $query->createNamedParameter($since))); |
|
304 | } |
||
305 | 3 | return []; |
|
306 | } |
||
307 | } |
||
308 | |||
309 | /** |
||
310 | * Couldn't find the since, so find the oldest one and set the header |
||
311 | */ |
||
312 | 14 | $fetchQuery = $this->connection->getQueryBuilder(); |
|
313 | 14 | $fetchQuery->select('activity_id') |
|
314 | 14 | ->from('activity') |
|
315 | 14 | ->where($fetchQuery->expr()->eq('affecteduser', $fetchQuery->createNamedParameter($user))) |
|
316 | 14 | ->orderBy('timestamp', $sort) |
|
317 | 14 | ->setMaxResults(1); |
|
318 | 14 | $result = $fetchQuery->execute(); |
|
319 | 14 | $activity = $result->fetch(); |
|
320 | 14 | $result->closeCursor(); |
|
321 | |||
322 | 14 | if ($activity !== false) { |
|
323 | return [ |
||
324 | 12 | 'X-Activity-First-Known' => (int) $activity['activity_id'], |
|
325 | ]; |
||
326 | } |
||
327 | |||
328 | 2 | return []; |
|
329 | } |
||
330 | |||
331 | /** |
||
332 | * Verify that the filter is valid |
||
333 | * |
||
334 | * @param string $filterValue |
||
335 | * @return string |
||
336 | */ |
||
337 | 6 | public function validateFilter($filterValue) { |
|
355 | |||
356 | /** |
||
357 | * Delete old events |
||
358 | * |
||
359 | * @param int $expireDays Minimum 1 day |
||
360 | * @return null |
||
361 | */ |
||
362 | 2 | public function expire($expireDays = 365) { |
|
370 | |||
371 | /** |
||
372 | * Delete activities that match certain conditions |
||
373 | * |
||
374 | * @param array $conditions Array with conditions that have to be met |
||
375 | * 'field' => 'value' => `field` = 'value' |
||
376 | * 'field' => array('value', 'operator') => `field` operator 'value' |
||
377 | * @return null |
||
378 | */ |
||
379 | 12 | public function deleteActivities($conditions) { |
|
395 | } |
||
396 |