Completed
Push — develop ( 894c58...40c6b6 )
by greg
02:56
created

Game   F

Complexity

Total Complexity 323

Size/Duplication

Total Lines 2295
Duplicated Lines 23.01 %

Coupling/Cohesion

Components 1
Dependencies 27

Importance

Changes 0
Metric Value
wmc 323
lcom 1
cbo 27
dl 528
loc 2295
rs 0.8
c 0
b 0
f 0

69 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A getEventManager() 7 7 2
A getGameUserPath() 14 14 3
A getGameUserMediaUrl() 7 7 1
F createOrUpdate() 121 273 55
B getNextGames() 11 65 9
B getActiveGames() 11 64 7
A getAvailableGames() 0 21 1
A getEntriesQuery() 36 37 1
B getEntriesHeader() 7 50 7
B getGameEntries() 11 23 7
A getActiveSliderGames() 11 32 4
A getPrizeCategoryGames() 12 12 1
A getGameIdentifierFromFacebook() 0 11 3
B checkGame() 0 53 9
A checkExistingEntry() 0 25 5
B updateEntryPlayerForm() 0 40 9
A checkIsFan() 0 18 3
A getAnonymousIdentifier() 0 14 4
B play() 0 43 5
A hasReachedPlayLimit() 0 15 3
B payToPlay() 0 32 6
B findLastEntries() 8 23 7
B getLimitDate() 19 35 6
A findLastActiveEntry() 0 4 1
A findLastInactiveEntry() 0 4 1
A findLastEntry() 0 4 1
B inviteToTeam() 0 63 6
C sendShareMail() 0 79 11
A sendResultMail() 0 29 3
A sendGameMail() 0 23 1
A postFbWall() 24 24 2
A postFbRequest() 0 23 2
A postTwitter() 24 24 2
A postGoogle() 24 24 2
B allowBonus() 0 20 6
A addAnotherEntry() 0 14 1
A addAnotherChance() 0 10 2
A playAgain() 0 13 3
C uploadFile() 0 76 11
A fileNewname() 0 19 3
B getQueryGamesOrderBy() 0 48 5
A draw() 0 22 2
A getGameMapper() 8 8 2
A setGameMapper() 0 6 1
A getEntryMapper() 0 8 2
A setEntryMapper() 0 6 1
A setOptions() 0 6 1
A getOptions() 0 9 2
A getExtension() 0 9 1
A getSrc() 0 20 5
A resize() 0 33 2
A getGameEntity() 0 4 1
A isAllowed() 0 6 1
B getIp() 0 21 7
A getGeoloc() 0 14 3
A getAnonymousId() 0 9 3
A createForm() 30 30 5
A getCSV() 0 11 2
F getAttributes() 0 40 16
B decorate() 0 63 6
F createFormFromJson() 131 184 14
C sendMail() 12 22 15
A getPlayerFormMapper() 0 8 2
A setPlayerFormMapper() 0 6 1
A getInvitationMapper() 0 8 2
A setInvitationMapper() 0 6 1
A getUserMapper() 0 8 2
A getServiceManager() 0 4 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

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

Common duplication problems, and corresponding solutions are:

Complex Class

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

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

1
<?php
2
namespace PlaygroundGame\Service;
3
4
use PlaygroundGame\Entity\Entry;
5
use Zend\Session\Container;
6
use Zend\ServiceManager\ServiceManager;
7
use Zend\EventManager\EventManagerAwareTrait;
8
use Zend\EventManager\EventManager;
9
use PlaygroundGame\Options\ModuleOptions;
10
use PlaygroundGame\Mapper\GameInterface as GameMapperInterface;
11
use DoctrineModule\Validator\NoObjectExists as NoObjectExistsValidator;
12
use Zend\Validator\File\Size;
13
use Zend\Validator\File\IsImage;
14
use Zend\Stdlib\ErrorHandler;
15
use PlaygroundCore\Filter\Sanitize;
16
use Zend\Form\Element;
17
use Zend\Form\Form;
18
use Zend\InputFilter\Factory as InputFactory;
19
use Zend\ServiceManager\ServiceLocatorInterface;
20
21
class Game
22
{
23
    use EventManagerAwareTrait;
24
25
    /**
26
     *
27
     * @var GameMapperInterface
28
     */
29
    protected $gameMapper;
30
31
    /**
32
     *
33
     * @var EntryMapperInterface
34
     */
35
    protected $entryMapper;
36
37
    /**
38
     *
39
     * @var UserServiceOptionsInterface
40
     */
41
    protected $options;
42
43
    protected $playerformMapper;
44
45
    protected $invitationMapper;
46
47
    protected $userMapper;
48
    
49
    protected $anonymousIdentifier = null;
50
51
    /**
52
     *
53
     * @var ServiceManager
54
     */
55
    protected $serviceLocator;
56
57
    protected $event;
58
59
    public function __construct(ServiceLocatorInterface $locator)
60
    {
61
        $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...
62
    }
63
64 View Code Duplication
    public function getEventManager() {
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...
65
        if (null === $this->event) {
66
            $this->event = new EventManager($this->serviceLocator->get('SharedEventManager'), [get_class($this)]);
67
        }
68
69
        return $this->event;
70
    }
71
72 View Code Duplication
    public function getGameUserPath($game, $user)
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...
73
    {
74
        $path = $this->getOptions()->getMediaPath() . DIRECTORY_SEPARATOR;
75
        $path .= 'game' . $game->getId() . DIRECTORY_SEPARATOR;
76
        if (!is_dir($path)) {
77
            mkdir($path, 0777, true);
78
        }
79
        $path .= 'user'. $user->getId() . DIRECTORY_SEPARATOR;
80
        if (!is_dir($path)) {
81
            mkdir($path, 0777, true);
82
        }
83
84
        return $path;
85
    }
86
87 View Code Duplication
    public function getGameUserMediaUrl($game, $user)
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...
88
    {
89
        $media_url = $this->getOptions()->getMediaUrl() . '/';
90
        $media_url .= 'game' . $game->getId() . '/' . 'user'. $user->getId() . '/';
91
92
        return $media_url;
93
    }
94
95
    /**
96
     *
97
     * This service is ready for all types of games
98
     *
99
     * @param array $data
100
     * @param string $formClass
101
     * @return \PlaygroundGame\Entity\Game
102
     */
103
    public function createOrUpdate(array $data, $game, $formClass)
104
    {
105
        $entityManager = $this->serviceLocator->get('doctrine.entitymanager.orm_default');
106
107
        $form = $this->serviceLocator->get($formClass);
108
        $form->get('publicationDate')->setOptions(array(
109
            'format' => 'Y-m-d H:i:s'
110
        ));
111
        $form->get('startDate')->setOptions(array(
112
            'format' => 'Y-m-d H:i:s'
113
        ));
114
        $form->get('endDate')->setOptions(array(
115
            'format' => 'Y-m-d H:i:s'
116
        ));
117
        $form->get('closeDate')->setOptions(array(
118
            'format' => 'Y-m-d H:i:s'
119
        ));
120
121
        $form->bind($game);
122
123
        $path = $this->getOptions()->getMediaPath() . '/';
124
        if (!is_dir($path)) {
125
            mkdir($path, 0777, true);
126
        }
127
        $media_url = $this->getOptions()->getMediaUrl() . '/';
128
129
        $identifierInput = $form->getInputFilter()->get('identifier');
130
        $noObjectExistsValidator = new NoObjectExistsValidator(array(
131
            'object_repository' => $entityManager->getRepository('PlaygroundGame\Entity\Game'),
132
            'fields' => 'identifier',
133
            'messages' => array(
134
                'objectFound' => 'This url already exists !'
135
            )
136
        ));
137
138
        if ($game->getIdentifier() != $data['identifier']) {
139
            $identifierInput->getValidatorChain()->addValidator($noObjectExistsValidator);
140
        }
141
142
        // I must switch from original format to the Y-m-d format because
143
        // this is the only one accepted by new DateTime($value)
144 View Code Duplication
        if (isset($data['publicationDate']) && $data['publicationDate']) {
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...
145
            $tmpDate = \DateTime::createFromFormat('d/m/Y H:i:s', $data['publicationDate']);
146
            $data['publicationDate'] = $tmpDate->format('Y-m-d H:i:s');
147
        }
148 View Code Duplication
        if (isset($data['startDate']) && $data['startDate']) {
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...
149
            $tmpDate = \DateTime::createFromFormat('d/m/Y H:i:s', $data['startDate']);
150
            $data['startDate'] = $tmpDate->format('Y-m-d H:i:s');
151
        }
152 View Code Duplication
        if (isset($data['endDate']) && $data['endDate']) {
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...
153
            $tmpDate = \DateTime::createFromFormat('d/m/Y H:i:s', $data['endDate']);
154
            $data['endDate'] = $tmpDate->format('Y-m-d H:i:s');
155
        }
156 View Code Duplication
        if (isset($data['closeDate']) && $data['closeDate']) {
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...
157
            $tmpDate = \DateTime::createFromFormat('d/m/Y H:i:s', $data['closeDate']);
158
            $data['closeDate'] = $tmpDate->format('Y-m-d H:i:s');
159
        }
160
161
        // If publicationDate is null, I update it with the startDate if not null neither
162
        if ((! isset($data['publicationDate']) || $data['publicationDate'] == '') &&
163
            (isset($data['startDate']) && $data['startDate'] != '')
164
        ) {
165
            $data['publicationDate'] = $data['startDate'];
166
        }
167
168
        // If the identifier has not been set, I use the title to create one.
169 View Code Duplication
        if ((! isset($data['identifier']) || empty($data['identifier'])) && isset($data['title'])) {
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...
170
            $data['identifier'] = $data['title'];
171
        }
172
173
        $form->setData($data);
174
175
        // If someone want to claim... It's time to do it ! used for exemple by PlaygroundFacebook Module
176
        $result = $this->getEventManager()->trigger(__FUNCTION__ . '.validate', $this, array(
177
            'game' => $game,
178
            'data' => $data
179
        ));
180
        if (is_array($result) && ! $result[0]) {
181
            $form->get('fbAppId')->setMessages(array(
182
                'Vous devez d\'abord désinstaller l\'appli Facebook'
183
            ));
184
185
            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\Game::createOrUpdate 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...
186
        }
187
188
        if (! $form->isValid()) {
189 View Code Duplication
            if (isset($data['publicationDate']) && $data['publicationDate']) {
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...
190
                $tmpDate = \DateTime::createFromFormat('Y-m-d H:i:s', $data['publicationDate']);
191
                $data['publicationDate'] = $tmpDate->format('d/m/Y H:i:s');
192
                $form->setData(array(
193
                    'publicationDate' => $data['publicationDate']
194
                ));
195
            }
196 View Code Duplication
            if (isset($data['startDate']) && $data['startDate']) {
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...
197
                $tmpDate = \DateTime::createFromFormat('Y-m-d H:i:s', $data['startDate']);
198
                $data['startDate'] = $tmpDate->format('d/m/Y H:i:s');
199
                $form->setData(array(
200
                    'startDate' => $data['startDate']
201
                ));
202
            }
203 View Code Duplication
            if (isset($data['endDate']) && $data['endDate']) {
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...
204
                $tmpDate = \DateTime::createFromFormat('Y-m-d H:i:s', $data['endDate']);
205
                $data['endDate'] = $tmpDate->format('d/m/Y H:i:s');
206
                $form->setData(array(
207
                    'endDate' => $data['endDate']
208
                ));
209
            }
210 View Code Duplication
            if (isset($data['closeDate']) && $data['closeDate']) {
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...
211
                $tmpDate = \DateTime::createFromFormat('Y-m-d H:i:s', $data['closeDate']);
212
                $data['closeDate'] = $tmpDate->format('d/m/Y H:i:s');
213
                $form->setData(array(
214
                    'closeDate' => $data['closeDate']
215
                ));
216
            }
217
            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\Game::createOrUpdate 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...
218
        }
219
220
        $game = $form->getData();
221
        $game = $this->getGameMapper()->insert($game);
222
223
        // I wait for the game to be saved to obtain its ID.
224 View Code Duplication
        if (! empty($data['uploadMainImage']['tmp_name'])) {
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...
225
            ErrorHandler::start();
226
            $data['uploadMainImage']['name'] = $this->fileNewname(
227
                $path,
228
                $game->getId() . "-" . $data['uploadMainImage']['name']
229
            );
230
            move_uploaded_file($data['uploadMainImage']['tmp_name'], $path . $data['uploadMainImage']['name']);
231
            $game->setMainImage($media_url . $data['uploadMainImage']['name']);
232
            ErrorHandler::stop(true);
233
        }
234
235 View Code Duplication
        if (isset($data['deleteMainImage']) &&
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...
236
            $data['deleteMainImage'] &&
237
            empty($data['uploadMainImage']['tmp_name'])
238
        ) {
239
            ErrorHandler::start();
240
            $image = $game->getMainImage();
241
            $image = str_replace($media_url, '', $image);
242
            unlink($path . $image);
243
            $game->setMainImage(null);
244
            ErrorHandler::stop(true);
245
        }
246
247 View Code Duplication
        if (! empty($data['uploadSecondImage']['tmp_name'])) {
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...
248
            ErrorHandler::start();
249
            $data['uploadSecondImage']['name'] = $this->fileNewname(
250
                $path,
251
                $game->getId() . "-" . $data['uploadSecondImage']['name']
252
            );
253
            move_uploaded_file($data['uploadSecondImage']['tmp_name'], $path . $data['uploadSecondImage']['name']);
254
            $game->setSecondImage($media_url . $data['uploadSecondImage']['name']);
255
            ErrorHandler::stop(true);
256
        }
257
258 View Code Duplication
        if (isset($data['deleteSecondImage']) &&
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...
259
            $data['deleteSecondImage'] &&
260
            empty($data['uploadSecondImage']['tmp_name'])
261
        ) {
262
            ErrorHandler::start();
263
            $image = $game->getSecondImage();
264
            $image = str_replace($media_url, '', $image);
265
            unlink($path . $image);
266
            $game->setSecondImage(null);
267
            ErrorHandler::stop(true);
268
        }
269
270
        if (! empty($data['uploadStylesheet']['tmp_name'])) {
271
            ErrorHandler::start();
272
            move_uploaded_file($data['uploadStylesheet']['tmp_name'], $path . 'stylesheet_' . $game->getId() . '.css');
273
            $game->setStylesheet($media_url . 'stylesheet_' . $game->getId() . '.css');
274
            ErrorHandler::stop(true);
275
        }
276
277 View Code Duplication
        if (! empty($data['uploadFbShareImage']['tmp_name'])) {
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...
278
            ErrorHandler::start();
279
            $data['uploadFbShareImage']['name'] = $this->fileNewname(
280
                $path,
281
                $game->getId() . "-" . $data['uploadFbShareImage']['name']
282
            );
283
            move_uploaded_file($data['uploadFbShareImage']['tmp_name'], $path . $data['uploadFbShareImage']['name']);
284
            $game->setFbShareImage($media_url . $data['uploadFbShareImage']['name']);
285
            ErrorHandler::stop(true);
286
        }
287
288 View Code Duplication
        if (isset($data['deleteFbShareImage']) &&
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...
289
            $data['deleteFbShareImage'] &&
290
            empty($data['uploadFbShareImage']['tmp_name'])
291
        ) {
292
            ErrorHandler::start();
293
            $image = $game->getFbShareImage();
294
            $image = str_replace($media_url, '', $image);
295
            unlink($path . $image);
296
            $game->setFbShareImage(null);
297
            ErrorHandler::stop(true);
298
        }
299
300
        if (! empty($data['uploadFbPageTabImage']['tmp_name'])) {
301
            ErrorHandler::start();
302
            $extension = $this->getExtension(strtolower($data['uploadFbPageTabImage']['name']));
303
            $src = $this->getSrc($extension, $data['uploadFbPageTabImage']['tmp_name']);
304
            $this->resize(
305
                $data['uploadFbPageTabImage']['tmp_name'],
306
                $extension,
307
                $path . $game->getId() . "-" . $data['uploadFbPageTabImage']['name'],
308
                $src,
309
                111,
310
                74
311
            );
312
313
            $game->setFbPageTabImage($media_url . $game->getId() . "-" . $data['uploadFbPageTabImage']['name']);
314
            ErrorHandler::stop(true);
315
        }
316
317 View Code Duplication
        if (isset($data['deleteFbPageTabImage']) &&
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...
318
            $data['deleteFbPageTabImage'] &&
319
            empty($data['uploadFbPageTabImage']['tmp_name'])
320
        ) {
321
            ErrorHandler::start();
322
            $image = $game->getFbPageTabImage();
323
            $image = str_replace($media_url, '', $image);
324
            unlink($path . $image);
325
            $game->setFbPageTabImage(null);
326
            ErrorHandler::stop(true);
327
        }
328
329
        // Let's remove the fbPostId if there is no post to send anymore
330
        if ($data['broadcastPostFacebook'] == 0) {
331
            $game->setFbPostId(null);
332
        }
333
334
        $game = $this->getGameMapper()->update($game);
335
336
        $prize_mapper = $this->serviceLocator->get('playgroundgame_prize_mapper');
337
        if (isset($data['prizes'])) {
338
            foreach ($data['prizes'] as $prize_data) {
339
                if (! empty($prize_data['picture_file']['tmp_name']) && ! $prize_data['picture_file']['error']) {
340
                    if ($prize_data['id']) {
341
                        $prize = $prize_mapper->findById($prize_data['id']);
342
                    } else {
343
                        $some_prizes = $prize_mapper->findBy(array(
344
                            'game' => $game,
345
                            'title' => $prize_data['title']
346
                        ));
347
                        if (count($some_prizes) == 1) {
348
                            $prize = $some_prizes[0];
349
                        } else {
350
                            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\Game::createOrUpdate 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...
351
                        }
352
                    }
353
                    // Remove if existing image
354
                    if ($prize->getPicture() && file_exists($prize->getPicture())) {
355
                        unlink($prize->getPicture());
356
                        $prize->getPicture(null);
357
                    }
358
                    // Upload and set new
359
                    ErrorHandler::start();
360
                    $filename = "game-" . $game->getId() . "-prize-";
361
                    $filename .= $prize->getId() . "-" . $prize_data['picture_file']['name'];
362
                    move_uploaded_file($prize_data['picture_file']['tmp_name'], $path . $filename);
363
                    $prize->setPicture($media_url . $filename);
364
                    ErrorHandler::stop(true);
365
                    $prize_mapper->update($prize);
366
                }
367
            }
368
        }
369
        // If I receive false, it means that the FB Id was not available anymore
370
        $this->getEventManager()->trigger(__FUNCTION__ . '.post', $this, array(
371
            'game' => $game
372
        ));
373
374
        return $game;
375
    }
376
 
377
    /**
378
     * getNextGames
379
     *
380
     * @return Array of PlaygroundGame\Entity\Game
381
     */
382
    public function getNextGames($dateStart = null, $dateEnd = null, $classType = null, $cost = null, $order = null, $dir = 'DESC')
383
    {
384
        $em = $this->serviceLocator->get('doctrine.entitymanager.orm_default');
385
        if ($dateStart === null) {
386
            $today = new \DateTime("now");
387
        } else {
388
            $today = new \DateTime($dateStart);
389
        }
390
        
391
        $today = $today->format('Y-m-d H:i:s');
392
        $orderBy = 'g.startDate';
393
        if ($order != null) {
394
            $orderBy = 'g.'.$order;
395
        }
396
397
        $qb = $em->createQueryBuilder();
398
        $and = $qb->expr()->andx();
399
        $and->add($qb->expr()->gte('g.startDate', ':date'));
400
        $qb->setParameter('date', $today);
401
        if ($dateEnd != null) {
402
            $dateEnd = new \DateTime($dateEnd);
403
            $end = $dateEnd->format('Y-m-d H:i:s');
404
            $and->add($qb->expr()->lte('g.endDate', ':datefin'));
405
            $qb->setParameter('datefin', $end);
406
        }
407
        
408
        $and->add($qb->expr()->eq('g.active', '1'));
409
        $and->add($qb->expr()->eq('g.broadcastPlatform', '1'));
410
        
411
        if ($classType != '') {
412
            $and->add($qb->expr()->eq('g.classType', ':classType'));
413
            $qb->setParameter('classType', $classType);
414
        }
415
        
416
        if ($cost !== null) {
417
            $and->add($qb->expr()->eq('g.costToPlay', ':cost'));
418
            $qb->setParameter('cost', $cost);
419
        }
420
        
421
        $qb->select('g')
422
            ->from('PlaygroundGame\Entity\Game', 'g')
423
            ->where($and)
424
            ->orderBy($orderBy, $dir);
425
        
426
        $query = $qb->getQuery();
427
        //echo $query->getSql();
428
        $games = $query->getResult();
429
        
430
        // je les classe par date de publication (date comme clé dans le tableau afin de pouvoir merger les objets
431
        // de type article avec le même procédé en les classant naturellement par date asc ou desc
432
        $arrayGames = array();
433 View Code Duplication
        foreach ($games as $game) {
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...
434
            if ($game->getPublicationDate()) {
435
                $key = $game->getPublicationDate()->format('Ymd');
436
            } elseif ($game->getStartDate()) {
437
                $key = $game->getStartDate()->format('Ymd');
438
            } else {
439
                $key = $game->getUpdatedAt()->format('Ymd');
440
            }
441
            $key .= $game->getUpdatedAt()->format('Ymd') . '-' . $game->getId();
442
            $arrayGames[$key] = $game;
443
        }
444
445
        return $arrayGames;
446
    }
447
448
    /**
449
     * getActiveGames
450
     *
451
     * @return Array of PlaygroundGame\Entity\Game
452
     */
453
    public function getActiveGames($displayHome = null, $classType = '', $order = '')
454
    {
455
        $em = $this->serviceLocator->get('doctrine.entitymanager.orm_default');
456
        $today = new \DateTime("now");
457
        $today = $today->format('Y-m-d H:i:s');
458
        $orderBy = 'g.publicationDate';
459
        if ($order != '') {
460
            $orderBy = 'g.'.$order;
461
        }
462
463
        $qb = $em->createQueryBuilder();
464
        $and = $qb->expr()->andx();
465
        $and->add(
466
            $qb->expr()->orX(
467
                $qb->expr()->lte('g.publicationDate', ':date'),
468
                $qb->expr()->isNull('g.publicationDate')
469
            )
470
        );
471
        $and->add(
472
            $qb->expr()->orX(
473
                $qb->expr()->gte('g.closeDate', ':date'),
474
                $qb->expr()->isNull('g.closeDate')
475
            )
476
        );
477
        $qb->setParameter('date', $today);
478
        
479
        $and->add($qb->expr()->eq('g.active', '1'));
480
        $and->add($qb->expr()->eq('g.broadcastPlatform', '1'));
481
        
482
        if ($classType != '') {
483
            $and->add($qb->expr()->eq('g.classType', ':classType'));
484
            $qb->setParameter('classType', $classType);
485
        }
486
        
487
        if ($displayHome !== null) {
488
            $and->add($qb->expr()->eq('g.displayHome', ':key'));
489
            $qb->setParameter('key', $displayHome);
490
        }
491
        
492
        $qb->select('g')
493
            ->from('PlaygroundGame\Entity\Game', 'g')
494
            ->where($and)
495
            ->orderBy($orderBy, 'DESC');
496
        
497
        $query = $qb->getQuery();
498
        $games = $query->getResult();
499
        
500
        // je les classe par date de publication (date comme clé dans le tableau afin de pouvoir merger les objets
501
        // de type article avec le même procédé en les classant naturellement par date asc ou desc
502
        $arrayGames = array();
503 View Code Duplication
        foreach ($games as $game) {
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...
504
            if ($game->getPublicationDate()) {
505
                $key = $game->getPublicationDate()->format('Ymd');
506
            } elseif ($game->getStartDate()) {
507
                $key = $game->getStartDate()->format('Ymd');
508
            } else {
509
                $key = $game->getUpdatedAt()->format('Ymd');
510
            }
511
            $key .= $game->getUpdatedAt()->format('Ymd') . '-' . $game->getId();
512
            $arrayGames[$key] = $game;
513
        }
514
515
        return $arrayGames;
516
    }
517
518
    /**
519
     * getAvailableGames : Games OnLine and not already played by $user
520
     *
521
     * @return Array of PlaygroundGame\Entity\Game
522
     */
523
    public function getAvailableGames($user, $maxResults = 2)
524
    {
525
        $em = $this->serviceLocator->get('doctrine.entitymanager.orm_default');
526
        $today = new \DateTime("now");
527
        $today = $today->format('Y-m-d H:i:s');
528
529
        // Game active with a start_date before today (or without start_date)
530
        // and end_date after today (or without end-date)
531
        $query = $em->createQuery('SELECT g FROM PlaygroundGame\Entity\Game g
532
                WHERE NOT EXISTS (SELECT l FROM PlaygroundGame\Entity\Entry l WHERE l.game = g AND l.user = :user)
533
                AND (g.startDate <= :date OR g.startDate IS NULL)
534
                AND (g.endDate >= :date OR g.endDate IS NULL)
535
                AND g.active = 1 AND g.broadcastPlatform = 1
536
                ORDER BY g.startDate ASC');
537
        $query->setParameter('date', $today);
538
        $query->setParameter('user', $user);
539
        $query->setMaxResults($maxResults);
540
        $games = $query->getResult();
541
542
        return $games;
543
    }
544
545 View Code Duplication
    public function getEntriesQuery($game)
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...
546
    {
547
        $em = $this->serviceLocator->get('doctrine.entitymanager.orm_default');
548
549
        $qb = $em->createQueryBuilder();
550
        $qb->select('
551
            e.id,
552
            u.username,
553
            u.title,
554
            u.firstname,
555
            u.lastname,
556
            u.email,
557
            u.optin,
558
            u.optinPartner,
559
            u.address,
560
            u.address2,
561
            u.postalCode,
562
            u.city,
563
            u.country,
564
            u.telephone,
565
            u.mobile,
566
            u.created_at,
567
            u.dob,
568
            e.winner,
569
            e.socialShares,
570
            e.playerData,
571
            e.geoloc,
572
            e.updated_at
573
            ')
574
            ->from('PlaygroundGame\Entity\Entry', 'e')
575
            ->leftJoin('e.user', 'u')
576
            ->where($qb->expr()->eq('e.game', ':game'));
577
        
578
        $qb->setParameter('game', $game);
579
580
        return $qb->getQuery();
581
    }
582
583
    public function getEntriesHeader($game)
584
    {
585
        if ($game->getAnonymousAllowed() && $game->getPlayerForm()) {
586
            $formPV = json_decode($game->getPlayerForm()->getForm(), true);
587
            $header = array('id'=> 1);
588 View Code Duplication
            foreach ($formPV as $element) {
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...
589
                foreach ($element as $k => $v) {
590
                    if ($k !== 'form_properties') {
591
                        $header[$v[0]['name']] = 1;
592
                    }
593
                }
594
            }
595
        } elseif ($game->getAnonymousAllowed()) {
596
            $header = array(
597
                'id' => 1,
598
                'ip' => 1,
599
                'geoloc' => 1,
600
                'winner' => 1,
601
                'socialShares' => 1,
602
                'updated_at' => 1,
603
            );
604
        } else {
605
            $header = array(
606
                'id' => 1,
607
                'username' => 1,
608
                'title' => 1,
609
                'firstname' => 1,
610
                'lastname' => 1,
611
                'email' => 1,
612
                'optin' => 1,
613
                'optinPartner' => 1,
614
                'address' => 1,
615
                'address2' => 1,
616
                'postalCode' => 1,
617
                'city' => 1,
618
                'country' => 1,
619
                'telephone' => 1,
620
                'mobile' => 1,
621
                'created_at' => 1,
622
                'dob' => 1,
623
                'winner' => 1
624
            );
625
        }
626
        $header['geoloc'] = 1;
627
        $header['winner'] = 1;
628
        $header['socialShares'] = 1;
629
        $header['updated_at'] = 1;
630
631
        return $header;
632
    }
633
634
    /**
635
    * getGameEntries : I create an array of entries based on playerData + header
636
    *
637
    * @return Array of PlaygroundGame\Entity\Game
638
    */
639
    public function getGameEntries($header, $entries, $game)
640
    {
641
        $header = $this->getEntriesHeader($game);
642
643
        $results = array();
644
645
        foreach ($entries as $k => $entry) {
646
            $entryData = json_decode($entry['playerData'], true);
647 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...
648
                if (isset($entryData[$key])) {
649
                    $results[$k][$key] = (is_array($entryData[$key]))?implode(', ', $entryData[$key]):$entryData[$key];
650
                } elseif (array_key_exists($key, $entry)) {
651
                    $results[$k][$key] = ($entry[$key] instanceof \DateTime)?
652
                        $entry[$key]->format('Y-m-d H:i:s'):
653
                        $entry[$key];
654
                } else {
655
                    $results[$k][$key] = '';
656
                }
657
            }
658
        }
659
660
        return $results;
661
    }
662
663
    /**
664
     * getActiveSliderGames
665
     *
666
     * @return Array of PlaygroundGame\Entity\Game
667
     */
668
    public function getActiveSliderGames()
669
    {
670
        $em = $this->serviceLocator->get('doctrine.entitymanager.orm_default');
671
        $today = new \DateTime("now");
672
        $today = $today->format('Y-m-d H:i:s');
673
674
        // Game active with a start_date before today (or without start_date)
675
        // and end_date after today (or without end-date)
676
        $query = $em->createQuery('SELECT g FROM PlaygroundGame\Entity\Game g
677
            WHERE (g.publicationDate <= :date OR g.publicationDate IS NULL)
678
            AND (g.closeDate >= :date OR g.closeDate IS NULL)
679
            AND g.active = true AND g.broadcastPlatform = 1 AND g.pushHome = true');
680
        $query->setParameter('date', $today);
681
        $games = $query->getResult();
682
683
        // je les classe par date de publication (date comme clé dans le tableau afin de pouvoir merger les objets
684
        // de type article avec le même procédé en les classant naturellement par date asc ou desc
685
        $arrayGames = array();
686 View Code Duplication
        foreach ($games as $game) {
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...
687
            if ($game->getPublicationDate()) {
688
                $key = $game->getPublicationDate()->format('Ymd');
689
            } elseif ($game->getStartDate()) {
690
                $key = $game->getStartDate()->format('Ymd');
691
            } else {
692
                $key = $game->getUpdatedAt()->format('Ymd');
693
            }
694
            $key .= $game->getUpdatedAt()->format('Ymd') . '-' . $game->getId();
695
            $arrayGames[$key] = $game;
696
        }
697
698
        return $arrayGames;
699
    }
700
701
    /**
702
     * getPrizeCategoryGames
703
     *
704
     * @return Array of PlaygroundGame\Entity\Game
705
     */
706 View Code Duplication
    public function getPrizeCategoryGames($categoryid)
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...
707
    {
708
        $em = $this->serviceLocator->get('doctrine.entitymanager.orm_default');
709
710
        $query = $em->createQuery('SELECT g FROM PlaygroundGame\Entity\Game g
711
            WHERE (g.prizeCategory = :categoryid AND g.broadcastPlatform = 1)
712
            ORDER BY g.publicationDate DESC');
713
        $query->setParameter('categoryid', $categoryid);
714
        $games = $query->getResult();
715
716
        return $games;
717
    }
718
719
    public function getGameIdentifierFromFacebook($fbPageId)
720
    {
721
        $identifier = null;
722
        $game = $this->getGameMapper()->findOneBy(array('fbPageId' => $fbPageId, 'broadcastFacebook' => 1));
723
724
        if($game && $game->getIdentifier() !== null) {
725
            $identifier = $game->getIdentifier();
726
        }
727
728
        return $identifier;
729
    }
730
731
    public function checkGame($identifier, $checkIfStarted = true)
732
    {
733
        $gameMapper = $this->getGameMapper();
734
735
        if (! $identifier) {
736
            return false;
737
        }
738
739
        $game = $gameMapper->findByIdentifier($identifier);
740
741
        // the game has not been found
742
        if (! $game) {
743
            return false;
744
        }
745
746
        // for preview stuff as admin
747
        if ($this->isAllowed('game', 'edit')) {
748
            $r =$this->serviceLocator->get('request');
749
            if ($r->getQuery()->get('preview')) {
750
                $game->setActive(true);
751
                $game->setStartDate(null);
752
                $game->setEndDate(null);
753
                $game->setPublicationDate(null);
754
                $game->setBroadcastPlatform(true);
755
756
                // I don't want the game to be updated through any update during the preview mode.
757
                // I mark it as readonly for Doctrine
758
                $this->serviceLocator
759
                    ->get('doctrine.entitymanager.orm_default')
760
                    ->getUnitOfWork()
761
                    ->markReadOnly($game);
762
                    
763
                return $game;
764
            }
765
        }
766
767
        // The game is inactive
768
        if (! $game->getActive()) {
769
            return false;
770
        }
771
772
        // the game has not begun yet
773
        if (! $game->isOpen()) {
774
            return false;
775
        }
776
777
        // the game is finished and closed
778
        if (! $game->isStarted() && $checkIfStarted) {
779
            return false;
780
        }
781
782
        return $game;
783
    }
784
785
    /**
786
     * Return the last entry of the user on this game, if it exists.
787
     * An entry can be associated to :
788
     * - A user account (a real one, linked to PlaygroundUser
789
     * - An anonymous Identifier (based on one value of playerData (generally email))
790
     * - A cookie set on the player device (the less secure)
791
     * If the active param is set, it can check if the entry is active or not.
792
     * If the bonus param is set, it can check if the entry is a bonus or not.
793
     *
794
     * @param unknown $game
795
     * @param string $user
796
     * @param boolean $active
797
     * @param boolean $bonus
798
     * @return boolean
799
     */
800
    public function checkExistingEntry($game, $user = null, $active = null, $bonus = null)
801
    {
802
        $search = array('game'  => $game);
803
804
        if ($user) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $user of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
805
            $search['user'] = $user;
806
        } elseif ($this->getAnonymousIdentifier()) {
807
            $search['anonymousIdentifier'] = $this->getAnonymousIdentifier();
808
            $search['user'] = null;
809
        } else {
810
            $search['anonymousId'] = $this->getAnonymousId();
811
            $search['user'] = null;
812
        }
813
        
814
        if (! is_null($active)) {
815
            $search['active'] = $active;
816
        }
817
        if (! is_null($bonus)) {
818
            $search['bonus'] = $bonus;
819
        }
820
821
        $entry = $this->getEntryMapper()->findOneBy($search, array('updated_at' => 'desc'));
822
823
        return $entry;
824
    }
825
826
    /*
827
    * This function updates the entry with the player data after checking
828
    * that the data are compliant with the formUser Game attribute
829
    *
830
    * The $data has to be a json object
831
    */
832
    public function updateEntryPlayerForm($data, $game, $user, $entry, $mandatory = true)
0 ignored issues
show
Unused Code introduced by
The parameter $user 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...
833
    {
834
        $form = $this->createFormFromJson($game->getPlayerForm()->getForm(), 'playerForm');
835
        $form->setData($data);
836
837
        if (!$mandatory) {
838
            $filter = $form->getInputFilter();
839
            foreach ($form->getElements() as $element) {
840
                try {
841
                    $elementInput = $filter->get($element->getName());
842
                    $elementInput->setRequired(false);
843
                    $form->get($element->getName())->setAttribute('required', false);
844
                } catch (\Zend\Form\Exception\InvalidElementException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
845
                }
846
            }
847
        }
848
849
        if ($form->isValid()) {
850
            $dataJson = json_encode($form->getData());
851
852
            if ($game->getAnonymousAllowed() &&
853
                $game->getAnonymousIdentifier() &&
854
                isset($data[$game->getAnonymousIdentifier()])
855
            ) {
856
                $session = new \Zend\Session\Container('anonymous_identifier');
857
                $anonymousIdentifier = $data[$game->getAnonymousIdentifier()];
858
                $entry->setAnonymousIdentifier($anonymousIdentifier);
859
                if (empty($session->offsetGet('anonymous_identifier'))) {
860
                    $session->offsetSet('anonymous_identifier', $anonymousIdentifier);
861
                }
862
            }
863
864
            $entry->setPlayerData($dataJson);
865
            $this->getEntryMapper()->update($entry);
866
        } else {
867
            return false;
868
        }
869
870
        return true;
871
    }
872
873
874
    public function checkIsFan($game)
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...
875
    {
876
        // If on Facebook, check if you have to be a FB fan to play the game
877
        $session = new Container('facebook');
878
879
        if ($session->offsetExists('signed_request')) {
880
            // I'm on Facebook
881
            $sr = $session->offsetGet('signed_request');
882
            if ($sr['page']['liked'] == 1) {
883
                return true;
884
            }
885
        } else {
886
            // I'm not on Facebook
887
            return true;
888
        }
889
890
        return false;
891
    }
892
    
893
    public function getAnonymousIdentifier()
894
    {
895
        if (is_null($this->anonymousIdentifier) || $this->anonymousIdentifier === false) {
896
            $session = new Container('anonymous_identifier');
897
            
898
            if ($session->offsetExists('anonymous_identifier')) {
899
                $this->anonymousIdentifier = $session->offsetGet('anonymous_identifier');
900
            } else {
901
                $this->anonymousIdentifier = false;
902
            }
903
        }
904
    
905
        return $this->anonymousIdentifier;
906
    }
907
908
    /**
909
     * errors :
910
     * -1 : user not connected
911
     * -2 : limit entry games for this user reached
912
     *
913
     * @param \PlaygroundGame\Entity\Game $game
914
     * @param \PlaygroundUser\Entity\UserInterface $user
915
     * @return number unknown
916
     */
917
    public function play($game, $user)
918
    {
919
920
        // certaines participations peuvent rester ouvertes.
921
        // On autorise alors le joueur à reprendre là ou il en était
922
        // par exemple les postvote...
923
        $entry = $this->checkExistingEntry($game, $user, true);
0 ignored issues
show
Documentation introduced by
$game is of type object<PlaygroundGame\Entity\Game>, but the function expects a object<PlaygroundGame\Service\unknown>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Documentation introduced by
$user is of type object<PlaygroundUser\Entity\UserInterface>, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
924
925
        if (! $entry) {
926
            if ($this->hasReachedPlayLimit($game, $user)) {
927
                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\Game::play of type integer|double.

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...
928
            }
929
            if (!$this->payToPlay($game, $user)) {
930
                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\Game::play of type integer|double.

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...
931
            }
932
933
            $ip = $this->getIp();
934
            $geoloc = $this->getGeoloc($ip);
935
            $entry = new Entry();
936
            $entry->setGame($game);
0 ignored issues
show
Documentation introduced by
$game is of type object<PlaygroundGame\Entity\Game>, but the function expects a object<PlaygroundGame\Entity\field_type>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
937
            $entry->setUser($user);
0 ignored issues
show
Documentation introduced by
$user is of type object<PlaygroundUser\Entity\UserInterface>, but the function expects a object<PlaygroundGame\Entity\field_type>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
938
            $entry->setPoints(0);
939
            $entry->setIp($ip);
940
            $entry->setGeoloc($geoloc);
0 ignored issues
show
Documentation introduced by
$geoloc is of type string, but the function expects a object<PlaygroundGame\Entity\field_type>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
941
            $entry->setAnonymousId($this->getAnonymousId());
942
            if ($this->getAnonymousIdentifier()) {
943
                $entry->setAnonymousIdentifier($this->getAnonymousIdentifier());
944
            }
945
946
            $entry = $this->getEntryMapper()->insert($entry);
947
            $this->getEventManager()->trigger(
948
                __FUNCTION__ . '.post',
949
                $this,
950
                [
951
                    'user' => $user,
952
                    'game' => $game,
953
                    'entry' => $entry,
954
                ]
955
            );
956
        }
957
958
        return $entry;
959
    }
960
961
    /**
962
     * @param \PlaygroundGame\Entity\Game $game
963
     * @param \PlaygroundUser\Entity\UserInterface $user
964
     */
965
    public function hasReachedPlayLimit($game, $user)
966
    {
967
        // Is there a limitation on the game ?
968
        $limitAmount = $game->getPlayLimit();
969
        if ($limitAmount) {
970
            $limitScale = $game->getPlayLimitScale();
971
            $userEntries = $this->findLastEntries($game, $user, $limitScale);
972
973
            // player has reached the game limit
974
            if ($userEntries >= $limitAmount) {
975
                return true;
976
            }
977
        }
978
        return false;
979
    }
980
981
    /**
982
     * If the game has a cost to be played (costToPlay>0)
983
     * I check and decrement the price from the leaderboard all of the user
984
     * 
985
     * @param \PlaygroundGame\Entity\Game $game
986
     * @param \PlaygroundUser\Entity\UserInterface $user
987
     */
988
    public function payToPlay($game, $user)
989
    {
990
        // Is there a limitation on the game ?
991
        $cost = $game->getCostToPlay();
992
        if ($cost && $cost > 0) {
993
            $availableAmount = $this->getEventManager()->trigger(
994
                'leaderboardUserTotal',
995
                $this,
996
                [
997
                    'user' => $user,
998
                ]
999
            )->last();
1000
            if ($availableAmount && $availableAmount >= $cost) {
1001
                $leaderboard = $this->getEventManager()->trigger(
1002
                    'leaderboardUserUpdate',
1003
                    $this,
1004
                    [
1005
                        'user' => $user,
1006
                        'points' => -$cost,
1007
                    ]
1008
                )->last();
1009
1010
                if ($leaderboard->getTotalPoints() === ($availableAmount - $cost)) {
1011
                    return true;
1012
                }
1013
            }
1014
        } else {
1015
            return true;
1016
        }
1017
1018
        return false;
1019
    }
1020
    
1021
    /**
1022
     * @param \PlaygroundGame\Entity\Game $game
1023
     * @param \PlaygroundUser\Entity\UserInterface $user
1024
     */
1025
    public function findLastEntries($game, $user, $limitScale)
1026
    {
1027
        $limitDate = $this->getLimitDate($limitScale);
1028
1029
        if ($user) {
1030
            return $this->getEntryMapper()->countLastEntriesByUser($game, $user, $limitDate);
1031
        } elseif ($this->getAnonymousIdentifier()) {
1032
            $entries = $this->getEntryMapper()->countLastEntriesByAnonymousIdentifier(
1033
                $game,
1034
                $this->getAnonymousIdentifier(),
1035
                $limitDate
1036
            );
1037
1038
            return $entries;
1039 View Code Duplication
        } else {
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...
1040
            // If the game is supposed to be a reguler user game or an anonymous identified game,
1041
            // it means that the registration/login is at the end of the game
1042
            if((!$user &&  !$game->getAnonymousAllowed()) || ($game->getAnonymousAllowed() && $game->getAnonymousIdentifier())) {
1043
                return 0;
1044
            }
1045
            return $this->getEntryMapper()->countLastEntriesByIp($game, $this->getIp(), $limitDate);
1046
        }
1047
    }
1048
1049
    /**
1050
    *
1051
    *
1052
    */
1053
    public function getLimitDate($limitScale)
1054
    {
1055
        $now = new \DateTime("now");
1056
        switch ($limitScale) {
1057
            case 'always':
1058
                $interval = 'P100Y';
1059
                $now->sub(new \DateInterval($interval));
1060
                $dateLimit = $now->format('Y-m-d') . ' 0:0:0';
1061
                break;
1062
            case 'day':
1063
                $dateLimit = $now->format('Y-m-d') . ' 0:0:0';
1064
                break;
1065 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...
1066
                $interval = 'P7D';
1067
                $now->sub(new \DateInterval($interval));
1068
                $dateLimit = $now->format('Y-m-d') . ' 0:0:0';
1069
                break;
1070 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...
1071
                $interval = 'P1M';
1072
                $now->sub(new \DateInterval($interval));
1073
                $dateLimit = $now->format('Y-m-d') . ' 0:0:0';
1074
                break;
1075 View Code Duplication
            case 'year':
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...
1076
                $interval = 'P1Y';
1077
                $now->sub(new \DateInterval($interval));
1078
                $dateLimit = $now->format('Y-m-d') . ' 0:0:0';
1079
                break;
1080 View Code Duplication
            default:
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...
1081
                $interval = 'P100Y';
1082
                $now->sub(new \DateInterval($interval));
1083
                $dateLimit = $now->format('Y-m-d') . ' 0:0:0';
1084
        }
1085
1086
        return $dateLimit;
1087
    }
1088
1089
    public function findLastActiveEntry($game, $user)
1090
    {
1091
        return $this->checkExistingEntry($game, $user, true);
1092
    }
1093
1094
    public function findLastInactiveEntry($game, $user)
1095
    {
1096
        return $this->checkExistingEntry($game, $user, false, false);
1097
    }
1098
1099
    public function findLastEntry($game, $user)
1100
    {
1101
        return $this->checkExistingEntry($game, $user, null, false);
1102
    }
1103
1104
    public function inviteToTeam($data, $game, $user)
1105
    {
1106
        $mailService = $this->serviceLocator->get('playgroundgame_message');
1107
        $invitationMapper = $this->serviceLocator->get('playgroundgame_invitation_mapper');
1108
1109
        $sentInvitations = $invitationMapper->findBy(array('host' => $user, 'game' => $game));
1110
        $nbInvitations = count($sentInvitations);
1111
        $to = $data['email'];
1112
        if (empty($to)) {
1113
            return ['result'=>false, 'message'=>'no email'];
1114
        }
1115
1116
        if ($nbInvitations < 20) {
1117
            $alreadyInvited = $invitationMapper->findBy(array('requestKey' => $to, 'game' => $game));
1118
            if (!$alreadyInvited) {
1119
                $alreadyInvited = $this->getUserMapper()->findByEmail($to);
1120
            }
1121
1122
            if (empty($alreadyInvited)) {
1123
                $invitation = new \PlaygroundGame\Entity\Invitation();
1124
                $invitation->setRequestKey($to);
1125
                $invitation->setGame($game);
1126
                $invitation->setHost($user);
1127
                $invitationMapper->insert($invitation);
1128
1129
                $from = $this->getOptions()->getEmailFromAddress();
1130
                $subject = $this->serviceLocator->get('MvcTranslator')->translate(
1131
                    $this->getOptions()->getInviteToTeamSubjectLine(),
1132
                    'playgroundgame'
1133
                );
1134
                $message = $mailService->createHtmlMessage(
1135
                    $from,
1136
                    $to,
1137
                    $subject,
1138
                    'playground-game/email/invite_team',
1139
                    array(
1140
                        'game' => $game,
1141
                        'user' => $user,
1142
                        'data' => $data,
1143
                        'from' => $from
1144
                    )
1145
                );
1146
                try {
1147
                    $mailService->send($message);
1148
                } catch (\Zend\Mail\Protocol\Exception\RuntimeException $e) {
0 ignored issues
show
Bug introduced by
The class Zend\Mail\Protocol\Exception\RuntimeException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1149
                    return ['result' => true, 'message' => $this->serviceLocator->get('MvcTranslator')->translate(
1150
                        'mail error'
1151
                    )];
1152
                }
1153
1154
                return ['result' => true, 'message' => ''];
1155
            } else {
1156
                return ['result' => false, 'message' => 'already invited'];
1157
            }
1158
        } else {
1159
            return [
1160
                'result' => false,
1161
                'message' => $this->serviceLocator->get('MvcTranslator')->translate(
1162
                    'Too many invitations for this user'
1163
                )
1164
            ];
1165
        }
1166
    }
1167
1168
    public function sendShareMail(
1169
        $data,
1170
        $game,
1171
        $user,
1172
        $entry,
1173
        $template = 'share_game',
1174
        $subject = ''
1175
    ) {
1176
        $mailService = $this->serviceLocator->get('playgroundgame_message');
1177
        $mailSent = false;
1178
        $from = $this->getOptions()->getEmailFromAddress();
1179
1180
        if (empty($subject)) {
1181
            $subject = $game->getEmailShareSubject();
1182
        }
1183
1184
        $renderer = $this->serviceLocator->get('Zend\View\Renderer\RendererInterface');
1185
        $skinUrl = $renderer->url(
1186
            'frontend',
1187
            array(),
1188
            array('force_canonical' => true)
1189
        );
1190
        $secretKey = strtoupper(substr(sha1(uniqid('pg_', true) . '####' . time()), 0, 15));
1191
1192
        if (isset($data['email']) && !is_array($data['email'])) {
1193
            $data['email'] = array($data['email']);
1194
        }
1195
        
1196
        foreach ($data['email'] as $to) {
1197
            $mailSent = true;
1198
            if (!empty($to)) {
1199
                $message = $mailService->createHtmlMessage(
1200
                    $from,
1201
                    $to,
1202
                    $subject,
1203
                    'playground-game/email/' . $template,
1204
                    array(
1205
                        'game' => $game,
1206
                        'data' => $data,
1207
                        'from' => $from,
1208
                        'to' => $to,
1209
                        'secretKey' => $secretKey,
1210
                        'skinUrl' => $skinUrl,
1211
                        'message' => $game->getEmailShareMessage()
1212
                    )
1213
                );
1214
                try {
1215
                    $mailService->send($message);
1216
                } catch (\Zend\Mail\Protocol\Exception\RuntimeException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
Bug introduced by
The class Zend\Mail\Protocol\Exception\RuntimeException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1217
                }
1218
                
1219
                if ($entry) {
1220
                    $shares = json_decode($entry->getSocialShares(), true);
1221
                    (!isset($shares['mail']))? $shares['mail'] = 1:$shares['mail'] += 1;
1222
                }
1223
            }
1224
        }
1225
1226
        if ($mailSent) {
1227
            if ($entry) {
1228
                $sharesJson = json_encode($shares);
0 ignored issues
show
Bug introduced by
The variable $shares 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...
1229
                $entry->setSocialShares($sharesJson);
1230
                $entry = $this->getEntryMapper()->update($entry);
1231
            }
1232
            
1233
            $this->getEventManager()->trigger(__FUNCTION__ . '.post', $this, array(
1234
                'user' => $user,
1235
                'secretKey' => $secretKey,
1236
                'data' => $data,
1237
                'game' => $game,
1238
                'entry' => $entry,
1239
                'message' => $game->getEmailShareMessage()
1240
            ));
1241
1242
            return true;
1243
        }
1244
1245
        return false;
1246
    }
1247
1248
    /**
1249
     * @param \PlaygroundGame\Entity\Game $game
1250
     * @param \PlaygroundUser\Entity\User $user
1251
     * @param Entry $entry
1252
     * @param \PlaygroundGame\Entity\Prize $prize
1253
     */
1254
    public function sendResultMail($game, $user, $entry, $template = 'entry', $prize = null)
1255
    {
1256
        $mailService = $this->serviceLocator->get('playgroundgame_message');
1257
        $from = $this->getOptions()->getEmailFromAddress();
1258
        if ($entry->getAnonymousIdentifier()) {
1259
            $to = $entry->getAnonymousIdentifier();
1260
        } elseif ($user) {
1261
            $to = $user->getEmail();
1262
        } else {
1263
            return false;
1264
        }
1265
        $subject = $this->serviceLocator->get('MvcTranslator')->translate(
1266
            $this->getOptions()->getParticipationSubjectLine(),
1267
            'playgroundgame'
1268
        );
1269
        $renderer = $this->serviceLocator->get('Zend\View\Renderer\RendererInterface');
1270
        $skinUrl = $renderer->url(
1271
            'frontend',
1272
            array(),
1273
            array('force_canonical' => true)
1274
        );
1275
        $message = $mailService->createHtmlMessage($from, $to, $subject, 'playground-game/email/' . $template, array(
1276
            'game' => $game,
1277
            'entry' => $entry,
1278
            'skinUrl' => $skinUrl,
1279
            'prize' => $prize
1280
        ));
1281
        $mailService->send($message);
1282
    }
1283
1284
    public function sendGameMail($game, $user, $post, $template = 'postvote')
1285
    {
1286
        $mailService = $this->serviceLocator->get('playgroundgame_message');
1287
        $from = $this->getOptions()->getEmailFromAddress();
1288
        $to = $user->getEmail();
1289
        $subject = $this->serviceLocator->get('MvcTranslator')->translate(
1290
            $this->getOptions()->getParticipationSubjectLine(),
1291
            'playgroundgame'
1292
        );
1293
        $renderer = $this->serviceLocator->get('Zend\View\Renderer\RendererInterface');
1294
        $skinUrl = $renderer->url(
1295
            'frontend',
1296
            array(),
1297
            array('force_canonical' => true)
1298
        );
1299
1300
        $message = $mailService->createHtmlMessage($from, $to, $subject, 'playground-game/email/' . $template, array(
1301
            'game' => $game,
1302
            'post' => $post,
1303
            'skinUrl' => $skinUrl
1304
        ));
1305
        $mailService->send($message);
1306
    }
1307
1308 View Code Duplication
    public function postFbWall($secretKey, $game, $user, $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...
1309
    {
1310
        $topic = $game->getTitle();
1311
        
1312
        $shares = json_decode($entry->getSocialShares(), true);
1313
        if (!isset($shares['fbwall'])) {
1314
            $shares['fbwall'] = 1;
1315
        } else {
1316
            $shares['fbwall'] += 1;
1317
        }
1318
        $sharesJson = json_encode($shares);
1319
        $entry->setSocialShares($sharesJson);
1320
        $entry = $this->getEntryMapper()->update($entry);
1321
        
1322
        $this->getEventManager()->trigger(__FUNCTION__ . '.post', $this, array(
1323
            'user' => $user,
1324
            'game' => $game,
1325
            'secretKey' => $secretKey,
1326
            'topic' => $topic,
1327
            'entry' => $entry
1328
        ));
1329
1330
        return true;
1331
    }
1332
1333
    public function postFbRequest($secretKey, $game, $user, $entry, $to)
1334
    {
1335
        $shares = json_decode($entry->getSocialShares(), true);
1336
        $to = explode(',', $to);
1337
        if (!isset($shares['fbrequest'])) {
1338
            $shares['fbrequest'] = count($to);
1339
        } else {
1340
            $shares['fbrequest'] += count($to);
1341
        }
1342
        $sharesJson = json_encode($shares);
1343
        $entry->setSocialShares($sharesJson);
1344
        $entry = $this->getEntryMapper()->update($entry);
1345
        
1346
        $this->getEventManager()->trigger(__FUNCTION__ . '.post', $this, array(
1347
            'user' => $user,
1348
            'game' => $game,
1349
            'secretKey' => $secretKey,
1350
            'entry' => $entry,
1351
            'invites' => count($to)
1352
        ));
1353
1354
        return true;
1355
    }
1356
1357 View Code Duplication
    public function postTwitter($secretKey, $game, $user, $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...
1358
    {
1359
        $topic = $game->getTitle();
1360
1361
        $shares = json_decode($entry->getSocialShares(), true);
1362
        if (!isset($shares['fbrequest'])) {
1363
            $shares['tweet'] = 1;
1364
        } else {
1365
            $shares['tweet'] += 1;
1366
        }
1367
        $sharesJson = json_encode($shares);
1368
        $entry->setSocialShares($sharesJson);
1369
        $entry = $this->getEntryMapper()->update($entry);
1370
        
1371
        $this->getEventManager()->trigger(__FUNCTION__ . '.post', $this, array(
1372
            'user' => $user,
1373
            'game' => $game,
1374
            'secretKey' => $secretKey,
1375
            'topic' => $topic,
1376
            'entry' => $entry
1377
        ));
1378
1379
        return true;
1380
    }
1381
1382 View Code Duplication
    public function postGoogle($secretKey, $game, $user, $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...
1383
    {
1384
        $topic = $game->getTitle();
1385
        
1386
        $shares = json_decode($entry->getSocialShares(), true);
1387
        if (!isset($shares['fbrequest'])) {
1388
            $shares['google'] = 1;
1389
        } else {
1390
            $shares['google'] += 1;
1391
        }
1392
        $sharesJson = json_encode($shares);
1393
        $entry->setSocialShares($sharesJson);
1394
        $entry = $this->getEntryMapper()->update($entry);
1395
1396
        $this->getEventManager()->trigger(__FUNCTION__ . '.post', $this, array(
1397
            'user' => $user,
1398
            'game' => $game,
1399
            'secretKey' => $secretKey,
1400
            'topic' => $topic,
1401
            'entry' => $entry
1402
        ));
1403
1404
        return true;
1405
    }
1406
1407
    /**
1408
     * Is it possible to trigger a bonus entry ?
1409
     *
1410
     * @param unknown_type $game
1411
     * @param unknown_type $user
1412
     */
1413
    public function allowBonus($game, $user)
1414
    {
1415
        if (! $game->getPlayBonus() || $game->getPlayBonus() == 'none') {
1416
            return false;
1417
        } elseif ($game->getPlayBonus() == 'one') {
1418
            if ($this->getEntryMapper()->findOneBy(array(
1419
                'game' => $game,
1420
                'user' => $user,
1421
                'bonus' => 1
1422
            ))) {
1423
                return false;
1424
            } else {
1425
                return true;
1426
            }
1427
        } elseif ($game->getPlayBonus() == 'per_entry') {
1428
            return $this->getEntryMapper()->checkBonusEntry($game, $user);
1429
        }
1430
1431
        return false;
1432
    }
1433
1434
    public function addAnotherEntry($game, $user, $winner = 0)
1435
    {
1436
        $entry = new Entry();
1437
        $entry->setGame($game);
1438
        $entry->setUser($user);
1439
        $entry->setPoints(0);
1440
        $entry->setIp($this->getIp());
1441
        $entry->setActive(0);
1442
        $entry->setBonus(1);
1443
        $entry->setWinner($winner);
1444
        $entry = $this->getEntryMapper()->insert($entry);
1445
1446
        return $entry;
1447
    }
1448
1449
    /**
1450
     * This bonus entry doesn't give points nor badges
1451
     * It's just there to increase the chances during the Draw
1452
     * Old Name playBonus
1453
     *
1454
     * @param PlaygroundGame\Entity\Game $game
1455
     * @param unknown $user
1456
     * @return boolean unknown
1457
     */
1458
    public function addAnotherChance($game, $user, $winner = 0)
1459
    {
1460
        if ($this->allowBonus($game, $user)) {
1461
            $this->addAnotherEntry($game, $user, $winner);
1462
1463
            return true;
1464
        }
1465
1466
        return false;
1467
    }
1468
1469
    /**
1470
     * This bonus entry doesn't give points nor badges but can play again
1471
     *
1472
     * @param PlaygroundGame\Entity\Game $game
1473
     * @param user $user
1474
     * @return boolean unknown
1475
     */
1476
    public function playAgain($game, $user, $winner = 0)
1477
    {
1478
        if ($this->allowBonus($game, $user)) {
1479
            $entry = $this->addAnotherEntry($game, $user, $winner);
1480
            $entry->setActive(1);
1481
            $entry = $this->getEntryMapper()->update($entry);
1482
            if ($entry->getActive() == 1) {
1483
                return true;
1484
            }
1485
        }
1486
1487
        return false;
1488
    }
1489
1490
    /**
1491
     * @param string $path
1492
     * @param boolean $noReplace : If the image name already exist, don't replace it but change the name
1493
     */
1494
    public function uploadFile($path, $file, $noReplace = true)
1495
    {
1496
        $err = $file["error"];
1497
        $message = '';
1498
        if ($err > 0) {
1499
            switch ($err) {
1500
                case '1':
1501
                    $message .= 'Max file size exceeded. (php.ini)';
1502
                    break;
1503
                case '2':
1504
                    $message .= 'Max file size exceeded.';
1505
                    break;
1506
                case '3':
1507
                    $message .= 'File upload was only partial.';
1508
                    break;
1509
                case '4':
1510
                    $message .= 'No file was attached.';
1511
                    break;
1512
                case '7':
1513
                    $message .= 'File permission denied.';
1514
                    break;
1515
                default:
1516
                    $message .= 'Unexpected error occurs.';
1517
            }
1518
1519
            return $err;
1520
        } else {
1521
            $fileNewname = $this->fileNewname($path, $file['name'], $noReplace);
1522
1523
            if (isset($file["base64"])) {
1524
                list(, $img) = explode(',', $file["base64"]);
1525
                $img = str_replace(' ', '+', $img);
1526
                $im = base64_decode($img);
1527
                if ($im !== false) {
1528
                    // getimagesizefromstring
1529
                    file_put_contents($path . $fileNewname, $im);
1530
                } else {
1531
                    return 1;
1532
                }
1533
1534
                return $fileNewname;
1535
            } else {
1536
                $adapter = new \Zend\File\Transfer\Adapter\Http();
1537
                // 1Mo
1538
                $size = new Size(array(
1539
                    'max' => 1024000
1540
                ));
1541
                $is_image = new IsImage('jpeg,png,gif,jpg');
1542
                $adapter->setValidators(array(
1543
                    $size,
1544
                    $is_image
1545
                ), $fileNewname);
1546
1547
                if (! $adapter->isValid()) {
1548
                    return false;
1549
                }
1550
1551
                @move_uploaded_file($file["tmp_name"], $path . $fileNewname);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
1552
            }
1553
1554
            
1555
            if (class_exists("Imagick")) {
1556
                $ext = pathinfo($fileNewname, PATHINFO_EXTENSION);
1557
                $img = new \Imagick($path . $fileNewname);
1558
                $img->cropThumbnailImage(100, 100);
1559
                $img->setImageCompression(\Imagick::COMPRESSION_JPEG);
1560
                $img->setImageCompressionQuality(75);
1561
                // Strip out unneeded meta data
1562
                $img->stripImage();
1563
                $img->writeImage($path . str_replace('.'.$ext, '-thumbnail.'.$ext, $fileNewname));
1564
                ErrorHandler::stop(true);
1565
            }
1566
        }
1567
1568
        return $fileNewname;
1569
    }
1570
1571
    /**
1572
     * @param string $path
1573
     */
1574
    public function fileNewname($path, $filename, $generate = false)
1575
    {
1576
        $sanitize = new Sanitize();
1577
        $name = $sanitize->filter($filename);
1578
        $newpath = $path . $name;
1579
1580
        if ($generate) {
1581
            if (file_exists($newpath)) {
1582
                $filename = pathinfo($name, PATHINFO_FILENAME);
1583
                $ext = pathinfo($name, PATHINFO_EXTENSION);
1584
1585
                $name = $filename . '_' . rand(0, 99) . '.' . $ext;
1586
            }
1587
        }
1588
1589
        unset($sanitize);
1590
1591
        return $name;
1592
    }
1593
1594
    /**
1595
     * This function returns the list of games, ordered by $type
1596
     */
1597
    public function getQueryGamesOrderBy($type = 'createdAt', $order = 'DESC')
1598
    {
1599
        $em = $this->serviceLocator->get('doctrine.entitymanager.orm_default');
1600
        $today = new \DateTime("now");
1601
        $today = $today->format('Y-m-d H:i:s');
1602
1603
        $onlineGames = '(
1604
            (
1605
                CASE WHEN (
1606
                    g.active = 1
1607
                    AND g.broadcastPlatform = 1
1608
                    AND (g.startDate <= :date OR g.startDate IS NULL)
1609
                    AND (g.closeDate >= :date OR g.closeDate IS NULL)
1610
                ) THEN 1 ELSE 0 END
1611
            ) +
1612
            (
1613
                CASE WHEN (
1614
                    g.active = 0
1615
                    AND (g.broadcastPlatform = 0 OR g.broadcastPlatform IS NULL)
1616
                    AND g.startDate > :date
1617
                    AND g.closeDate < :date
1618
                ) THEN 1 ELSE 0 END
1619
            )
1620
        )';
1621
1622
        $qb = $em->createQueryBuilder();
1623
        $qb->select('g')->from('PlaygroundGame\Entity\Game', 'g');
1624
        
1625
        switch ($type) {
1626
            case 'startDate':
1627
                $qb->orderBy('g.startDate', $order);
1628
                break;
1629
            case 'activeGames':
1630
                $qb->orderBy('g.active', $order);
1631
                break;
1632
            case 'onlineGames':
1633
                $qb->orderBy($onlineGames, $order);
1634
                $qb->setParameter('date', $today);
1635
                break;
1636
            case 'createdAt':
1637
                $qb->orderBy('g.createdAt', $order);
1638
                break;
1639
        }
1640
1641
        $query = $qb->getQuery();
1642
1643
        return $query;
1644
    }
1645
1646
    public function draw($game)
1647
    {
1648
        $total = $game->getWinners();
1649
1650
        // I Have to know what is the User Class used
1651
        $zfcUserOptions = $this->serviceLocator->get('zfcuser_module_options');
1652
        $userClass = $zfcUserOptions->getUserEntityClass();
1653
1654
        $result = $this->getEntryMapper()->draw($game, $userClass, $total);
1655
1656
        foreach ($result as $e) {
1657
            $e->setWinner(1);
1658
            $e = $this->getEntryMapper()->update($e);
1659
            $this->getEventManager()->trigger('win_lottery.post', $this, array(
1660
                'user' => $e->getUser(),
1661
                'game' => $game,
1662
                'entry' => $e
1663
            ));
1664
        }
1665
1666
        return $result;
1667
    }
1668
1669
    /**
1670
     * getGameMapper
1671
     *
1672
     * @return GameMapperInterface
1673
     */
1674 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...
1675
    {
1676
        if (null === $this->gameMapper) {
1677
            $this->gameMapper = $this->serviceLocator->get('playgroundgame_game_mapper');
1678
        }
1679
1680
        return $this->gameMapper;
1681
    }
1682
1683
    /**
1684
     * setGameMapper
1685
     *
1686
     * @param GameMapperInterface $gameMapper
1687
     * @return Game
1688
     */
1689
    public function setGameMapper(GameMapperInterface $gameMapper)
1690
    {
1691
        $this->gameMapper = $gameMapper;
1692
1693
        return $this;
1694
    }
1695
1696
    /**
1697
     * getEntryMapper
1698
     *
1699
     * @return EntryMapperInterface
1700
     */
1701
    public function getEntryMapper()
1702
    {
1703
        if (null === $this->entryMapper) {
1704
            $this->entryMapper = $this->serviceLocator->get('playgroundgame_entry_mapper');
1705
        }
1706
1707
        return $this->entryMapper;
1708
    }
1709
1710
    /**
1711
     * setEntryMapper
1712
     *
1713
     * @param EntryMapperInterface $entryMapper
1714
     * @return Game
1715
     */
1716
    public function setEntryMapper($entryMapper)
1717
    {
1718
        $this->entryMapper = $entryMapper;
1719
1720
        return $this;
1721
    }
1722
1723
    public function setOptions(ModuleOptions $options)
1724
    {
1725
        $this->options = $options;
0 ignored issues
show
Documentation Bug introduced by
It seems like $options of type object<PlaygroundGame\Options\ModuleOptions> is incompatible with the declared type object<PlaygroundGame\Se...erviceOptionsInterface> of property $options.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
1726
1727
        return $this;
1728
    }
1729
1730
    public function getOptions()
1731
    {
1732
        if (! $this->options instanceof ModuleOptions) {
1733
            $this->setOptions($this->serviceLocator
1734
                ->get('playgroundgame_module_options'));
1735
        }
1736
1737
        return $this->options;
1738
    }
1739
1740
    /**
1741
     * @param string $str
1742
     */
1743
    public function getExtension($str)
1744
    {
1745
        $i = strrpos($str, '.');
1746
1747
        $l = strlen($str) - $i;
1748
        $ext = substr($str, $i + 1, $l);
1749
1750
        return $ext;
1751
    }
1752
1753
    /**
1754
     * @param string $extension
1755
     */
1756
    public function getSrc($extension, $temp_path)
1757
    {
1758
        $image_src = '';
1759
        switch ($extension) {
1760
            case 'jpg':
1761
                $image_src = imagecreatefromjpeg($temp_path);
1762
                break;
1763
            case 'jpeg':
1764
                $image_src = imagecreatefromjpeg($temp_path);
1765
                break;
1766
            case 'png':
1767
                $image_src = imagecreatefrompng($temp_path);
1768
                break;
1769
            case 'gif':
1770
                $image_src = imagecreatefromgif($temp_path);
1771
                break;
1772
        }
1773
1774
        return $image_src;
1775
    }
1776
1777
    /**
1778
     * @param string $extension
1779
     * @param string $rep
1780
     * @param integer $mini_width
1781
     * @param integer $mini_height
1782
     */
1783
    public function resize($tmp_file, $extension, $rep, $src, $mini_width, $mini_height)
0 ignored issues
show
Unused Code introduced by
The parameter $extension 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...
1784
    {
1785
        list($src_width, $src_height) = getimagesize($tmp_file);
1786
1787
        $ratio_src = $src_width / $src_height;
1788
        $ratio_mini = $mini_width / $mini_height;
1789
1790
        if ($ratio_src >= $ratio_mini) {
1791
            $new_height_mini = $mini_height;
1792
            $new_width_mini = $src_width / ($src_height / $mini_height);
1793
        } else {
1794
            $new_width_mini = $mini_width;
1795
            $new_height_mini = $src_height / ($src_width / $mini_width);
1796
        }
1797
1798
        $new_image_mini = imagecreatetruecolor($mini_width, $mini_height);
1799
1800
        imagecopyresampled(
1801
            $new_image_mini,
1802
            $src,
1803
            0 - ($new_width_mini - $mini_width) / 2,
1804
            0 - ($new_height_mini - $mini_height) / 2,
1805
            0,
1806
            0,
1807
            $new_width_mini,
1808
            $new_height_mini,
1809
            $src_width,
1810
            $src_height
1811
        );
1812
        imagejpeg($new_image_mini, $rep);
1813
1814
        imagedestroy($new_image_mini);
1815
    }
1816
1817
    public function getGameEntity()
1818
    {
1819
        return new \PlaygroundGame\Entity\Game();
1820
    }
1821
1822
    /**
1823
     * @param string $resource
1824
     * @param string $privilege
1825
     */
1826
    public function isAllowed($resource, $privilege = null)
1827
    {
1828
        $auth = $this->serviceLocator->get('BjyAuthorize\Service\Authorize');
1829
1830
        return $auth->isAllowed($resource, $privilege);
1831
    }
1832
1833
    public function getIp()
1834
    {
1835
        $ipaddress = '';
0 ignored issues
show
Unused Code introduced by
$ipaddress 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...
1836
        if (isset($_SERVER['HTTP_CLIENT_IP'])) {
1837
            $ipaddress = $_SERVER['HTTP_CLIENT_IP'];
1838
        } elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
1839
            $ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
1840
        } elseif (isset($_SERVER['HTTP_X_FORWARDED'])) {
1841
            $ipaddress = $_SERVER['HTTP_X_FORWARDED'];
1842
        } elseif (isset($_SERVER['HTTP_FORWARDED_FOR'])) {
1843
            $ipaddress = $_SERVER['HTTP_FORWARDED_FOR'];
1844
        } elseif (isset($_SERVER['HTTP_FORWARDED'])) {
1845
            $ipaddress = $_SERVER['HTTP_FORWARDED'];
1846
        } elseif (isset($_SERVER['REMOTE_ADDR'])) {
1847
            $ipaddress = $_SERVER['REMOTE_ADDR'];
1848
        } else {
1849
            $ipaddress = 'UNKNOWN';
1850
        }
1851
1852
        return $ipaddress;
1853
    }
1854
1855
    public function getGeoloc($ip)
1856
    {
1857
        $geoloc = '';
1858
        try {
1859
            $res = unserialize(file_get_contents('http://www.geoplugin.net/php.gp?ip='.$ip));
1860
            if($res['geoplugin_latitude'] != '') {
1861
                $geoloc = $res['geoplugin_latitude'] . ',' . $res['geoplugin_longitude'];
1862
            }
1863
        } catch (\Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
1864
1865
        } 
1866
1867
        return $geoloc;
1868
    }
1869
1870
    public function getAnonymousId()
1871
    {
1872
        $anonymousId = '';
1873
        if ($_COOKIE && array_key_exists('pg_anonymous', $_COOKIE)) {
1874
            $anonymousId = $_COOKIE['pg_anonymous'];
1875
        }
1876
1877
        return $anonymousId;
1878
    }
1879
1880
    /**
1881
     *
1882
     *
1883
     * This service is ready for all types of games
1884
     *
1885
     * @param array $data
1886
     * @return \PlaygroundGame\Entity\Game
1887
     */
1888 View Code Duplication
    public function createForm(array $data, $game, $form = null)
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...
1889
    {
1890
        $title = '';
1891
        $description = '';
1892
1893
        if ($data['form_jsonified']) {
1894
            $jsonPV = json_decode($data['form_jsonified']);
1895
            foreach ($jsonPV as $element) {
1896
                if ($element->form_properties) {
1897
                    $attributes = $element->form_properties[0];
1898
                    $title = $attributes->title;
1899
                    $description = $attributes->description;
1900
1901
                    break;
1902
                }
1903
            }
1904
        }
1905
        if (! $form) {
1906
            $form = new \PlaygroundGame\Entity\PlayerForm();
1907
        }
1908
        $form->setGame($game);
1909
        $form->setTitle($title);
1910
        $form->setDescription($description);
1911
        $form->setForm($data['form_jsonified']);
1912
        $form->setFormTemplate($data['form_template']);
1913
1914
        $form = $this->getPlayerFormMapper()->insert($form);
1915
1916
        return $form;
1917
    }
1918
1919
    /**
1920
     *  getCSV creates lines of CSV and returns it.
1921
     */
1922
    public function getCSV($array)
1923
    {
1924
        ob_start(); // buffer the output ...
1925
        $out = fopen('php://output', 'w');
1926
        fputcsv($out, array_keys($array[0]), ";");
1927
        foreach ($array as $line) {
1928
            fputcsv($out, $line, ";");
1929
        }
1930
        fclose($out);
1931
        return ob_get_clean(); // ... then return it as a string!
1932
    }
1933
    
1934
    public function getAttributes($attributes)
1935
    {
1936
        $a = array();
1937
1938
        $a['name']          = isset($attributes->name)? $attributes->name : '';
1939
        $a['placeholder']   = isset($attributes->data->placeholder)? $attributes->data->placeholder : '';
1940
        $a['label']         = isset($attributes->data->label)? $attributes->data->label : '';
1941
        $a['required']      = (isset($attributes->data->required) && $attributes->data->required == 'true')?
1942
            true:
1943
            false;
1944
        $a['class']         = isset($attributes->data->class)? $attributes->data->class : '';
1945
        $a['id']            = isset($attributes->data->id)? $attributes->data->id : '';
1946
        $a['lengthMin']     = isset($attributes->data->length)? $attributes->data->length->min : '';
1947
        $a['lengthMax']     = isset($attributes->data->length)? $attributes->data->length->max : '';
1948
        $a['validator']     = isset($attributes->data->validator)? $attributes->data->validator : '';
1949
        $a['innerData']     = isset($attributes->data->innerData)? $attributes->data->innerData : array();
1950
        $a['dropdownValues']= isset($attributes->data->dropdownValues)?
1951
            $attributes->data->dropdownValues :
1952
            array();
1953
        $a['filesizeMin']   = isset($attributes->data->filesize)? $attributes->data->filesize->min : 0;
1954
        $a['filesizeMax']   = isset($attributes->data->filesize)? $attributes->data->filesize->max : 10*1024*1024;
1955
        $a['fileextension']   = isset($attributes->data->fileextension)?
1956
            str_replace(', ', ',', $attributes->data->fileextension) :
1957
            'png,jpg,jpeg,gif';
1958
1959
        // hiddenRequired('fileexcludeextension', '').appendTo(li);
1960
        // hiddenRequired('filemimetype', '').appendTo(li);
1961
        // hiddenRequired('fileexcludemimetype', '').appendTo(li);
1962
        // hiddenRequired('fileexists', '').appendTo(li);
1963
        // hiddenRequired('fileimagesize_minheight', '').appendTo(li);
1964
        // hiddenRequired('fileimagesize_maxheight', '').appendTo(li);
1965
        // hiddenRequired('fileimagesize_minwidth', '').appendTo(li);
1966
        // hiddenRequired('fileimagesize_maxwidth', '').appendTo(li);
1967
        // hiddenRequired('fileiscompressed', '').appendTo(li);
1968
        // hiddenRequired('fileisimage', '').appendTo(li);
1969
        // hiddenRequired('filewordcount_min', '').appendTo(li);
1970
        // hiddenRequired('filewordcount_max', '').appendTo(li);
1971
1972
        return $a;
1973
    }
1974
1975
    /**
1976
     * @param \Zend\InputFilter\InputFilter $inputFilter
1977
     */
1978
    public function decorate($element, $attr, $inputFilter)
1979
    {
1980
        $factory = new InputFactory();
1981
        $element->setAttributes(
1982
            array(
1983
                'placeholder'   => $attr['placeholder'],
1984
                'required'      => $attr['required'],
1985
                'class'         => $attr['class'],
1986
                'id'            => $attr['id']
1987
            )
1988
        );
1989
1990
        $options = array();
1991
        $options['encoding'] = 'UTF-8';
1992
        if ($attr['lengthMin'] && $attr['lengthMin'] > 0) {
1993
            $options['min'] = $attr['lengthMin'];
1994
        }
1995
        if ($attr['lengthMax'] && $attr['lengthMax'] > $attr['lengthMin']) {
1996
            $options['max'] = $attr['lengthMax'];
1997
            $element->setAttribute('maxlength', $attr['lengthMax']);
1998
            $options['messages'] = array(
1999
                \Zend\Validator\StringLength::TOO_LONG => sprintf(
2000
                    $this->serviceLocator->get('MvcTranslator')->translate(
2001
                        'This field contains more than %s characters',
2002
                        'playgroundgame'
2003
                    ),
2004
                    $attr['lengthMax']
2005
                )
2006
            );
2007
        }
2008
2009
        $validators = array(
2010
            array(
2011
                'name'    => 'StringLength',
2012
                'options' => $options,
2013
            ),
2014
        );
2015
        if ($attr['validator']) {
2016
            $regex = "/.*\(([^)]*)\)/";
2017
            preg_match($regex, $attr['validator'], $matches);
2018
            $valArray = array(
2019
                'name' => str_replace(
2020
                    '('.$matches[1].')',
2021
                    '',
2022
                    $attr['validator']
2023
                ),
2024
                'options' => array($matches[1])
2025
            );
2026
            $validators[] = $valArray;
2027
        }
2028
2029
        $inputFilter->add($factory->createInput(array(
2030
            'name'     => $attr['name'],
2031
            'required' => $attr['required'],
2032
            'filters'  => array(
2033
                array('name' => 'StripTags'),
2034
                array('name' => 'StringTrim'),
2035
            ),
2036
            'validators' => $validators,
2037
        )));
2038
2039
        return $element;
2040
    }
2041
    /**
2042
     * Create a ZF2 Form from json data
2043
     * @return Form
2044
     */
2045
    public function createFormFromJson($jsonForm, $id = 'jsonForm')
2046
    {
2047
        $formPV = json_decode($jsonForm);
2048
        
2049
        $form = new Form();
2050
        $form->setAttribute('id', $id);
2051
        $form->setAttribute('enctype', 'multipart/form-data');
2052
        
2053
        $inputFilter = new \Zend\InputFilter\InputFilter();
2054
        $factory = new InputFactory();
2055
        
2056
        foreach ($formPV as $element) {
2057 View Code Duplication
            if (isset($element->line_text)) {
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...
2058
                $attr  = $this->getAttributes($element->line_text[0]);
2059
                $element = new Element\Text($attr['name']);
2060
                $element = $this->decorate($element, $attr, $inputFilter);
2061
                $form->add($element);
2062
            }
2063 View Code Duplication
            if (isset($element->line_password)) {
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...
2064
                $attr = $this->getAttributes($element->line_password[0]);
2065
                $element = new Element\Password($attr['name']);
2066
                $element = $this->decorate($element, $attr, $inputFilter);
2067
                $form->add($element);
2068
            }
2069 View Code Duplication
            if (isset($element->line_hidden)) {
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...
2070
                $attr = $this->getAttributes($element->line_hidden[0]);
2071
                $element = new Element\Hidden($attr['name']);
2072
                $element = $this->decorate($element, $attr, $inputFilter);
2073
                $form->add($element);
2074
            }
2075 View Code Duplication
            if (isset($element->line_email)) {
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...
2076
                $attr = $this->getAttributes($element->line_email[0]);
2077
                $element = new Element\Email($attr['name']);
2078
                $element = $this->decorate($element, $attr, $inputFilter);
2079
                $form->add($element);
2080
            }
2081 View Code Duplication
            if (isset($element->line_radio)) {
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...
2082
                $attr = $this->getAttributes($element->line_radio[0]);
2083
                $element = new Element\Radio($attr['name']);
2084
2085
                $element->setLabel($attr['label']);
2086
                $element->setAttributes(
2087
                    array(
2088
                        'name'      => $attr['name'],
2089
                        'required'  => $attr['required'],
2090
                        'allowEmpty'=> !$attr['required'],
2091
                        'class'     => $attr['class'],
2092
                        'id'        => $attr['id']
2093
                    )
2094
                );
2095
                $values = array();
2096
                foreach ($attr['innerData'] as $value) {
2097
                    $values[] = $value->label;
2098
                }
2099
                $element->setValueOptions($values);
2100
        
2101
                $options = array();
2102
                $options['encoding'] = 'UTF-8';
2103
                $options['disable_inarray_validator'] = true;
2104
        
2105
                $element->setOptions($options);
2106
        
2107
                $form->add($element);
2108
        
2109
                $inputFilter->add($factory->createInput(array(
2110
                    'name'     => $attr['name'],
2111
                    'required' => $attr['required'],
2112
                    'allowEmpty' => !$attr['required'],
2113
                )));
2114
            }
2115 View Code Duplication
            if (isset($element->line_checkbox)) {
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...
2116
                $attr = $this->getAttributes($element->line_checkbox[0]);
2117
                $element = new Element\MultiCheckbox($attr['name']);
2118
        
2119
                $element->setLabel($attr['label']);
2120
                $element->setAttributes(
2121
                    array(
2122
                        'name'      => $attr['name'],
2123
                        'required'  => $attr['required'],
2124
                        'allowEmpty'=> !$attr['required'],
2125
                        'class'     => $attr['class'],
2126
                        'id'        => $attr['id']
2127
                    )
2128
                );
2129
2130
                $values = array();
2131
                foreach ($attr['innerData'] as $value) {
2132
                    $values[] = $value->label;
2133
                }
2134
                $element->setValueOptions($values);
2135
                $form->add($element);
2136
        
2137
                $options = array();
2138
                $options['encoding'] = 'UTF-8';
2139
                $options['disable_inarray_validator'] = true;
2140
        
2141
                $element->setOptions($options);
2142
        
2143
                $inputFilter->add($factory->createInput(array(
2144
                    'name'      => $attr['name'],
2145
                    'required'  => $attr['required'],
2146
                    'allowEmpty'=> !$attr['required'],
2147
                )));
2148
            }
2149 View Code Duplication
            if (isset($element->line_dropdown)) {
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...
2150
                $attr = $this->getAttributes($element->line_dropdown[0]);
2151
                $element = new Element\Select($attr['name']);
2152
2153
                $element->setLabel($attr['label']);
2154
                $element->setAttributes(
2155
                    array(
2156
                        'name'      => $attr['name'],
2157
                        'required'  => $attr['required'],
2158
                        'allowEmpty'=> !$attr['required'],
2159
                        'class'     => $attr['class'],
2160
                        'id'        => $attr['id']
2161
                    )
2162
                );
2163
                $values = array();
2164
                foreach ($attr['dropdownValues'] as $value) {
2165
                    $values[] = $value->dropdown_label;
2166
                }
2167
                $element->setValueOptions($values);
2168
                $form->add($element);
2169
        
2170
                $options = array();
2171
                $options['encoding'] = 'UTF-8';
2172
                $options['disable_inarray_validator'] = true;
2173
        
2174
                $element->setOptions($options);
2175
        
2176
                $inputFilter->add($factory->createInput(array(
2177
                    'name'     => $attr['name'],
2178
                    'required' => $attr['required'],
2179
                    'allowEmpty' => !$attr['required'],
2180
                )));
2181
            }
2182 View Code Duplication
            if (isset($element->line_paragraph)) {
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...
2183
                $attr = $this->getAttributes($element->line_paragraph[0]);
2184
                $element = new Element\Textarea($attr['name']);
2185
                $element = $this->decorate($element, $attr, $inputFilter);
2186
                $form->add($element);
2187
            }
2188
            if (isset($element->line_upload)) {
2189
                $attr = $this->getAttributes($element->line_upload[0]);
2190
                $element = new Element\File($attr['name']);
2191
2192
                $element->setLabel($attr['label']);
2193
                $element->setAttributes(
2194
                    array(
2195
                        'name'      => $attr['name'],
2196
                        'required'  => $attr['required'],
2197
                        'class'     => $attr['class'],
2198
                        'id'        => $attr['id']
2199
                    )
2200
                );
2201
                $form->add($element);
2202
2203
                $inputFilter->add($factory->createInput(array(
2204
                    'name'     => $attr['name'],
2205
                    'required' => $attr['required'],
2206
                    'validators' => array(
2207
                        array(
2208
                            'name' => '\Zend\Validator\File\Size',
2209
                            'options' => array('min' => $attr['filesizeMin'], 'max' => $attr['filesizeMax'])
2210
                        ),
2211
                        array(
2212
                            'name' => '\Zend\Validator\File\Extension',
2213
                            'options'  => array(
2214
                                $attr['fileextension'],
2215
                                'messages' => array(
2216
                                    \Zend\Validator\File\Extension::FALSE_EXTENSION =>'Veuillez télécharger un fichier avec la bonne extension'
2217
                                )
2218
                            )
2219
                        ),
2220
                    ),
2221
                )));
2222
            }
2223
        }
2224
        
2225
        $form->setInputFilter($inputFilter);
2226
        
2227
        return $form;
2228
    }
2229
2230
    /**
2231
     * Send mail for winner and/or loser
2232
     * @param \PlaygroundGame\Entity\Game $game
2233
     * @param \PlaygroundUser\Entity\User $user
2234
     * @param \PlaygroundGame\Entity\Entry $lastEntry
2235
     * @param \PlaygroundGame\Entity\Prize $prize
2236
     */
2237
    public function sendMail($game, $user, $lastEntry, $prize = null)
2238
    {
2239 View Code Duplication
        if (($user || ($game->getAnonymousAllowed() && $game->getAnonymousIdentifier())) &&
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...
2240
            $game->getMailWinner() &&
2241
            $lastEntry->getWinner()
2242
        ) {
2243
            $this->sendResultMail($game, $user, $lastEntry, 'winner', $prize);
2244
        }
2245
2246 View Code Duplication
        if (($user || ($game->getAnonymousAllowed() && $game->getAnonymousIdentifier())) &&
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...
2247
            $game->getMailLooser() &&
2248
            !$lastEntry->getWinner()
2249
        ) {
2250
            $this->sendResultMail($game, $user, $lastEntry, 'looser');
2251
        }
2252
2253
        if (($user || ($game->getAnonymousAllowed() && $game->getAnonymousIdentifier())) &&
2254
            $game->getMailEntry()
2255
        ) {
2256
            $this->sendResultMail($game, $user, $lastEntry);
2257
        }
2258
    }
2259
2260
    public function getPlayerFormMapper()
2261
    {
2262
        if (null === $this->playerformMapper) {
2263
            $this->playerformMapper = $this->serviceLocator->get('playgroundgame_playerform_mapper');
2264
        }
2265
2266
        return $this->playerformMapper;
2267
    }
2268
2269
    public function setPlayerFormMapper($playerformMapper)
2270
    {
2271
        $this->playerformMapper = $playerformMapper;
2272
2273
        return $this;
2274
    }
2275
2276
    public function getInvitationMapper()
2277
    {
2278
        if (null === $this->invitationMapper) {
2279
            $this->invitationMapper = $this->serviceLocator->get('playgroundgame_invitation_mapper');
2280
        }
2281
2282
        return $this->invitationMapper;
2283
    }
2284
2285
    public function setInvitationMapper($invitationMapper)
2286
    {
2287
        $this->invitationMapper = $invitationMapper;
2288
2289
        return $this;
2290
    }
2291
2292
    /**
2293
     * getUserMapper
2294
     *
2295
     * @return UserMapperInterface
2296
     */
2297
    public function getUserMapper()
2298
    {
2299
        if (null === $this->userMapper) {
2300
            $this->userMapper = $this->serviceLocator->get('zfcuser_user_mapper');
2301
        }
2302
2303
        return $this->userMapper;
2304
    }
2305
2306
    /**
2307
     * getUserMapper
2308
     *
2309
     * @return ServiceManager
2310
     */
2311
    public function getServiceManager()
2312
    {
2313
        return $this->serviceLocator;
2314
    }
2315
}
2316