Completed
Push — master ( 50c02f...203180 )
by greg
02:48
created

InstantWin::createOrUpdate()   C

Complexity

Conditions 8
Paths 9

Size

Total Lines 43
Code Lines 28

Duplication

Lines 11
Ratio 25.58 %

Importance

Changes 0
Metric Value
dl 11
loc 43
rs 5.3846
c 0
b 0
f 0
cc 8
eloc 28
nc 9
nop 3
1
<?php
2
3
namespace PlaygroundGame\Service;
4
5
use Zend\Stdlib\ErrorHandler;
6
7
class InstantWin extends Game
8
{
9
    /**
10
     * @var InstantWinOccurrenceMapperInterface
11
     */
12
    protected $instantWinOccurrenceMapper;
13
14
    protected $prizeMapper;
15
16
    /**
17
     *
18
     * saving an instantwin image if any
19
     *
20
     * @param  array                  $data
21
     * @param  string                 $formClass
22
     * @return \PlaygroundGame\Entity\Game
23
     */
24
    public function createOrUpdate(array $data, $game, $formClass)
25
    {
26
        $game = parent::createOrUpdate($data, $game, $formClass);
27
28
        if ($game) {
29
            $path = $this->getOptions()->getMediaPath() . DIRECTORY_SEPARATOR;
30
            $media_url = $this->getOptions()->getMediaUrl() . '/';
31
32
            if (!empty($data['uploadScratchcardImage']['tmp_name'])) {
33
                ErrorHandler::start();
34
                $data['uploadScratchcardImage']['name'] = $this->fileNewname(
35
                    $path,
36
                    $game->getId() . "-" . $data['uploadScratchcardImage']['name']
37
                );
38
                move_uploaded_file(
39
                    $data['uploadScratchcardImage']['tmp_name'],
40
                    $path . $data['uploadScratchcardImage']['name']
41
                );
42
                $game->setScratchcardImage($media_url . $data['uploadScratchcardImage']['name']);
43
                ErrorHandler::stop(true);
44
45
                $game = $this->getGameMapper()->update($game);
46
            }
47
48 View Code Duplication
            if (isset($data['deleteScratchcardImage']) &&
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...
49
                $data['deleteScratchcardImage'] &&
50
                empty($data['uploadScratchcardImage']['tmp_name'])
51
            ) {
52
                ErrorHandler::start();
53
                $image = $game->getScratchcardImage();
54
                $image = str_replace($media_url, '', $image);
55
                unlink($path .$image);
56
                $game->setScratchcardImage(null);
57
                ErrorHandler::stop(true);
58
            }
59
60
            if ($game->getOccurrenceNumber() && $game->getScheduleOccurrenceAuto()) {
61
                $this->scheduleOccurrences($game, $data);
62
            }
63
        }
64
65
        return $game;
66
    }
67
68
    /**
69
     * We can create Instant win occurrences dynamically
70
     *
71
     *
72
     * @param  array                  $data
73
     * @return boolean|null
74
     */
75
    public function scheduleOccurrences($game, array $data)
76
    {
77
        // It will be quite long to create these occurrences !
78
        set_time_limit(0);
79
        if ($game->getOccurrenceType() === 'code') {
80
            return $this->scheduleCodeOccurrences($game, $data);
81
        } elseif ($game->getOccurrenceType() === 'datetime') {
82
            return $this->scheduleDateOccurrences($game);
83
        }
84
    }
85
86
    public function scheduleCodeOccurrences($game, $data)
87
    {
88
        $available_characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-';
89
        $last_character_index = strlen($available_characters)-1;
90
        if (!$game->getWinningOccurrenceNumber()) {
91
            $game->setWinningOccurrenceNumber($game->getOccurrenceNumber());
92
        }
93
        if (empty($data['occurrenceValueSize'])) {
94
            $data['occurrenceValueSize'] = 8;
95
        }
96
        $created = 0;
97
        $numOccurrences = $game->getOccurrenceNumber();
98
        
99
        for ($i=0; $i < $numOccurrences; $i++) {
100
            $code = '';
101
            while (strlen($code)<$data['occurrenceValueSize']) {
102
                $code .= $available_characters[rand(0, $last_character_index)];
103
            }
104
            $occurrence = new \PlaygroundGame\Entity\InstantWinOccurrence();
105
            $occurrence->setInstantwin($game);
106
            $occurrence->setValue($code);
107
            $occurrence->setActive(1);
108
            $occurrence->setWinning($created < $game->getWinningOccurrenceNumber());
109
            if ($this->getInstantWinOccurrenceMapper()->insert($occurrence)) {
110
                $created++;
111
            }
112
        }
113
        return true;
114
    }
115
116
    public function createRandomOccurrences($game, $beginning, $end, $quantity)
117
    {
118
        for ($i=1; $i<=$quantity; $i++) {
119
            $randomDate = $this->getRandomDate($beginning->format('U'), $end->format('U'));
120
            $randomDate = \DateTime::createFromFormat('Y-m-d H:i:s', $randomDate);
121
            $occurrence  = new \PlaygroundGame\Entity\InstantWinOccurrence();
122
            $occurrence->setInstantwin($game);
123
            $occurrence->setValue($randomDate->format('Y-m-d H:i:s'));
124
            $occurrence->setActive(1);
125
126
            $this->getInstantWinOccurrenceMapper()->insert($occurrence);
127
        }
128
    }
129
130
    public function scheduleDateOccurrences($game)
131
    {
132
        $f = $game->getOccurrenceDrawFrequency();
133
        $today    = new \DateTime("now");
134
        $end      = new \DateTime("now");
135
        $interval = 'P10D';
136
        if ($game->getStartDate() && $game->getStartDate() > $today) {
137
            $beginning = $game->getStartDate();
138
        } else {
139
            $beginning = $today;
140
        }
141
142
        if ($game->getEndDate()) {
143
            $end = $game->getEndDate();
144
        } else {
145
            $end->add(new \DateInterval($interval));
146
        }
147
148
        // Summertimes timezone management
149
        $timezone = $today->getTimezone();
150
        $transitions = $timezone->getTransitions($beginning->getTimestamp(), $end->getTimestamp());
151
152
        // There is a time transition between these datetimes()
153
        if (count($transitions) == 2) {
154
            $shift = $transitions[0]['offset'] - $transitions[1]['offset'];
155
            if ($shift > 0) {
156
                $end->sub(new \DateInterval('PT'.abs($shift).'S'));
157
            } else {
158
                $end->add(new \DateInterval('PT'.abs($shift).'S'));
159
            }
160
        }
161
162
        // DateInterval takes the day @ 00:00 to calculate the difference between the dates, so 1 day is always missing
163
        // as we consider the last day @ 23:59:59 in Playground :)
164
        if ($end->format('His') == 0) {
165
            $end->add(new \DateInterval('P1D'));
166
        }
167
168
        $dateInterval = (int)(($end->getTimestamp() - $beginning->getTimestamp())/60);
169
170
        // Je recherche tous les IG non gagnés
171
        $occurrences = $this->getInstantWinOccurrenceMapper()->findBy(array('instantwin' => $game));
172
        $nbExistingOccurrences = count($occurrences);
173
        $nbOccurencesToCreate = 0;
174
175
        switch ($f) {
176
            case null:
177
            case 'game':
178
                $nbOccurencesToCreate = $game->getOccurrenceNumber() - $nbExistingOccurrences;
179
                if ($nbOccurencesToCreate > 0) {
180
                    $this->createRandomOccurrences($game, $beginning, $end, $nbOccurencesToCreate);
181
                }
182
183
                break;
184 View Code Duplication
            case 'hour':
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...
185
                $nbInterval = (int) ($dateInterval/60);
186
187
                // If a hour don't last 60min, I consider it as a hour anyway.
188
                if ($dateInterval%60 > 0) {
189
                    ++$nbInterval;
190
                }
191
                if ($nbInterval > 0) {
192
                    $nbOccurencesToCreate = $game->getOccurrenceNumber() - floor($nbExistingOccurrences/$nbInterval);
193
                }
194
195
                $beginningDrawDate = \DateTime::createFromFormat('m/d/Y H:i:s', $beginning->format('m/d/Y H:i:s'));
196
                $endDrawDate = \DateTime::createFromFormat('m/d/Y H:i:s', $beginning->format('m/d/Y H'). ':59:59');
197
                
198
                if ($nbOccurencesToCreate > 0) {
199
                    for ($d=1; $d<=$nbInterval; $d++) {
200
                        $this->createRandomOccurrences(
201
                            $game,
202
                            $beginningDrawDate,
203
                            $endDrawDate,
204
                            $nbOccurencesToCreate
205
                        );
206
                        $beginningDrawDate = \DateTime::createFromFormat(
207
                            'm/d/Y H:i:s',
208
                            $beginningDrawDate->format('m/d/Y H'). ':00:00'
209
                        );
210
                        $beginningDrawDate->add(new \DateInterval('PT1H'));
211
                        $endDrawDate->add(new \DateInterval('PT1H'));
212
                    }
213
                }
214
215
                break;
216 View Code Duplication
            case 'day':
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...
217
                $nbInterval = (int) ($dateInterval/(60*24));
218
219
                // Prise en compte des changements d'horaires
220
                // If a day don't last 24h, I consider it as a day anyway
221
222
                if ($dateInterval%(60*24) > 0) {
223
                    ++$nbInterval;
224
                }
225
226
                if ($nbInterval > 0) {
227
                    $nbOccurencesToCreate = $game->getOccurrenceNumber() - floor($nbExistingOccurrences/$nbInterval);
228
                }
229
230
                $beginningDrawDate = \DateTime::createFromFormat('m/d/Y H:i:s', $beginning->format('m/d/Y H:i:s'));
231
                $endDrawDate = \DateTime::createFromFormat('m/d/Y H:i:s', $beginning->format('m/d/Y'). ' 23:59:59');
232
                
233
                if ($nbOccurencesToCreate > 0) {
234
                    for ($d=1; $d<=$nbInterval; $d++) {
235
                        $this->createRandomOccurrences(
236
                            $game,
237
                            $beginningDrawDate,
238
                            $endDrawDate,
239
                            $nbOccurencesToCreate
240
                        );
241
                        // As the first beginning date was not @ midnight,
242
                        // I recreate the beginning date
243
                        $beginningDrawDate = \DateTime::createFromFormat(
244
                            'm/d/Y H:i:s',
245
                            $beginningDrawDate->format('m/d/Y'). ' 00:00:00'
246
                        );
247
                        $beginningDrawDate->add(new \DateInterval('P1D'));
248
                        $endDrawDate->add(new \DateInterval('P1D'));
249
                    }
250
                }
251
252
                break;
253 View Code Duplication
            case 'week':
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...
254
                $nbOccurencesToCreate = $game->getOccurrenceNumber() - $nbExistingOccurrences;
255
                $nbWeeksInterval = (int) ($dateInterval/(60*24*7));
256
                // If a week don't last 7d, I consider it as a week anyway.
257
                if ($dateInterval%(60*24*7) > 0) {
258
                    ++$nbWeeksInterval;
259
                }
260
                $beginningDrawDate = \DateTime::createFromFormat(
261
                    'm/d/Y H:i:s',
262
                    $beginning->format('m/d/Y'). ' 00:00:00'
263
                );
264
                $endDrawDate = \DateTime::createFromFormat(
265
                    'm/d/Y H:i:s',
266
                    $beginning->format('m/d/Y'). ' 23:59:59'
267
                );
268
                $endDrawDate->add(new \DateInterval('P6D'));
269
                if ($endDrawDate > $end) {
270
                    $endDrawDate = $end;
271
                }
272
273
                if ($nbOccurencesToCreate > 0) {
274
                    for ($d=1; $d<=$nbWeeksInterval; $d++) {
275
                        $this->createRandomOccurrences(
276
                            $game,
277
                            $beginningDrawDate,
278
                            $endDrawDate,
279
                            $nbOccurencesToCreate
280
                        );
281
                        $beginningDrawDate->add(new \DateInterval('P1W'));
282
                        $endDrawDate->add(new \DateInterval('P1W'));
283
                        if ($endDrawDate > $end) {
284
                            $endDrawDate = $end;
285
                        }
286
                    }
287
                }
288
289
                break;
290 View Code Duplication
            case 'month':
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...
291
                $nbOccurencesToCreate = $game->getOccurrenceNumber() - $nbExistingOccurrences;
292
                $nbMonthsInterval = (int) ($dateInterval/(60*24*30));
293
                // If a week don't last 30d, I consider it as a month anyway.
294
                if ($dateInterval%(60*24*30) > 0) {
295
                    ++$nbMonthsInterval;
296
                }
297
                $beginningDrawDate = \DateTime::createFromFormat(
298
                    'm/d/Y H:i:s',
299
                    $beginning->format('m/d/Y'). ' 00:00:00'
300
                );
301
                $endDrawDate = \DateTime::createFromFormat('m/d/Y H:i:s', $beginning->format('m/d/Y'). ' 23:59:59');
302
                $endDrawDate->add(new \DateInterval('P1M'));
303
                $endDrawDate->sub(new \DateInterval('P1D'));
304
                if ($endDrawDate > $end) {
305
                    $endDrawDate = $end;
306
                }
307
308
                if ($nbOccurencesToCreate > 0) {
309
                    for ($d=1; $d<=$nbMonthsInterval; $d++) {
310
                        $this->createRandomOccurrences(
311
                            $game,
312
                            $beginningDrawDate,
313
                            $endDrawDate,
314
                            $nbOccurencesToCreate
315
                        );
316
                        $beginningDrawDate->add(new \DateInterval('P1M'));
317
                        $endDrawDate->add(new \DateInterval('P1M'));
318
                        if ($endDrawDate > $end) {
319
                            $endDrawDate = $end;
320
                        }
321
                    }
322
                }
323
324
                break;
325
        }
326
327
        return true;
328
    }
329
330
    public function getRandomDate($min_date, $max_date)
331
    {
332
        $rand_epoch = rand($min_date, $max_date);
333
334
        return date('Y-m-d H:i:s', $rand_epoch);
335
    }
336
337
    /**
338
     * @param string $fileName
339
     */
340
    public function getOccurencesFromCSV($fileName)
341
    {
342
        if (file_exists($fileName)) {
343
            $csvFile = fopen($fileName, 'r');
344
            if ($csvFile) {
345
                while (!feof($csvFile)) {
346
                    $csvContent[] = fgetcsv($csvFile);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$csvContent was never initialized. Although not strictly required by PHP, it is generally a good practice to add $csvContent = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
347
                }
348
                fclose($csvFile);
349
                return $csvContent;
0 ignored issues
show
Bug introduced by
The variable $csvContent does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
350
            }
351
        }
352
        return false;
353
    }
354
355
    public function setOccurencesToCSV($game)
356
    {
357
        $path = $this->getOptions()->getMediaPath() . DIRECTORY_SEPARATOR;
358
        $fileName = $path.'occurences-'.$game->getId().'.csv';
359
        $csvFile = fopen($fileName, 'w');
360
        if ($csvFile) {
361
            $occurrences = $this->getInstantWinOccurrenceMapper()->findByGameId($game);
362
            foreach ($occurrences as $occurrence) {
363
                fputcsv($csvFile, array($occurrence->getValue(), $occurrence->getWinning()));
364
            }
365
            fclose($csvFile);
366
            return $fileName;
367
        }
368
        return false;
369
    }
370
371
    public function importOccurrences($data)
372
    {
373
        if (!empty($data['file']['tmp_name'])) {
374
            $path = $this->getOptions()->getMediaPath() . DIRECTORY_SEPARATOR;
375
            $real_media_path = realpath($path) . DIRECTORY_SEPARATOR;
376
377
            // upload the csv file
378
            ErrorHandler::start();
379
            $data['file']['name'] = $this->fileNewname($path, $data['instant_win_id'] . "-" . $data['file']['name']);
380
            move_uploaded_file($data['file']['tmp_name'], $path . $data['file']['name']);
381
            ErrorHandler::stop(true);
382
            $csv_content = $this->getOccurencesFromCSV($real_media_path.$data['file']['name']);
383
            if ($csv_content) {
384
                $created = 0;
385
                foreach ($csv_content as $line) {
386
                    if ($line) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $line of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
387
                        $occurrence = $this->updateOccurrence(array(
388
                            'id' => '',
389
                            'instant_win_id' => $data['instant_win_id'],
390
                            'value' => $line[0],
391
                            'active' => $data['active'],
392
                            'winning' => ((bool) $line[1]) ? 1 : 0,
393
                            'prize_id' => $data['prize'],
394
                        ), null);
395
                        if ($occurrence) {
396
                            $created++;
397
                        }
398
                    }
399
                }
400
                // remove the csv file from folder
401
                unlink($real_media_path.$data['file']['name']);
402
                return $created;
403
            }
404
        }
405
        return false;
406
    }
407
408
    /**
409
     *
410
     *
411
     * @param  array                  $data
412
     * @return \PlaygroundGame\Entity\Game
413
     */
414
    public function updateOccurrence(array $data, $occurrence_id = null)
415
    {
416
        if (!$occurrence_id) {
417
            $occurrence  = new \PlaygroundGame\Entity\InstantWinOccurrence();
418
        } else {
419
            $occurrence = $this->getInstantWinOccurrenceMapper()->findById($occurrence_id);
420
        }
421
        $form  = $this->serviceLocator->get('playgroundgame_instantwinoccurrence_form');
422
        $form->bind($occurrence);
423
424
        $form->setData($data);
425
426
        $instantwin = $this->getGameMapper()->findById($data['instant_win_id']);
427
        $prize = null;
428
        if (isset($data['prize'])) {
429
            $prize = $this->getPrizeMapper()->findById($data['prize']);
430
        }
431
432
        if (!$form->isValid()) {
433
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by PlaygroundGame\Service\I...ntWin::updateOccurrence of type PlaygroundGame\Entity\Game.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

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

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
434
        }
435
436
        $occurrence->setInstantWin($instantwin);
437
        $occurrence->setPrize($prize);
438
        $occurrence->populate($data);
439
440
        if ($occurrence_id) {
441
            $this->getInstantWinOccurrenceMapper()->insert($occurrence);
442
        } else {
443
            $this->getInstantWinOccurrenceMapper()->update($occurrence);
444
        }
445
446
        return $occurrence;
447
    }
448
449
    /**
450
     * return true if the player has won. False otherwise.
451
     *
452
     * @param \PlaygroundGame\Entity\Game $game
453
     * @param \PlaygroundUser\Entity\UserInterface $user
454
     *
455
     * @return boolean
456
     */
457
    public function isInstantWinner($game, $user, $value = null)
458
    {
459
        $occurrenceMapper = $this->getInstantWinOccurrenceMapper();
460
461
        if ($game->getOccurrenceType()=='datetime') {
462
            $entry = $this->findLastActiveEntry($game, $user);
463
464
            // si date après date de gain et date de gain encore active alors desactive date de gain, et winner !
465
            $occurrence = $occurrenceMapper->checkDateOccurrenceByGameId($game);
466
        } elseif ($game->getOccurrenceType()=='code') {
467
            $occurrence = $occurrenceMapper->checkCodeOccurrenceByGameId($game, $value);
468
            if (!$occurrence) {
469
                return false;
470
            }
471
            $entry = $this->play($game, $user);
472
        }
473
474
        if (!$entry) {
0 ignored issues
show
Bug introduced by
The variable $entry does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
475
            return false;
476
        }
477
        return $this->setOccurrenceEntry($game, $user, $entry, $occurrence);
0 ignored issues
show
Bug introduced by
The variable $occurrence does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
478
    }
479
480
    /**
481
     * @param \PlaygroundGame\Entity\Game $game
482
     * @param \PlaygroundUser\Entity\UserInterface $user
483
     */
484
    public function setOccurrenceEntry($game, $user, $entry, $occurrence = null)
485
    {
486
        $entryMapper = $this->getEntryMapper();
487
        $occurrenceMapper = $this->getInstantWinOccurrenceMapper();
488
489
        $entry->setActive(0);
490
        if ($occurrence) {
491
            $occurrence->setEntry($entry);
492
            $occurrence->setUser($user);
493
            $occurrence->setActive(0);
494
            $occurrence = $occurrenceMapper->update($occurrence);
495
            if ($occurrence->getWinning()) {
496
                $entry->setWinner(true);
497
            } else {
498
                $entry->setPoints(0);
499
                $entry->setWinner(false);
500
            }
501
        } else {
502
            $entry->setPoints(0);
503
            $entry->setWinner(false);
504
        }
505
        $entry = $entryMapper->update($entry);
506
        $this->getEventManager()->trigger(
507
            'complete_instantwin.post',
508
            $this,
509
            array('user' => $user, 'game' => $game, 'entry' => $entry)
510
        );
511
512
        return $occurrence;
513
    }
514
515
    public function getEntriesHeader($game)
516
    {
517
        $header = parent::getEntriesHeader($game);
518
        $header['value'] = 1;
519
        $header['prize'] = 1;
520
521
        return $header;
522
    }
523
524
    /**
525
    * getGameEntries : All entries of a game
526
    *
527
    * @return Array of PlaygroundGame\Entity\Game
528
    */
529
    public function getGameEntries($header, $entries, $game)
530
    {
531
        $results = array();
532
533
        foreach ($entries as $k => $entry) {
534
            $entryData = json_decode($entry['playerData'], true);
535
            $winner = $entry['winner'];
536
537 View Code Duplication
            foreach ($header as $key => $v) {
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...
538
                if (isset($entryData[$key]) && $key !=='id') {
539
                    $results[$k][$key] = (is_array($entryData[$key]))?implode(', ', $entryData[$key]):$entryData[$key];
540
                } elseif (array_key_exists($key, $entry)) {
541
                    $results[$k][$key] = ($entry[$key] instanceof \DateTime)?
542
                        $entry[$key]->format('Y-m-d'):
543
                        $entry[$key];
544
                } else {
545
                    $results[$k][$key] = '';
546
                }
547
            }
548
            // If the occurrenceType is code, this will be triggered for every entry. To be improved.
549
            if ($game->getOccurrenceType() === 'code' || ($game->getOccurrenceType() === 'datetime' && $winner)) {
550
                $entry = $this->getEntryMapper()->findById($entry['id']);
551
                $occurrence = $this->getInstantWinOccurrenceMapper()->findByEntry($entry);
552
                $results[$k]['value'] = $occurrence->getValue();
553
                if ($occurrence->getPrize()) {
554
                    $results[$k]['prize'] = $occurrence->getPrize()->getTitle();
555
                }
556
            }
557
        }
558
559
        return $results;
560
    }
561
562
    public function getGameEntity()
563
    {
564
        return new \PlaygroundGame\Entity\InstantWin;
565
    }
566
567
    /**
568
     * getInstantWinOccurrenceMapper
569
     *
570
     * @return InstantWinOccurrenceMapperInterface
571
     */
572
    public function getInstantWinOccurrenceMapper()
573
    {
574
        if (null === $this->instantWinOccurrenceMapper) {
575
            $this->instantWinOccurrenceMapper = $this->serviceLocator->get(
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->serviceLocator->g...twinoccurrence_mapper') can also be of type array. However, the property $instantWinOccurrenceMapper is declared as type object<PlaygroundGame\Se...urrenceMapperInterface>. 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...
576
                'playgroundgame_instantwinoccurrence_mapper'
577
            );
578
        }
579
580
        return $this->instantWinOccurrenceMapper;
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->instantWinOccurrenceMapper; of type object|array adds the type array to the return on line 580 which is incompatible with the return type documented by PlaygroundGame\Service\I...tantWinOccurrenceMapper of type PlaygroundGame\Service\I...currenceMapperInterface.
Loading history...
581
    }
582
583
    /**
584
     * setInstantWinOccurrenceMapper
585
     *
586
     * @return InstantWin
587
     */
588
    public function setInstantWinOccurrenceMapper($instantWinOccurrenceMapper)
589
    {
590
        $this->instantWinOccurrenceMapper = $instantWinOccurrenceMapper;
591
592
        return $this;
593
    }
594
595
    /**
596
     * getPrizeMapper
597
     *
598
     * @return PrizeMapperInterface
599
     */
600 View Code Duplication
    public function getPrizeMapper()
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...
601
    {
602
        if (null === $this->prizeMapper) {
603
            $this->prizeMapper = $this->serviceLocator->get('playgroundgame_prize_mapper');
604
        }
605
606
        return $this->prizeMapper;
607
    }
608
609
    /**
610
     * setInstantWinOccurrenceMapper
611
     *
612
     * @param  PrizeMapperInterface $prizeMapper
613
     * @return InstantWin
614
     */
615
    public function setPrizeMapper($prizeMapper)
616
    {
617
        $this->prizeMapper = $prizeMapper;
618
619
        return $this;
620
    }
621
}
622