Completed
Push — dev ( 007c56...e65940 )
by
unknown
04:40
created

GuiHandler   B

Complexity

Total Complexity 42

Size/Duplication

Total Lines 280
Duplicated Lines 7.5 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 42
lcom 1
cbo 6
dl 21
loc 280
ccs 91
cts 91
cp 1
rs 8.295
c 0
b 0
f 0

14 Methods

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