Completed
Push — master ( 437856...5fb154 )
by greg
03:04
created

MissionGame   B

Complexity

Total Complexity 42

Size/Duplication

Total Lines 285
Duplicated Lines 28.77 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 4
Bugs 2 Features 0
Metric Value
wmc 42
c 4
b 2
f 0
lcom 1
cbo 4
dl 82
loc 285
rs 8.295

14 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
B checkGames() 0 21 5
A checkGamesInMission() 0 22 3
A associate() 0 17 1
A clear() 0 7 2
C checkCondition() 66 68 19
A findMissionGameByMission() 0 4 1
A findMissionGameByGame() 0 4 1
A findMissionGameConditionByMissionGame() 0 4 1
A getServiceManager() 0 4 1
A setServiceManager() 0 6 1
A getMissionGameConditionMapper() 0 10 2
A getMissionGameMapper() 8 8 2
A getGameMapper() 8 8 2

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 MissionGame 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 MissionGame, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace PlaygroundGame\Service;
4
5
use Zend\ServiceManager\ServiceManager;
6
use ZfcBase\EventManager\EventProvider;
7
use PlaygroundGame\Entity\MissionGame as MissionGameEntity;
8
use PlaygroundGame\Entity\MissionGameCondition as MissionGameConditionEntity;
9
use Zend\ServiceManager\ServiceLocatorInterface;
10
11
class MissionGame extends EventProvider
12
{
13
14
    /**
15
    * @var missionMapper
16
    */
17
    protected $missionMapper;
18
     /**
19
    * @var missionGameMapper
20
    */
21
    protected $missionGameMapper;
22
     /**
23
    * @var missionGameConditionMapper
24
    */
25
    protected $missionGameConditionMapper;
26
     /**
27
    * @var gameMapper
28
    */
29
    protected $gameMapper;
30
     /**
31
    * @var options
32
    */
33
    protected $options;
34
35
    /**
36
     *
37
     * @var ServiceManager
38
     */
39
    protected $serviceLocator;
40
41
    public function __construct(ServiceLocatorInterface $locator)
42
    {
43
        $this->serviceLocator = $locator;
0 ignored issues
show
Documentation Bug introduced by
$locator is of type object<Zend\ServiceManag...erviceLocatorInterface>, but the property $serviceLocator was declared to be of type object<Zend\ServiceManager\ServiceManager>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
44
    }
45
46
    public function checkGames($dataGames)
47
    {
48
        $nbGames = count($dataGames);
49
        for ($i=0; $i < $nbGames; $i++) {
50
            if (!empty($dataGames[$i+1])) {
51
                $game1 = $this->getGameMapper()->findById($dataGames[$i]['games']);
52
                $game2 = $this->getGameMapper()->findById($dataGames[$i+1]['games']);
53
54
                if ($game2->getEndDate() === null) {
55
                    continue;
56
                }
57
58
                // Si la date de fin du jeu 2 est inférieur a la date du jeu 1
59
                if ($game2->getEndDate()->getTimestamp() < $game1->getStartDate()->getTimestamp()) {
60
                    return false;
61
                }
62
            }
63
        }
64
65
        return true;
66
    }
67
68
69
    public function checkGamesInMission($dataGames)
70
    {
71
        $gamesId = array();
72
        $nbGames = count($dataGames);
73
        for ($i=0; $i < $nbGames; $i++) {
74
            $gamesId[] = $dataGames[$i]['games'];
75
        }
76
77
        $em = $this->serviceLocator->get('doctrine.entitymanager.orm_default');
78
79
        $query = $em->createQuery('SELECT mg 
80
                                   FROM PlaygroundGame\Entity\MissionGame mg
81
                                   WHERE mg.game IN (:gamesId)');
82
        $query->setParameter('gamesId', $gamesId);
83
        $games = $query->getResult();
84
85
        if (count($games) > 0) {
86
            return false;
87
        }
88
89
        return true;
90
    }
91
    /**
92
    * associate : Permet d'associer des jeux et des conditions à une mission
93
    * @param array $data
94
    * @param Mission $mission
95
    *
96
    * @return MissionGameEntity $missionGameEntity
97
    */
98
    public function associate($data, $mission)
99
    {
100
        $missionGameEntity = new MissionGameEntity();
101
        $game = $this->getGameMapper()->findById($data['games']);
102
        $missionGameEntity->setGame($game);
103
        $missionGameEntity->setPosition($data['position']);
104
        $missionGameEntity->setMission($mission);
105
        $missionGameEntity = $this->getMissionGameMapper()->insert($missionGameEntity);
106
107
        $missionGameConditionEntity = new MissionGameConditionEntity;
108
        $missionGameConditionEntity->setMissionGame($missionGameEntity);
109
        $missionGameConditionEntity->setAttribute($data['conditions']);
110
        $missionGameConditionEntity->setValue($data['points']);
111
        $missionGameConditionEntity = $this->getMissionGameConditionMapper()->insert($missionGameConditionEntity);
0 ignored issues
show
Unused Code introduced by
$missionGameConditionEntity is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
112
113
        return $missionGameEntity;
114
    }
115
116
    /**
117
    * clear : Permet de supprimer l'association des jeux et des conditions à une mission
118
    * @param Mission $mission
119
    */
120
    public function clear($mission)
121
    {
122
        $missionGames = $this->findMissionGameByMission($mission);
123
        foreach ($missionGames as $missionGames) {
124
            $this->getMissionGameMapper()->remove($missionGames);
125
        }
126
    }
127
128
129 View Code Duplication
    public function checkCondition($game, $winner, $prediction, $entry)
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...
130
    {
131
        $missionGame = $this->findMissionGameByGame($game);
132
        if (empty($missionGame)) {
133
            return false;
134
        }
135
136
        if ($missionGame->getMission()->getActive() === false) {
137
            return false;
138
        }
139
140
        $nextMissionGame = $this->getMissionGameMapper()->getNextGame(
141
            $missionGame->getMission(),
142
            $missionGame->getPosition()
143
        );
144
        
145
        if (empty($nextMissionGame)) {
146
            return false;
147
        }
148
149
        $missionGameConditions = $this->findMissionGameConditionByMissionGame($nextMissionGame);
150
        
151
        if (empty($missionGameConditions)) {
152
            return false;
153
        }
154
155
        foreach ($missionGameConditions as $missionGameCondition) {
156
            if ($missionGameCondition->getAttribute() == MissionGameConditionEntity::NONE) {
157
                continue;
158
            }
159
160
            // On passe au suivant si on a gagné
161
            if ($missionGameCondition->getAttribute() == MissionGameConditionEntity::VICTORY) {
162
                if (!($winner || $prediction)) {
163
                    return false;
164
                }
165
            }
166
167
            // On passe au suivant si on a perdu
168
            if ($missionGameCondition->getAttribute() == MissionGameConditionEntity::DEFEAT) {
169
                if ($winner || $prediction) {
170
                    return false;
171
                }
172
            }
173
174
            // On passe au suivant si on a perdu
175
            if ($missionGameCondition->getAttribute() == MissionGameConditionEntity::GREATER) {
176
                if (!$entry) {
177
                    return false;
178
                }
179
                if (!($entry->getPoints() > $missionGameCondition->getValue())) {
180
                    return false;
181
                }
182
            }
183
184
            // On passe au suivant si on a perdu
185
            if ($missionGameCondition->getAttribute() == MissionGameConditionEntity::LESS) {
186
                if (!$entry) {
187
                    return false;
188
                }
189
                if (!($entry->getPoints() < $missionGameCondition->getValue())) {
190
                    return false;
191
                }
192
            }
193
        }
194
195
        return $nextMissionGame->getGame();
196
    }
197
198
    /**
199
    * findMissionGameByMission : Permet de recuperer les missionsGame à partir d'une mission
200
    * @param Mission $mission
201
    *
202
    * @return Collection de MissionGame $missionGames
203
    */
204
    public function findMissionGameByMission($mission)
205
    {
206
        return $this->getMissionGameMapper()->findBy(array('mission'=>$mission));
207
    }
208
209
    /**
210
    * findMissionGameByMission : Permet de recuperer les missionsGame à partir d'une mission
211
    *
212
    * @return Collection de MissionGame $missionGames
213
    */
214
    public function findMissionGameByGame($game)
215
    {
216
        return $this->getMissionGameMapper()->findOneBy(array('game'=>$game));
217
    }
218
219
    /**
220
    * findMissionGameConditionByMissionGame : Permet de recuperer les missionsGameCondition à partir d'une missionGame
221
    * @param MissionGame $missionGame
222
    *
223
    * @return Collection de MissionGameCondition $missionGameConditions
224
    */
225
    public function findMissionGameConditionByMissionGame($missionGame)
226
    {
227
        return $this->getMissionGameConditionMapper()->findBy(array('missionGame'=>$missionGame));
228
    }
229
230
    /**
231
     * Retrieve service manager instance
232
     *
233
     * @return ServiceManager
234
     */
235
    public function getServiceManager()
236
    {
237
        return $this->serviceManager;
0 ignored issues
show
Bug introduced by
The property serviceManager does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
238
    }
239
240
    /**
241
     * Set service manager instance
242
     *
243
     * @return MissionGame
244
     */
245
    public function setServiceManager(ServiceManager $serviceManager)
246
    {
247
        $this->serviceManager = $serviceManager;
248
249
        return $this;
250
    }
251
252
     /**
253
    * getMissionGameConditionMapper : retrieve missionGameCondition mapper instance
254
    *
255
    * @return Mapper/missionGameCondition $missionGameConditionMapper
0 ignored issues
show
Documentation introduced by
The doc-type Mapper/missionGameCondition could not be parsed: Unknown type name "Mapper/missionGameCondition" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
256
    */
257
    public function getMissionGameConditionMapper()
258
    {
259
        if (null === $this->missionGameConditionMapper) {
260
            $this->missionGameConditionMapper = $this->serviceLocator->get(
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->serviceLocator->g...game_condition_mapper') can also be of type array. However, the property $missionGameConditionMapper is declared as type object<PlaygroundGame\Se...ionGameConditionMapper>. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
261
                'playgroundgame_mission_game_condition_mapper'
262
            );
263
        }
264
265
        return $this->missionGameConditionMapper;
266
    }
267
268
    /**
269
    * getMissionGameMapper : retrieve missionGame mapper instance
270
    *
271
    * @return Mapper/MissionGameMapper $missionGameMapper
0 ignored issues
show
Documentation introduced by
The doc-type Mapper/MissionGameMapper could not be parsed: Unknown type name "Mapper/MissionGameMapper" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
272
    */
273 View Code Duplication
    public function getMissionGameMapper()
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...
274
    {
275
        if (null === $this->missionGameMapper) {
276
            $this->missionGameMapper = $this->serviceLocator->get('playgroundgame_mission_game_mapper');
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->serviceLocator->g...e_mission_game_mapper') can also be of type array. However, the property $missionGameMapper is declared as type object<PlaygroundGame\Service\missionGameMapper>. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
277
        }
278
279
        return $this->missionGameMapper;
280
    }
281
282
    /**
283
    * getGameMapper : retrieve game mapper instance
284
    *
285
    * @return Mapper/GameMapper $gameMapper
0 ignored issues
show
Documentation introduced by
The doc-type Mapper/GameMapper could not be parsed: Unknown type name "Mapper/GameMapper" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
286
    */
287 View Code Duplication
    public function getGameMapper()
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...
288
    {
289
        if (null === $this->gameMapper) {
290
            $this->gameMapper = $this->serviceLocator->get('playgroundgame_game_mapper');
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->serviceLocator->g...roundgame_game_mapper') can also be of type array. However, the property $gameMapper is declared as type object<PlaygroundGame\Service\gameMapper>. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
291
        }
292
293
        return $this->gameMapper;
294
    }
295
}
296