Completed
Push — master ( 2a3483...c07a8d )
by De Cramer
02:05 queued 02:03
created

Analytics   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 212
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 19
lcom 1
cbo 8
dl 0
loc 212
ccs 0
cts 116
cp 0
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 17 1
A setStatus() 0 6 3
B handshake() 0 39 4
C ping() 0 40 7
A getBasePingData() 0 19 1
A onPreLoop() 0 4 1
A onPostLoop() 0 4 1
A onEverySecond() 0 4 1
1
<?php
2
3
namespace eXpansion\Framework\Core\Plugins;
4
5
use eXpansion\Framework\Core\DataProviders\Listener\ListenerInterfaceExpTimer;
6
use eXpansion\Framework\Core\Helpers\Http;
7
use eXpansion\Framework\Core\Helpers\Structures\HttpResult;
8
use eXpansion\Framework\Core\Services\Application;
9
use eXpansion\Framework\Core\Storage\GameDataStorage;
10
use eXpansion\Framework\Core\Storage\PlayerStorage;
11
use Psr\Log\LoggerInterface;
12
13
/**
14
 * Class Analytics
15
 *
16
 * @author    de Cramer Oliver<[email protected]>
17
 * @copyright 2018 eXpansion
18
 * @package eXpansion\Framework\Core\Plugins
19
 */
20
class Analytics implements ListenerInterfaceExpTimer, StatusAwarePluginInterface
21
{
22
    /** @var Http */
23
    protected $http;
24
25
    /** @var GameDataStorage */
26
    protected $gameData;
27
28
    /** @var PlayerStorage */
29
    protected $playerStorage;
30
31
    /** @var LoggerInterface */
32
    protected $logger;
33
34
    /** @var string  */
35
    protected $url;
36
37
    /** @var int */
38
    protected $pingInterval;
39
40
    /** @var int */
41
    protected $retryInterval;
42
43
    /** @var bool Is a call in progress. */
44
    protected $operationInProgress = false;
45
46
    /** @var string */
47
    protected $key = null;
48
49
    /** @var int */
50
    protected $lastPing;
51
52
    /**
53
     * Analytics constructor.
54
     *
55
     * @param Http $http
56
     * @param GameDataStorage $gameData
57
     * @param PlayerStorage $playerStorage
58
     * @param LoggerInterface $logger
59
     * @param string $url
60
     * @param int $pingInterval
61
     * @param int $retryInterval
62
     */
63
    public function __construct(
64
        Http $http,
65
        GameDataStorage $gameData,
66
        PlayerStorage $playerStorage,
67
        LoggerInterface $logger,
68
        string $url,
69
        int $pingInterval,
70
        int $retryInterval
71
    ) {
72
        $this->http = $http;
73
        $this->gameData = $gameData;
74
        $this->playerStorage = $playerStorage;
75
        $this->logger = $logger;
76
        $this->url = $url;
77
        $this->pingInterval = $pingInterval;
78
        $this->retryInterval = $retryInterval;
79
    }
80
81
82
    /**
83
     * Set the status of the plugin
84
     *
85
     * @param boolean $status
86
     *
87
     * @return null
88
     */
89
    public function setStatus($status)
90
    {
91
        if ($status && !$this->operationInProgress) {
92
            $this->handshake();
93
        }
94
    }
95
96
    /**
97
     * Handshake with analytics tool!
98
     */
99
    protected function handshake()
100
    {
101
        $key =        &$this->key;
102
        $lastPing =   &$this->lastPing;
103
        $that = $this;
104
        $logger = $this->logger;
105
106
        $query = http_build_query(
107
            ['page' => 'handshake', 'server-login' => $this->gameData->getSystemInfo()->serverLogin]
108
        );
109
        $url = $this->url . '?' . $query;
110
111
        $lastPing = time();
112
        $this->logger->debug("[eXpansion analytics]Starting handshake");
113
114
115
        $this->http->get(
116
            $url,
117
            function (HttpResult $result) use (&$key, &$lastPing, $logger, $that) {
118
                $key = null;
119
120
                if ($result->getHttpCode() != '200') {
121
                    $logger->debug('[eXpansion analytics]Handshake failed', ['http_code' => $result->getHttpCode()]);
122
                    return;
123
                }
124
125
                $json = json_decode($result->getResponse());
126
                if (isset($json->key) && !empty($json->key)) {
127
                    $logger->debug('[eXpansion analytics]Handshake successfull', ['key' => $json->key]);
128
129
                    $key = $json->key;
130
                    $that->ping();
131
132
                    // allow ping just after handshake.
133
                    $lastPing = 0;
134
                }
135
            }
136
        );
137
    }
138
139
    /**
140
     * Ping the analytics server with proper information.
141
     */
142
    public function ping()
143
    {
144
        if (!$this->key || $this->operationInProgress || (time() - $this->lastPing) < $this->pingInterval) {
145
            // Attempt a new handshake.
146
            if (is_null($this->key) && (time() - $this->lastPing) > $this->retryInterval) {
147
                $this->lastPing = time();
148
                $this->handshake();
149
            }
150
151
            return;
152
        }
153
154
        $data = $this->getBasePingData();
155
        $data['page'] = 'ping';
156
157
        $query = http_build_query(
158
            $data
159
        );
160
        $url = $this->url . '?' . $query;
161
162
        $this->operationInProgress = true;
163
        $this->lastPing = time();
164
        $operationInProgress = &$this->operationInProgress;
165
        $key = &$this->key;
166
        $logger = $this->logger;
167
168
        $logger->debug('[eXpansion analytics]Starting ping');
169
        $this->http->get(
170
            $url,
171
            function (HttpResult $result) use (&$operationInProgress, &$key, $logger) {
172
                if ($result->getHttpCode() == '200') {
173
                    $operationInProgress = false;
174
                    $logger->debug('[eXpansion analytics]Ping successfull');
175
                } else {
176
                    $logger->debug('[eXpansion analytics]Ping failed', ['http_code' => $result->getHttpCode(), 'result' => $result->getResponse()]);
177
                    $key = null;
178
                }
179
            }
180
        );
181
    }
182
183
    /**
184
     * Get base data for pinging the server.
185
     *
186
     * @return array
187
     */
188
    protected function getBasePingData()
189
    {
190
        return [
191
            'key' => $this->key,
192
            'nbPlayers' => count($this->playerStorage->getOnline()),
193
            'country' => $this->gameData->getServerCountry(),
194
            'version' => Application::EXPANSION_VERSION,
195
            'php_version' => $this->gameData->getServerCleanPhpVersion(),
196
            'php_version_short' => $this->gameData->getServerMajorPhpVersion(),
197
            'mysql_version' => 'unknown',
198
            'memory' => memory_get_usage(),
199
            'memory_peak' => memory_get_peak_usage(),
200
            'build' => '',
201
            'title' => str_replace('@','_by_', $this->gameData->getVersion()->titleId),
202
            'game' => $this->gameData->getTitle(),
203
            'mode' => $this->gameData->getGameInfos()->scriptName,
204
            'serverOs' => $this->gameData->getServerOs(),
205
        ];
206
    }
207
208
    /**
209
     * @inheritdoc
210
     */
211
    public function onPreLoop()
212
    {
213
        // Nothing.
214
    }
215
216
    /**
217
     * @inheritdoc
218
     */
219
    public function onPostLoop()
220
    {
221
        // Nothing.
222
    }
223
224
    /**
225
     * @inheritdoc
226
     */
227
    public function onEverySecond()
228
    {
229
        $this->ping();
230
    }
231
}