Completed
Pull Request — master (#182)
by De Cramer
52:24 queued 46:41
created

GuiHandler   B

Complexity

Total Complexity 50

Size/Duplication

Total Lines 332
Duplicated Lines 9.04 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 95.2%

Importance

Changes 0
Metric Value
wmc 50
lcom 1
cbo 6
dl 30
loc 332
ccs 119
cts 125
cp 0.952
rs 8.6206
c 0
b 0
f 0

19 Methods

Rating   Name   Duplication   Size   Complexity  
A getDisplayeds() 0 4 1
A __construct() 0 16 1
A onPlayerConnect() 0 3 1
A addToDisplay() 0 12 2
A addToHide() 0 16 3
A getManialink() 0 12 4
B displayManialinks() 0 32 5
A executeMultiCall() 0 9 2
D getManialinksToDisplay() 0 45 12
A setCharLimit() 0 4 1
A onPostLoop() 0 4 1
A onPreLoop() 0 3 1
A onEverySecond() 0 3 1
B onExpansionGroupAddUser() 15 15 5
B onExpansionGroupRemoveUser() 15 15 5
A onExpansionGroupDestroy() 0 6 2
A onPlayerDisconnect() 0 5 1
A onPlayerInfoChanged() 0 3 1
A onPlayerAlliesChanged() 0 3 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like GuiHandler 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 GuiHandler, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace eXpansion\Framework\Core\Plugins;
4
5
use eXpansion\Framework\Core\DataProviders\Listener\ListenerInterfaceExpTimer;
6
use eXpansion\Framework\Core\DataProviders\Listener\ListenerInterfaceExpUserGroup;
7
use eXpansion\Framework\GameManiaplanet\DataProviders\Listener\ListenerInterfaceMpLegacyPlayer;
8
use eXpansion\Framework\Core\Model\Gui\ManialinkFactoryInterface;
9
use eXpansion\Framework\Core\Model\Gui\ManialinkInterface;
10
use eXpansion\Framework\Core\Model\UserGroups\Group;
11
use eXpansion\Framework\Core\Plugins\Gui\ActionFactory;
12
use eXpansion\Framework\Core\Plugins\Gui\ManialinkFactory;
13
use eXpansion\Framework\Core\Services\Console;
14
use eXpansion\Framework\Core\Storage\Data\Player;
15
use Maniaplanet\DedicatedServer\Connection;
16
use oliverde8\AssociativeArraySimplified\AssociativeArray;
17
use Psr\Log\LoggerInterface;
18
19
/**
20
 * Class GuiHandler will send manialinks to player as needed.
21
 *
22
 * @package eXpansion\Framework\Core\Plugins\Gui
23
 * @author Oliver de Cramer
24
 */
25
class GuiHandler implements
26
    ListenerInterfaceExpTimer,
27
    ListenerInterfaceExpUserGroup,
28
    ListenerInterfaceMpLegacyPlayer,
29
    GuiHandlerInterface
30
{
31
    /** @var Connection */
32
    protected $connection;
33
34
    /** @var LoggerInterface */
35
    protected $logger;
36
37
    /** @var Console */
38
    protected $console;
39
40
    /** @var ActionFactory */
41
    protected $actionFactory;
42
43
    /** @var int */
44
    protected $charLimit;
45
46
    /** @var ManialinkInterface[][] */
47
    protected $displayQueu = [];
48
49
    /** @var ManialinkInterface[][] */
50
    protected $individualQueu = [];
51
52
    /** @var ManialinkInterface[][] */
53
    protected $displayeds = [];
54
55
    /** @var ManialinkInterface[][] */
56
    protected $hideQueu = [];
57
58
    /** @var ManialinkInterface[][] */
59
    protected $hideIndividualQueu = [];
60
61
    /** @var String[] */
62
    protected $disconnectedLogins = [];
63
64
    /**
65
     * GuiHandler constructor.
66
     *
67
     * @param Connection $connection
68
     */
69 13
    public function __construct(
70
        Connection $connection,
71
        LoggerInterface $logger,
72
        Console $console,
73
        ActionFactory $actionFactory,
74
        $charLimit = 262144
75
    ) {
76 13
        $this->connection = $connection;
77
78 13
        $this->connection->sendHideManialinkPage(null);
79
80 13
        $this->logger = $logger;
81 13
        $this->console = $console;
82 13
        $this->actionFactory = $actionFactory;
83 13
        $this->charLimit = $charLimit;
84 13
    }
85
86
87
    /**
88
     * @inheritdoc
89
     **/
90 11
    public function addToDisplay(ManialinkInterface $manialink)
91
    {
92
93 11
        $userGroup = $manialink->getUserGroup()->getName();
94 11
        $id = $manialink->getManialinkFactory()->getId();
95
96 11
        if (AssociativeArray::getFromKey($this->hideQueu, [$userGroup, $id])) {
97 1
            unset($this->hideQueu[$userGroup][$id]);
98
        }
99
100 11
        $this->displayQueu[$userGroup][$id] = $manialink;
101 11
    }
102
103
    /**
104
     * @inheritdoc
105
     */
106 3
    public function addToHide(ManialinkInterface $manialink)
107
    {
108 3
        $userGroup = $manialink->getUserGroup()->getName();
109 3
        $id = $manialink->getManialinkFactory()->getId();
110
111 3
        if (AssociativeArray::getFromKey($this->displayQueu, [$userGroup, $id])) {
112 1
            unset($this->displayQueu[$userGroup][$id]);
113
        }
114
115 3
        if (AssociativeArray::getFromKey($this->displayeds, [$userGroup, $id])) {
116 1
            unset($this->displayeds[$userGroup][$id]);
117
        }
118
119 3
        $this->actionFactory->destroyManialinkActions($manialink);
120 3
        $this->hideQueu[$userGroup][$id] = $manialink;
121 3
    }
122
123
    /**
124
     * @inheritdoc
125
     */
126
    public function getManialink(Group $group, ManialinkFactoryInterface $manialinkFactory)
127
    {
128
        $varsToCheck = ['displayeds', 'hideQueu', 'displayQueu'];
129
130
        foreach ($varsToCheck as $var) {
131
            if (isset($this->$var[$group->getName()]) && isset($this->$var[$group->getName()][$manialinkFactory->getId()])) {
132
                return $this->$var[$group->getName()][$manialinkFactory->getId()];
133
            }
134
        }
135
136
        return null;
137
    }
138
139
    /**
140
     * Display & hide all manialinks.
141
     */
142 12
    protected function displayManialinks()
143
    {
144 12
        $size = 0;
145 12
        foreach ($this->getManialinksToDisplay() as $mlData) {
146 12
            $currentSize = $size;
147 12
            $size += strlen($mlData['ml']);
148
149 12
            if ($currentSize != 0 && $size > $this->charLimit) {
150 2
                $this->executeMultiCall();
151 2
                $size = strlen($mlData['ml']);
152
            }
153
154 12
            $this->connection->sendDisplayManialinkPage(
155 12
                $mlData['logins'],
156 12
                $mlData['ml'],
157 12
                0,
158 12
                false,
159 12
                true
160
            );
161
        }
162
163 12
        if ($size > 0) {
164 12
            $this->executeMultiCall();
165
        }
166
167
        // Reset the queues.
168 12
        $this->displayQueu = [];
169 12
        $this->individualQueu = [];
170 12
        $this->hideQueu = [];
171 12
        $this->hideIndividualQueu = [];
172 12
        $this->disconnectedLogins = [];
173 12
    }
174
175
    /**
176
     * Execute multi call & handle error.
177
     */
178 12
    protected function executeMultiCall()
179
    {
180
        try {
181 12
            $this->connection->executeMulticall();
182 1
        } catch (\Exception $e) {
183 1
            $this->logger->error("Couldn't deliver all manialinks : ".$e->getMessage(), ['exception' => $e]);
184 1
            $this->console->writeln('$F00ERROR - Couldn\'t deliver all manialinks : '.$e->getMessage());
185
        }
186 12
    }
187
188
    /**
189
     * Get list of all manialinks that needs to be displayed
190
     *
191
     * @return \Generator
192
     */
193 12
    protected function getManialinksToDisplay()
194
    {
195 12
        foreach ($this->displayQueu as $groupName => $manialinks) {
196 11
            foreach ($manialinks as $factoryId => $manialink) {
197 11
                $logins = $manialink->getUserGroup()->getLogins();
198
199 11
                $this->displayeds[$groupName][$factoryId] = $manialink;
200 11
                if (!empty($logins)) {
201 11
                    yield ['logins' => $logins, 'ml' => $manialink->getXml()];
202
                }
203
            }
204
        }
205
206 12
        foreach ($this->individualQueu as $login => $manialinks) {
207 3
            foreach ($manialinks as $manialink) {
208 2
                $xml = $manialink->getXml();
209 3
                yield ['logins' => $login, 'ml' => $xml];
210
            }
211
        }
212
213 12
        foreach ($this->hideQueu as $manialinks) {
214 3
            foreach ($manialinks as $manialink) {
215 2
                $id = $manialink->getId();
216 2
                $manialink->destroy();
217
218 2
                $logins = $manialink->getUserGroup()->getLogins();
219 2
                $logins = array_diff($logins, $this->disconnectedLogins);
220
221 2
                if (!empty($logins)) {
222 3
                    yield ['logins' => $logins, 'ml' => '<manialink id="'.$id.'" />'];
223
                }
224
            }
225
        }
226
227 12
        foreach ($this->hideIndividualQueu as $login => $manialinks) {
228 4
            foreach ($manialinks as $manialink) {
229 3
                $id = $manialink->getId();
230
                // Manialink is not destroyed just not shown at a particular user that left the group.
231
232 3
                if (!in_array($login, $this->disconnectedLogins)) {
233 4
                    yield ['logins' => $login, 'ml' => '<manialink id="'.$id.'" />'];
234
                }
235
            }
236
        }
237 12
    }
238
239
    /**
240
     * @param int $charLimit
241
     */
242 2
    public function setCharLimit($charLimit)
243
    {
244 2
        $this->charLimit = $charLimit;
245 2
    }
246
247
    /**
248
     * List of all manialinks that are currently displayed.
249
     *
250
     * @return ManialinkInterface[][]
251
     */
252 1
    public function getDisplayeds()
253
    {
254 1
        return $this->displayeds;
255
    }
256
257
    /**
258
     * @inheritdoc
259
     */
260 12
    public function onPostLoop()
261
    {
262 12
        $this->displayManialinks();
263 12
    }
264
265
    /**
266
     * @inheritdoc
267
     */
268 1
    public function onPreLoop()
269
    {
270 1
    }
271
272
    /**
273
     * @inheritdoc
274
     */
275 1
    public function onEverySecond()
276
    {
277 1
    }
278
279
    /**
280
     * @inheritdoc
281
     */
282 3 View Code Duplication
    public function onExpansionGroupAddUser(Group $group, $loginAdded)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
283
    {
284 3
        $group = $group->getName();
285
286
        // User was added to group, need to display all manialinks of the group to this user
287 3
        if (isset($this->displayeds[$group])) {
288 3
            foreach ($this->displayeds[$group] as $mlId => $manialink) {
289 3
                $this->individualQueu[$loginAdded][$mlId] = $manialink;
290
291 3
                if (isset($this->hideIndividualQueu[$loginAdded]) && isset($this->hideIndividualQueu[$loginAdded][$mlId])) {
292 3
                    unset ($this->hideIndividualQueu[$loginAdded][$mlId]);
293
                }
294
            }
295
        }
296 3
    }
297
298
    /**
299
     * @inheritdoc
300
     */
301 4 View Code Duplication
    public function onExpansionGroupRemoveUser(Group $group, $loginRemoved)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
302
    {
303 4
        $group = $group->getName();
304
305
        // User was removed from group, need to hide all manialinks of the group to this user
306 4
        if (isset($this->displayeds[$group])) {
307 4
            foreach ($this->displayeds[$group] as $mlId => $manialink) {
308 4
                $this->hideIndividualQueu[$loginRemoved][$mlId] = $manialink;
309
310 4
                if (isset($this->individualQueu[$loginRemoved]) && isset($this->individualQueu[$loginRemoved][$mlId])) {
311 4
                    unset ($this->individualQueu[$loginRemoved][$mlId]);
312
                }
313
            }
314
        }
315 4
    }
316
317
    /**
318
     * @inheritdoc
319
     */
320 1
    public function onExpansionGroupDestroy(Group $group, $lastLogin)
321
    {
322 1
        if (isset($this->displayeds[$group->getName()])) {
323 1
            unset($this->displayeds[$group->getName()]);
324
        }
325 1
    }
326
327
    /**
328
     * @inheritdoc
329
     */
330 1
    public function onPlayerConnect(Player $player)
331
    {
332 1
    }
333
334
    /**
335
     * @inheritdoc
336
     */
337 1
    public function onPlayerDisconnect(Player $player, $disconnectionReason)
338
    {
339
        // To prevent sending manialinks to those players.
340 1
        $this->disconnectedLogins[] = $player->getLogin();
341 1
    }
342
343
    /**
344
     * @inheritdoc
345
     */
346 1
    public function onPlayerInfoChanged(Player $oldPlayer, Player $player)
347
    {
348 1
    }
349
350
    /**
351
     * @inheritdoc
352
     */
353 1
    public function onPlayerAlliesChanged(Player $oldPlayer, Player $player)
354
    {
355 1
    }
356
}
357