Completed
Push — master ( f61da2...430ae5 )
by Sam
03:08
created

StatisticsManager::getUsers()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 7
ccs 0
cts 6
cp 0
rs 9.4285
cc 1
eloc 4
nc 1
nop 1
crap 2
1
<?php
2
3
namespace Jalle19\StatusManager\Manager;
4
5
use Jalle19\StatusManager\Database\InstanceQuery;
6
use Jalle19\StatusManager\Database\SubscriptionQuery;
7
use Jalle19\StatusManager\Database\User;
8
use Jalle19\StatusManager\Database\UserQuery;
9
use Jalle19\StatusManager\Message\AbstractMessage;
10
use Jalle19\StatusManager\Message\Handler\HandlerInterface;
11
use Jalle19\StatusManager\Message\Request\InstancesRequest;
12
use Jalle19\StatusManager\Message\Request\MostActiveWatchersRequest;
13
use Jalle19\StatusManager\Message\Request\PopularChannelsRequest;
14
use Jalle19\StatusManager\Message\Request\StatisticsRequest;
15
use Jalle19\StatusManager\Message\Request\UsersRequest;
16
use Jalle19\StatusManager\Message\Response\InstancesResponse;
17
use Jalle19\StatusManager\Message\Response\MostActiveWatchersResponse;
18
use Jalle19\StatusManager\Message\Response\PopularChannelsResponse;
19
use Jalle19\StatusManager\Message\Response\UsersResponse;
20
use Jalle19\tvheadend\exception\RequestFailedException;
21
use Propel\Runtime\ActiveQuery\Criteria;
22
use Propel\Runtime\Exception\PropelException;
23
use Ratchet\ConnectionInterface;
24
25
/**
26
 * Class StatisticsManager
27
 * @package   Jalle19\StatusManager\Manager
28
 * @copyright Copyright &copy; Sam Stenvall 2016-
29
 * @license   https://www.gnu.org/licenses/gpl.html The GNU General Public License v2.0
30
 */
31
class StatisticsManager extends AbstractManager implements HandlerInterface
32
{
33
34
	/**
35
	 * @inheritdoc
36
	 */
37
	public function handleMessage(AbstractMessage $message, ConnectionInterface $sender)
38
	{
39
		// Wrap database exceptions in the more generic RequestFailedException
40
		try
41
		{
42
			switch ($message->getType())
43
			{
44
				case AbstractMessage::TYPE_POPULAR_CHANNELS_REQUEST:
45
					/* @var PopularChannelsRequest $message */
46
					return new PopularChannelsResponse($message, $this->getPopularChannels(
47
						$message->getInstanceName(),
48
						$message->getUserName(),
49
						$message->getLimit(),
50
						$message->getTimeInterval()));
51
				case AbstractMessage::TYPE_MOST_ACTIVE_WATCHERS_REQUEST:
52
					/* @var MostActiveWatchersRequest $message */
53
					return new MostActiveWatchersResponse($message, $this->getMostActiveWatchers(
54
						$message->getInstanceName(),
55
						$message->getLimit(),
56
						$message->getTimeInterval()));
57
				case AbstractMessage::TYPE_INSTANCES_REQUEST:
58
					/* @var InstancesRequest $message */
59
					return new InstancesResponse($this->configuration->getInstances());
60
				case AbstractMessage::TYPE_USERS_REQUEST:
61
					/* @var UsersRequest $message */
62
					return new UsersResponse($this->getUsers($message->getInstanceName()));
63
			}
64
		}
65
		catch (PropelException $e)
66
		{
67
			throw new RequestFailedException('A database error occured: ' . $e->getMessage());
68
		}
69
70
		return false;
71
	}
72
73
74
	/**
75
	 * @param string      $instanceName
76
	 * @param string|null $userName
77
	 * @param int|null    $limit
78
	 * @param string      $timeInterval
79
	 *
80
	 * @return array the popular channels
81
	 */
82
	private function getPopularChannels($instanceName, $userName, $limit, $timeInterval)
83
	{
84
		// Find the instance and the user
85
		$instance = InstanceQuery::create()->findOneByName($instanceName);
86
		$user     = UserQuery::create()->findOneByName($userName);
87
		$query    = SubscriptionQuery::create()->getPopularChannelsQuery($instance, $user);
88
89
		$query = $this->filterByLimit($limit, $query);
90
		$query = $this->filterBySubscriptionStopped($timeInterval, $query);
91
		$query = $this->filterIgnoredUsers($instanceName, $query->useUserQuery())->endUse();
92
93
		return $query->find()->getData();
94
	}
95
96
97
	/**
98
	 * @param string $instanceName
99
	 * @param int    $limit
100
	 * @param string $timeInterval
101
	 *
102
	 * @return array
103
	 */
104
	private function getMostActiveWatchers($instanceName, $limit, $timeInterval)
105
	{
106
		$instance = InstanceQuery::create()->findOneByName($instanceName);
107
		$query    = UserQuery::create()->getMostActiveWatchersQuery($instance);
108
109
		$query = $this->filterByLimit($limit, $query);
110
		$query = $this->filterBySubscriptionStopped($timeInterval, $query->useSubscriptionQuery())->endUse();
111
		$query = $this->filterIgnoredUsers($instanceName, $query);
112
113
		return $query->find()->getData();
114
	}
115
116
117
	/**
118
	 * Returns all users found so far for the specified instance name
119
	 *
120
	 * @param string $instanceName
121
	 *
122
	 * @return User[]
123
	 */
124
	private function getUsers($instanceName)
125
	{
126
		$query = UserQuery::create();
127
		$query = $this->filterIgnoredUsers($instanceName, $query);
128
129
		return $query->findByInstanceName($instanceName)->getArrayCopy();
130
	}
131
132
133
	/**
134
	 * @param int|null $limit
135
	 * @param mixed    $query a query instance
136
	 *
137
	 * @return mixed
138
	 */
139
	private function filterByLimit($limit, $query)
140
	{
141
		if ($limit !== null)
142
			$query->limit($limit);
143
144
		return $query;
145
	}
146
147
148
	/**
149
	 * @param string            $timeInterval
150
	 * @param SubscriptionQuery $query
151
	 *
152
	 * @return SubscriptionQuery
153
	 */
154
	private function filterBySubscriptionStopped($timeInterval, SubscriptionQuery $query)
155
	{
156
		if ($timeInterval !== StatisticsRequest::TIME_INTERVAL_ALL_TIME)
157
		{
158
			$query = $query->filterByStopped([
159
				'min' => $this->getTimeIntervalTimestamp($timeInterval),
160
			]);
161
		}
162
163
		return $query;
164
	}
165
166
167
	/**
168
	 * @param string    $instanceName
169
	 * @param UserQuery $query
170
	 *
171
	 * @return UserQuery
172
	 */
173
	private function filterIgnoredUsers($instanceName, UserQuery $query)
174
	{
175
		$instance     = $this->configuration->getInstanceByName($instanceName);
176
		$ignoredUsers = $instance->getIgnoredUsers();
177
178
		// Always ignore system users
179
		$ignoredUsers[] = User::NAME_DVR;
180
181
		foreach ($ignoredUsers as $ignoredUser)
182
			$query = $query->filterByName($ignoredUser, Criteria::NOT_EQUAL);
183
184
		return $query;
185
	}
186
187
188
	/**
189
	 * @param string $timeInterval
190
	 *
191
	 * @return int
192
	 */
193
	private function getTimeIntervalTimestamp($timeInterval)
194
	{
195
		$dateTime = new \DateTime();
196
197
		switch ($timeInterval)
198
		{
199
			case StatisticsRequest::TIME_INTERVAL_LAST_MONTH:
200
				$dateTime = $dateTime->modify('-1 month');
201
		}
202
203
		return $dateTime->getTimestamp();
204
	}
205
206
}
207