Completed
Push — develop ( f8b904...18781a )
by greg
02:53
created

InstantWin::getOccurrencesQuery()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 19
rs 9.6333
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace PlaygroundGame\Service;
4
5
use Zend\Stdlib\ErrorHandler;
6
use ZfcDatagrid\Column;
7
use ZfcDatagrid\Action;
8
use ZfcDatagrid\Column\Formatter;
9
use ZfcDatagrid\Column\Type;
10
use ZfcDatagrid\Column\Style;
11
use ZfcDatagrid\Filter;
12
use Doctrine\ORM\Query\Expr;
13
14
class InstantWin extends Game
15
{
16
    /**
17
     * @var InstantWinOccurrenceMapperInterface
18
     */
19
    protected $instantWinOccurrenceMapper;
20
21
    protected $prizeMapper;
22
23
    /**
24
     *
25
     * saving an instantwin image if any
26
     *
27
     * @param  array                  $data
28
     * @param  string                 $formClass
29
     * @return \PlaygroundGame\Entity\Game
30
     */
31 View Code Duplication
    public function createOrUpdate(array $data, $game, $formClass)
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...
32
    {
33
        $game = parent::createOrUpdate($data, $game, $formClass);
34
35
        if ($game) {
36
            $path = $this->getOptions()->getMediaPath() . DIRECTORY_SEPARATOR;
37
            $media_url = $this->getOptions()->getMediaUrl() . '/';
38
39
            if (!empty($data['uploadScratchcardImage']['tmp_name'])) {
40
                ErrorHandler::start();
41
                $data['uploadScratchcardImage']['name'] = $this->fileNewname(
42
                    $path,
43
                    $game->getId() . "-" . $data['uploadScratchcardImage']['name']
44
                );
45
                move_uploaded_file(
46
                    $data['uploadScratchcardImage']['tmp_name'],
47
                    $path . $data['uploadScratchcardImage']['name']
48
                );
49
                $game->setScratchcardImage($media_url . $data['uploadScratchcardImage']['name']);
50
                ErrorHandler::stop(true);
51
52
                $game = $this->getGameMapper()->update($game);
53
            }
54
55
            if (isset($data['deleteScratchcardImage']) &&
56
                $data['deleteScratchcardImage'] &&
57
                empty($data['uploadScratchcardImage']['tmp_name'])
58
            ) {
59
                ErrorHandler::start();
60
                $image = $game->getScratchcardImage();
61
                $image = str_replace($media_url, '', $image);
62
                unlink($path .$image);
63
                $game->setScratchcardImage(null);
64
                ErrorHandler::stop(true);
65
            }
66
67
            if ($game->getScheduleOccurrenceAuto()) {
68
                $this->scheduleOccurrences($game, $data);
69
            }
70
        }
71
72
        return $game;
73
    }
74
75
    /**
76
     * We can create Instant win occurrences dynamically
77
     *
78
     *
79
     * @param  array                  $data
80
     * @return boolean|null
81
     */
82
    public function scheduleOccurrences($game, array $data)
83
    {
84
        // It will be quite long to create these occurrences !
85
        set_time_limit(0);
86
        if ($game->getOccurrenceType() === 'code') {
87
            return $this->scheduleCodeOccurrences($game, $data);
88
        } elseif ($game->getOccurrenceType() === 'datetime') {
89
            return $this->scheduleDateOccurrences($game);
90
        }
91
    }
92
93
    public function getOccurrencesGrid($game = null)
94
    {
95
        $qb = $this->getOccurrencesQuery($game);
96
        $adminUrl = $this->serviceLocator->get('ControllerPluginManager')->get('adminUrl');
97
98
        /* @var $grid \ZfcDatagrid\Datagrid */
99
        $grid = $this->serviceLocator->get('ZfcDatagrid\Datagrid');
100
        $grid->setTitle('Occurrences');
101
        $grid->setDataSource($qb);
102
        $grid->setDefaultItemsPerPage(50);
103
104
        $col = new Column\Select('id', 'i');
105
        $col->setLabel('Id');
106
        $col->setIdentity(true);
107
        $grid->addColumn($col);
108
109
        $col = new Column\Select('value', 'i');
110
        $col->setLabel('Value');
111
        $grid->addColumn($col);
112
113
        $col = new Column\Select('email', 'u');
114
        $col->setLabel('Email');
115
        $grid->addColumn($col);
116
117
        $col = new Column\Select('title', 'p');
118
        $col->setLabel('Prize');
119
        $grid->addColumn($col);
120
121
        $col = new Column\Select('winning', 'i');
122
        $col->setLabel('Status');
123
        $col->setReplaceValues(
124
            [
125
                0 => 'not winning',
126
                1 => 'winning',
127
            ]
128
        );
129
        $grid->addColumn($col);
130
131
        $actions = new Column\Action();
132
        $actions->setLabel('');
133
134
        $viewAction = new Column\Action\Button();
135
        $viewAction->setLabel('Edit');
136
        $rowId = $viewAction->getRowIdPlaceholder();
137
        $viewAction->setLink($adminUrl->fromRoute('playgroundgame/instantwin-occurrence-edit', array('gameId' => $game->getId(), 'occurrenceId' => $rowId)));
138
        $actions->addAction($viewAction);
139
140
        $viewAction = new Column\Action\Button();
141
        $viewAction->setLabel('Delete');
142
        $rowId = $viewAction->getRowIdPlaceholder();
143
        $viewAction->setLink($adminUrl->fromRoute('playgroundgame/instantwin-occurrence-remove', array('occurrenceId' => $rowId)));
144
        $actions->addAction($viewAction);
145
146
        $grid->addColumn($actions);
147
148
        return $grid;
149
    }
150
151
    public function getOccurrencesQuery($game)
152
    {
153
        $em = $this->serviceLocator->get('doctrine.entitymanager.orm_default');
154
155
        $qb = $em->createQueryBuilder();
156
        $selectString = 'i, e, u, p, g';
157
        $qb->select($selectString)
158
            ->from('PlaygroundGame\Entity\InstantWinOccurrence', 'i')
159
            ->leftJoin('i.entry', 'e')
160
            ->leftJoin('i.prize', 'p')
161
            ->innerJoin('i.instantwin', 'g')
162
            ->leftJoin('i.user', 'u')
163
            ->where($qb->expr()->eq('i.instantwin', ':game'))
164
            ->orderBy('i.id');
165
166
        $qb->setParameter('game', $game);
167
168
        return $qb;
169
    }
170
171
    public function scheduleCodeOccurrences($game, $data)
172
    {
173
        $available_characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-';
174
        $last_character_index = strlen($available_characters)-1;
175
        if (!$game->getWinningOccurrenceNumber()) {
176
            $game->setWinningOccurrenceNumber($game->getOccurrenceNumber());
177
        }
178
        if (empty($data['occurrenceValueSize'])) {
179
            $data['occurrenceValueSize'] = 8;
180
        }
181
        $created = 0;
182
        $numOccurrences = $game->getOccurrenceNumber();
183
        
184
        for ($i=0; $i < $numOccurrences; $i++) {
185
            $code = '';
186
            while (strlen($code)<$data['occurrenceValueSize']) {
187
                $code .= $available_characters[rand(0, $last_character_index)];
188
            }
189
            $occurrence = new \PlaygroundGame\Entity\InstantWinOccurrence();
190
            $occurrence->setInstantwin($game);
191
            $occurrence->setValue($code);
192
            $occurrence->setActive(1);
193
            $occurrence->setWinning($created < $game->getWinningOccurrenceNumber());
194
            if ($this->getInstantWinOccurrenceMapper()->insert($occurrence)) {
195
                $created++;
196
            }
197
        }
198
        return true;
199
    }
200
201
    public function createRandomOccurrences($game, $beginning, $end, $quantity)
202
    {
203
        $prizes = $game->getPrizes();
204
        $randomPrizes = [];
205
        $insertPrize = false;
206
        $exactCount = false;
207
        foreach ($prizes as $prize) {
208
            $qty = $prize->getQty();
209
            if ($qty > 0) {
210
                for ($i = 0; $i < $qty; $i++) {
211
                    $randomPrizes[] = $prize;
212
                }
213
            }
214
        }
215
        $min = 0;
216
        $max = count($randomPrizes);
217
        if ($max > $min) {
218
            $insertPrize = true;
219
            if ($quantity === $max) {
220
                $exactCount = true;
221
            }
222
        }
223
224
        for ($i=1; $i<=$quantity; $i++) {
225
            $randomDate = $this->getRandomDate($beginning->format('U'), $end->format('U'));
226
            $randomDate = \DateTime::createFromFormat('Y-m-d H:i:s', $randomDate);
227
            $occurrence  = new \PlaygroundGame\Entity\InstantWinOccurrence();
228
            $occurrence->setInstantwin($game);
229
            $occurrence->setValue($randomDate->format('Y-m-d H:i:s'));
230
            $occurrence->setActive(1);
231
            if ($insertPrize) {
232
                $toPick = rand($min, $max - 1);
233
                $occurrence->setPrize($randomPrizes[$toPick]);
234
                if ($exactCount) {
235
                    array_splice($randomPrizes, $toPick, 1);
236
                    --$max;
237
                }
238
            }
239
240
            $this->getInstantWinOccurrenceMapper()->insert($occurrence);
241
        }
242
    }
243
244
    /**
245
     * Get the number of occurrences to create for the instantwin
246
     */
247
    public function getOccurrenceNumber($game)
248
    {
249
        $nb = 0;
250
        if ($game->getOccurrenceNumber() > 0) {
251
            $nb = $game->getOccurrenceNumber();
252
        } else {
253
            $prizes = $game->getPrizes();
254
            foreach ($prizes as $prize) {
255
                $nb += $prize->getQty();
256
            }
257
        }
258
259
        return $nb;
260
    }
261
262
    public function scheduleDateOccurrences($game)
263
    {
264
        $f = $game->getOccurrenceDrawFrequency();
265
        $today    = new \DateTime("now");
266
        $end      = new \DateTime("now");
267
        $interval = 'P10D';
268
        if ($game->getStartDate() && $game->getStartDate() > $today) {
269
            $beginning = $game->getStartDate();
270
        } else {
271
            $beginning = $today;
272
        }
273
274
        if ($game->getEndDate()) {
275
            $end = $game->getEndDate();
276
        } else {
277
            $end->add(new \DateInterval($interval));
278
        }
279
280
        // Summertimes timezone management
281
        $timezone = $today->getTimezone();
282
        $transitions = $timezone->getTransitions($beginning->getTimestamp(), $end->getTimestamp());
283
284
        // There is a time transition between these datetimes()
285
        if (count($transitions) == 2) {
286
            $shift = $transitions[0]['offset'] - $transitions[1]['offset'];
287
            if ($shift > 0) {
288
                $end->sub(new \DateInterval('PT'.abs($shift).'S'));
289
            } else {
290
                $end->add(new \DateInterval('PT'.abs($shift).'S'));
291
            }
292
        }
293
294
        // DateInterval takes the day @ 00:00 to calculate the difference between the dates, so 1 day is always missing
295
        // as we consider the last day @ 23:59:59 in Playground :)
296
        if ($end->format('His') == 0) {
297
            $end->add(new \DateInterval('P1D'));
298
        }
299
300
        $dateInterval = (int)(($end->getTimestamp() - $beginning->getTimestamp())/60);
301
302
        // Je recherche tous les IG non gagnés
303
        $occurrences = $this->getInstantWinOccurrenceMapper()->findBy(array('instantwin' => $game));
304
        $nbExistingOccurrences = count($occurrences);
305
        $nbOccurencesToCreate = 0;
306
307
        switch ($f) {
308
            case null:
309
            case 'game':
310
                $nbOccurencesToCreate = $this->getOccurrenceNumber($game) - $nbExistingOccurrences;
311
                if ($nbOccurencesToCreate > 0) {
312
                    $this->createRandomOccurrences($game, $beginning, $end, $nbOccurencesToCreate);
313
                }
314
315
                break;
316 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...
317
                $nbInterval = (int) ($dateInterval/60);
318
319
                // If a hour don't last 60min, I consider it as a hour anyway.
320
                if ($dateInterval%60 > 0) {
321
                    ++$nbInterval;
322
                }
323
                if ($nbInterval > 0) {
324
                    $nbOccurencesToCreate = $game->getOccurrenceNumber() - floor($nbExistingOccurrences/$nbInterval);
325
                }
326
327
                $beginningDrawDate = \DateTime::createFromFormat('m/d/Y H:i:s', $beginning->format('m/d/Y H:i:s'));
328
                $endDrawDate = \DateTime::createFromFormat('m/d/Y H:i:s', $beginning->format('m/d/Y H'). ':59:59');
329
                
330
                if ($nbOccurencesToCreate > 0) {
331
                    for ($d=1; $d<=$nbInterval; $d++) {
332
                        $this->createRandomOccurrences(
333
                            $game,
334
                            $beginningDrawDate,
335
                            $endDrawDate,
336
                            $nbOccurencesToCreate
337
                        );
338
                        $beginningDrawDate = \DateTime::createFromFormat(
339
                            'm/d/Y H:i:s',
340
                            $beginningDrawDate->format('m/d/Y H'). ':00:00'
341
                        );
342
                        $beginningDrawDate->add(new \DateInterval('PT1H'));
343
                        $endDrawDate->add(new \DateInterval('PT1H'));
344
                    }
345
                }
346
347
                break;
348 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...
349
                $nbInterval = (int) ($dateInterval/(60*24));
350
351
                // Prise en compte des changements d'horaires
352
                // If a day don't last 24h, I consider it as a day anyway
353
354
                if ($dateInterval%(60*24) > 0) {
355
                    ++$nbInterval;
356
                }
357
358
                if ($nbInterval > 0) {
359
                    $nbOccurencesToCreate = $game->getOccurrenceNumber() - floor($nbExistingOccurrences/$nbInterval);
360
                }
361
362
                $beginningDrawDate = \DateTime::createFromFormat('m/d/Y H:i:s', $beginning->format('m/d/Y H:i:s'));
363
                $endDrawDate = \DateTime::createFromFormat('m/d/Y H:i:s', $beginning->format('m/d/Y'). ' 23:59:59');
364
                
365
                if ($nbOccurencesToCreate > 0) {
366
                    for ($d=1; $d<=$nbInterval; $d++) {
367
                        $this->createRandomOccurrences(
368
                            $game,
369
                            $beginningDrawDate,
370
                            $endDrawDate,
371
                            $nbOccurencesToCreate
372
                        );
373
                        // As the first beginning date was not @ midnight,
374
                        // I recreate the beginning date
375
                        $beginningDrawDate = \DateTime::createFromFormat(
376
                            'm/d/Y H:i:s',
377
                            $beginningDrawDate->format('m/d/Y'). ' 00:00:00'
378
                        );
379
                        $beginningDrawDate->add(new \DateInterval('P1D'));
380
                        $endDrawDate->add(new \DateInterval('P1D'));
381
                    }
382
                }
383
384
                break;
385 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...
386
                $nbOccurencesToCreate = $game->getOccurrenceNumber() - $nbExistingOccurrences;
387
                $nbWeeksInterval = (int) ($dateInterval/(60*24*7));
388
                // If a week don't last 7d, I consider it as a week anyway.
389
                if ($dateInterval%(60*24*7) > 0) {
390
                    ++$nbWeeksInterval;
391
                }
392
                $beginningDrawDate = \DateTime::createFromFormat(
393
                    'm/d/Y H:i:s',
394
                    $beginning->format('m/d/Y'). ' 00:00:00'
395
                );
396
                $endDrawDate = \DateTime::createFromFormat(
397
                    'm/d/Y H:i:s',
398
                    $beginning->format('m/d/Y'). ' 23:59:59'
399
                );
400
                $endDrawDate->add(new \DateInterval('P6D'));
401
                if ($endDrawDate > $end) {
402
                    $endDrawDate = $end;
403
                }
404
405
                if ($nbOccurencesToCreate > 0) {
406
                    for ($d=1; $d<=$nbWeeksInterval; $d++) {
407
                        $this->createRandomOccurrences(
408
                            $game,
409
                            $beginningDrawDate,
410
                            $endDrawDate,
411
                            $nbOccurencesToCreate
412
                        );
413
                        $beginningDrawDate->add(new \DateInterval('P1W'));
414
                        $endDrawDate->add(new \DateInterval('P1W'));
415
                        if ($endDrawDate > $end) {
416
                            $endDrawDate = $end;
417
                        }
418
                    }
419
                }
420
421
                break;
422 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...
423
                $nbOccurencesToCreate = $game->getOccurrenceNumber() - $nbExistingOccurrences;
424
                $nbMonthsInterval = (int) ($dateInterval/(60*24*30));
425
                // If a week don't last 30d, I consider it as a month anyway.
426
                if ($dateInterval%(60*24*30) > 0) {
427
                    ++$nbMonthsInterval;
428
                }
429
                $beginningDrawDate = \DateTime::createFromFormat(
430
                    'm/d/Y H:i:s',
431
                    $beginning->format('m/d/Y'). ' 00:00:00'
432
                );
433
                $endDrawDate = \DateTime::createFromFormat('m/d/Y H:i:s', $beginning->format('m/d/Y'). ' 23:59:59');
434
                $endDrawDate->add(new \DateInterval('P1M'));
435
                $endDrawDate->sub(new \DateInterval('P1D'));
436
                if ($endDrawDate > $end) {
437
                    $endDrawDate = $end;
438
                }
439
440
                if ($nbOccurencesToCreate > 0) {
441
                    for ($d=1; $d<=$nbMonthsInterval; $d++) {
442
                        $this->createRandomOccurrences(
443
                            $game,
444
                            $beginningDrawDate,
445
                            $endDrawDate,
446
                            $nbOccurencesToCreate
447
                        );
448
                        $beginningDrawDate->add(new \DateInterval('P1M'));
449
                        $endDrawDate->add(new \DateInterval('P1M'));
450
                        if ($endDrawDate > $end) {
451
                            $endDrawDate = $end;
452
                        }
453
                    }
454
                }
455
456
                break;
457
        }
458
459
        return true;
460
    }
461
462
    public function getRandomDate($min_date, $max_date)
463
    {
464
        $rand_epoch = rand($min_date, $max_date);
465
466
        return date('Y-m-d H:i:s', $rand_epoch);
467
    }
468
469
    /**
470
     * @param string $fileName
471
     */
472
    public function getOccurencesFromCSV($fileName)
473
    {
474
        if (file_exists($fileName)) {
475
            $csvFile = fopen($fileName, 'r');
476
            if ($csvFile) {
477
                while (!feof($csvFile)) {
478
                    $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...
479
                }
480
                fclose($csvFile);
481
                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...
482
            }
483
        }
484
        return false;
485
    }
486
487
    public function setOccurencesToCSV($game)
488
    {
489
        $path = $this->getOptions()->getMediaPath() . DIRECTORY_SEPARATOR;
490
        $fileName = $path.'occurences-'.$game->getId().'.csv';
491
        $csvFile = fopen($fileName, 'w');
492
        if ($csvFile) {
493
            $occurrences = $this->getInstantWinOccurrenceMapper()->findByGameId($game);
494
            foreach ($occurrences as $occurrence) {
495
                fputcsv($csvFile, array($occurrence->getValue(), $occurrence->getWinning()));
496
            }
497
            fclose($csvFile);
498
            return $fileName;
499
        }
500
        return false;
501
    }
502
503
    public function importOccurrences($data)
504
    {
505
        if (!empty($data['file']['tmp_name'])) {
506
            $path = $this->getOptions()->getMediaPath() . DIRECTORY_SEPARATOR;
507
            $real_media_path = realpath($path) . DIRECTORY_SEPARATOR;
508
509
            // upload the csv file
510
            ErrorHandler::start();
511
            $data['file']['name'] = $this->fileNewname($path, $data['instant_win_id'] . "-" . $data['file']['name']);
512
            move_uploaded_file($data['file']['tmp_name'], $path . $data['file']['name']);
513
            ErrorHandler::stop(true);
514
            $csv_content = $this->getOccurencesFromCSV($real_media_path.$data['file']['name']);
515
            if ($csv_content) {
516
                $created = 0;
517
                foreach ($csv_content as $line) {
518
                    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...
519
                        $occurrence = $this->updateOccurrence(array(
520
                            'id' => '',
521
                            'instant_win_id' => $data['instant_win_id'],
522
                            'value' => $line[0],
523
                            'active' => $data['active'],
524
                            'winning' => ((bool) $line[1]) ? 1 : 0,
525
                            'prize_id' => $data['prize'],
526
                        ), null);
527
                        if ($occurrence) {
528
                            $created++;
529
                        }
530
                    }
531
                }
532
                // remove the csv file from folder
533
                unlink($real_media_path.$data['file']['name']);
534
                return $created;
535
            }
536
        }
537
        return false;
538
    }
539
540
    /**
541
     *
542
     *
543
     * @param  array                  $data
544
     * @return \PlaygroundGame\Entity\Game
545
     */
546
    public function updateOccurrence(array $data, $occurrence_id = null)
547
    {
548
        if (!$occurrence_id) {
549
            $occurrence  = new \PlaygroundGame\Entity\InstantWinOccurrence();
550
        } else {
551
            $occurrence = $this->getInstantWinOccurrenceMapper()->findById($occurrence_id);
552
        }
553
        $form  = $this->serviceLocator->get('playgroundgame_instantwinoccurrence_form');
554
        $form->bind($occurrence);
555
556
        $form->setData($data);
557
558
        $instantwin = $this->getGameMapper()->findById($data['instant_win_id']);
559
        $prize = null;
560
        if (isset($data['prize'])) {
561
            $prize = $this->getPrizeMapper()->findById($data['prize']);
562
        }
563
564
        if (!$form->isValid()) {
565
            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...
566
        }
567
568
        $occurrence->setInstantWin($instantwin);
569
        $occurrence->setPrize($prize);
570
        $occurrence->populate($data);
571
572
        if ($occurrence_id) {
573
            $this->getInstantWinOccurrenceMapper()->insert($occurrence);
574
        } else {
575
            $this->getInstantWinOccurrenceMapper()->update($occurrence);
576
        }
577
578
        return $occurrence;
579
    }
580
581
    /**
582
     * return true if the player has won. False otherwise.
583
     *
584
     * @param \PlaygroundGame\Entity\Game $game
585
     * @param \PlaygroundUser\Entity\UserInterface $user
586
     *
587
     * @return boolean
588
     */
589
    public function isInstantWinner($game, $user, $value = null)
590
    {
591
        $occurrenceMapper = $this->getInstantWinOccurrenceMapper();
592
593
        if ($game->getOccurrenceType()=='datetime') {
594
            $entry = $this->findLastActiveEntry($game, $user);
595
596
            // si date après date de gain et date de gain encore active alors desactive date de gain, et winner !
597
            $occurrence = $occurrenceMapper->checkDateOccurrenceByGameId($game);
598
        } elseif ($game->getOccurrenceType()=='code') {
599
            $occurrence = $occurrenceMapper->checkCodeOccurrenceByGameId($game, $value);
600
            if (!$occurrence) {
601
                return false;
602
            }
603
            $entry = $this->play($game, $user);
604
        }
605
606
        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...
607
            return false;
608
        }
609
        $this->getEventManager()->trigger(
610
            __FUNCTION__ . '.pre',
611
            $this,
612
            array('user' => $user, 'game' => $game, 'entry' => $entry)
613
        );
614
        $occurrence = $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...
615
        $this->getEventManager()->trigger(
616
            __FUNCTION__ . '.post',
617
            $this,
618
            array('user' => $user, 'game' => $game, 'entry' => $entry, 'occurrence' => $occurrence)
619
        );
620
        return $occurrence;
621
    }
622
623
    /**
624
     * @param \PlaygroundGame\Entity\Game $game
625
     * @param \PlaygroundUser\Entity\UserInterface $user
626
     */
627
    public function setOccurrenceEntry($game, $user, $entry, $occurrence = null)
0 ignored issues
show
Unused Code introduced by
The parameter $game is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
628
    {
629
        $entryMapper = $this->getEntryMapper();
630
        $occurrenceMapper = $this->getInstantWinOccurrenceMapper();
631
632
        $entry->setActive(0);
633
        $entry->setWinner(false);
634
        $entry->setPoints(0);
635
        if ($occurrence) {
636
            $occurrence->setEntry($entry);
637
            $occurrence->setUser($user);
638
            $occurrence->setActive(0);
639
            $occurrence = $occurrenceMapper->update($occurrence);
640
            if ($occurrence->getWinning()) {
641
                $entry->setWinner(true);
642
            }
643
            if ($occurrence->getPrize()) {
644
                $entry->setPoints($occurrence->getPrize()->getPoints());
645
            }
646
        }
647
        $entry = $entryMapper->update($entry);
0 ignored issues
show
Unused Code introduced by
$entry 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...
648
649
        return $occurrence;
650
    }
651
652
    /**
653
     * DEPRECATED
654
     */
655
    public function getEntriesHeader($game)
656
    {
657
        $header = parent::getEntriesHeader($game);
658
        $header['value'] = 1;
659
        $header['prize'] = 1;
660
661
        return $header;
662
    }
663
664
    /**
665
     * DEPRECATED
666
     * getGameEntries : All entries of a game
667
     *
668
     * @return Array of PlaygroundGame\Entity\Game
669
     */
670
    public function getGameEntries($header, $entries, $game)
671
    {
672
        $results = array();
673
674
        foreach ($entries as $k => $entry) {
675
            $entryData = json_decode($entry['playerData'], true);
676
            $winner = $entry['winner'];
677
678 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...
679
                if (isset($entryData[$key]) && $key !=='id') {
680
                    $results[$k][$key] = (is_array($entryData[$key]))?implode(', ', $entryData[$key]):$entryData[$key];
681
                } elseif (array_key_exists($key, $entry)) {
682
                    $results[$k][$key] = ($entry[$key] instanceof \DateTime)?
683
                        $entry[$key]->format('Y-m-d'):
684
                        $entry[$key];
685
                } else {
686
                    $results[$k][$key] = '';
687
                }
688
            }
689
            // If the occurrenceType is code, this will be triggered for every entry. To be improved.
690
            if ($game->getOccurrenceType() === 'code' || ($game->getOccurrenceType() === 'datetime' && $winner)) {
691
                $entry = $this->getEntryMapper()->findById($entry['id']);
692
                $occurrence = $this->getInstantWinOccurrenceMapper()->findByEntry($entry);
693
                if ($occurrence !== null) {
694
                    $results[$k]['value'] = $occurrence->getValue();
695
                    if ($occurrence->getPrize()) {
696
                        $results[$k]['prize'] = $occurrence->getPrize()->getTitle();
697
                    }
698
                }
699
            }
700
        }
701
702
        return $results;
703
    }
704
705
    public function getGameEntity()
706
    {
707
        return new \PlaygroundGame\Entity\InstantWin;
708
    }
709
710
    /**
711
     * getInstantWinOccurrenceMapper
712
     *
713
     * @return InstantWinOccurrenceMapperInterface
714
     */
715
    public function getInstantWinOccurrenceMapper()
716
    {
717
        if (null === $this->instantWinOccurrenceMapper) {
718
            $this->instantWinOccurrenceMapper = $this->serviceLocator->get(
719
                'playgroundgame_instantwinoccurrence_mapper'
720
            );
721
        }
722
723
        return $this->instantWinOccurrenceMapper;
724
    }
725
726
    /**
727
     * setInstantWinOccurrenceMapper
728
     *
729
     * @return InstantWin
730
     */
731
    public function setInstantWinOccurrenceMapper($instantWinOccurrenceMapper)
732
    {
733
        $this->instantWinOccurrenceMapper = $instantWinOccurrenceMapper;
734
735
        return $this;
736
    }
737
738
    /**
739
     * getPrizeMapper
740
     *
741
     * @return PrizeMapperInterface
742
     */
743 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...
744
    {
745
        if (null === $this->prizeMapper) {
746
            $this->prizeMapper = $this->serviceLocator->get('playgroundgame_prize_mapper');
747
        }
748
749
        return $this->prizeMapper;
750
    }
751
752
    /**
753
     * setInstantWinOccurrenceMapper
754
     *
755
     * @param  PrizeMapperInterface $prizeMapper
756
     * @return InstantWin
757
     */
758
    public function setPrizeMapper($prizeMapper)
759
    {
760
        $this->prizeMapper = $prizeMapper;
761
762
        return $this;
763
    }
764
}
765