Completed
Pull Request — master (#249)
by greg
04:18
created

Quiz::getQuizQuestionMapper()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 8
rs 9.4286
cc 2
eloc 4
nc 2
nop 0
1
<?php
2
3
namespace PlaygroundGame\Service;
4
5
use PlaygroundGame\Entity\QuizReply;
6
use PlaygroundGame\Entity\QuizReplyAnswer;
7
use Zend\ServiceManager\ServiceManagerAwareInterface;
8
use PlaygroundGame\Mapper\GameInterface as GameMapperInterface;
9
use Zend\Stdlib\ErrorHandler;
10
11
class Quiz extends Game implements ServiceManagerAwareInterface
12
{
13
    /**
14
     * @var QuizMapperInterface
15
     */
16
    protected $quizMapper;
17
18
    /**
19
     * @var QuizAnswerMapperInterface
20
     */
21
    protected $quizAnswerMapper;
22
23
    /**
24
     * @var QuizQuestionMapperInterface
25
     */
26
    protected $quizQuestionMapper;
27
28
    /**
29
     * @var QuizReplyMapperInterface
30
     */
31
    protected $quizReplyMapper;
32
33
    /**
34
     * @var quizReplyAnswerMapper
35
     */
36
    protected $quizReplyAnswerMapper;
37
    /**
38
     *
39
     *
40
     * @param  array                  $data
41
     * @return \PlaygroundGame\Entity\Game
42
     */
43
    public function createQuestion(array $data)
44
    {
45
        $path = $this->getOptions()->getMediaPath() . DIRECTORY_SEPARATOR;
46
        $media_url = $this->getOptions()->getMediaUrl() . '/';
47
48
        $question  = new \PlaygroundGame\Entity\QuizQuestion();
49
        $form  = $this->getServiceManager()->get('playgroundgame_quizquestion_form');
50
        $form->bind($question);
51
        $form->setData($data);
52
53
        $quiz = $this->getGameMapper()->findById($data['quiz_id']);
54
        if (!$form->isValid()) {
55
            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\Quiz::createQuestion 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...
56
        }
57
58
        $question->setQuiz($quiz);
59
60
        // If question is a prediction, no need to calculate max good answers
61
        if (!$question->getPrediction()) {
62
            // Max points and correct answers calculation for the question
63
            if (!$question = $this->calculateMaxAnswersQuestion($question)) {
64
                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\Quiz::createQuestion 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...
65
            }
66
        }
67
68
        // Max points and correct answers recalculation for the quiz
69
        $quiz = $this->calculateMaxAnswersQuiz($question->getQuiz());
70
71
        $this->getEventManager()->trigger(__FUNCTION__, $this, array('game' => $question, 'data' => $data));
72
        $this->getQuizQuestionMapper()->insert($question);
73
        $this->getEventManager()->trigger(__FUNCTION__.'.post', $this, array('game' => $question, 'data' => $data));
74
75 View Code Duplication
        if (!empty($data['upload_image']['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...
76
            ErrorHandler::start();
77
            $data['upload_image']['name'] = $this->fileNewname(
78
                $path,
79
                $question->getId() . "-" . $data['upload_image']['name']
80
            );
81
            move_uploaded_file($data['upload_image']['tmp_name'], $path . $data['upload_image']['name']);
82
            $question->setImage($media_url . $data['upload_image']['name']);
83
            ErrorHandler::stop(true);
84
        }
85
86
        $this->getQuizQuestionMapper()->update($question);
87
        $this->getQuizMapper()->update($quiz);
88
89
        return $question;
90
    }
91
92
    /**
93
     * @param  array                  $data
94
     * @return \PlaygroundGame\Entity\Game
95
     */
96
    public function updateQuestion(array $data, $question)
97
    {
98
        $path = $this->getOptions()->getMediaPath() . DIRECTORY_SEPARATOR;
99
        $media_url = $this->getOptions()->getMediaUrl() . '/';
100
101
        $form  = $this->getServiceManager()->get('playgroundgame_quizquestion_form');
102
        $form->bind($question);
103
        $form->setData($data);
104
105
        if (!$form->isValid()) {
106
            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\Quiz::updateQuestion 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...
107
        }
108
109
        // If question is a prediction, no need to calculate max good answers
110
        if (!$question->getPrediction()) {
111
            // Max points and correct answers calculation for the question
112
            if (!$question = $this->calculateMaxAnswersQuestion($question)) {
113
                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\Quiz::updateQuestion 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...
114
            }
115
        }
116
117 View Code Duplication
        if (!empty($data['upload_image']['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...
118
            ErrorHandler::start();
119
            $data['upload_image']['name'] = $this->fileNewname($path, $question->getId() . "-" . $data['upload_image']['name']);
120
            move_uploaded_file($data['upload_image']['tmp_name'], $path . $data['upload_image']['name']);
121
            $question->setImage($media_url . $data['upload_image']['name']);
122
            ErrorHandler::stop(true);
123
        }
124
125 View Code Duplication
        if (isset($data['delete_image']) && empty($data['upload_image']['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...
126
            ErrorHandler::start();
127
            $image = $question->getImage();
128
            $image = str_replace($media_url, '', $image);
129
            if (file_exists($path .$image)) {
130
                unlink($path .$image);
131
            }
132
            $question->setImage(null);
133
            ErrorHandler::stop(true);
134
        }
135
        
136
        $i = 0;
137
        foreach ($question->getAnswers() as $answer) {
138
            if (!empty($data['answers'][$i]['upload_image']['tmp_name'])) {
139
                ErrorHandler::start();
140
                $data['answers'][$i]['upload_image']['name'] = $this->fileNewname(
141
                    $path,
142
                    $question->getId() . "-" . $data['answers'][$i]['upload_image']['name']
143
                );
144
                move_uploaded_file(
145
                    $data['answers'][$i]['upload_image']['tmp_name'],
146
                    $path . $data['answers'][$i]['upload_image']['name']
147
                );
148
                $answer->setImage($media_url . $data['answers'][$i]['upload_image']['name']);
149
                ErrorHandler::stop(true);
150
            }
151
            
152
            /*if(isset($data['delete_image']) && empty($data['upload_image']['tmp_name'])) {
153
                ErrorHandler::start();
154
                $image = $question->getImage();
155
                $image = str_replace($media_url, '', $image);
156
                unlink($path .$image);
157
                $question->setImage(null);
158
                ErrorHandler::stop(true);
159
            }*/
160
            
161
            $i++;
162
        }
163
164
        // Max points and correct answers recalculation for the quiz
165
        $quiz = $this->calculateMaxAnswersQuiz($question->getQuiz());
166
167
        // If the question was a pronostic, I update entries with the results !
168
        if ($question->getPrediction()) {
169
            // je recherche toutes les participations au jeu
170
            $entries = $this->getEntryMapper()->findByGameId($question->getQuiz());
171
172
            $answers = $question->getAnswers();
173
174
            $answersarray = array();
175
            foreach ($answers as $answer) {
176
                $answersarray[$answer->getId()] = $answer;
177
            }
178
179
            // I update all answers with points and correctness
180
            // Refactorer findByEntryAndQuestion pour qu'elle fonctionne avec QuizReplyAnswer
181
            /**
182
             * 1. Je recherche $this->getQuizReplyMapper()->findByEntry($entry)
183
             * 2. Pour chaque entrée trouvée, je recherche $this->getQuizReplyAnswerMapper()->findByReplyAndQuestion($reply, $question->getId())
184
             * 3. Je mets à jour reply avec le nb de bonnes réponses
185
             * 4. Je trigger une story ?
186
             */
187
            foreach ($entries as $entry) {
188
                $quizReplies = $this->getQuizReplyMapper()->findByEntry($entry);
189
                if ($quizReplies) {
190
                    foreach ($quizReplies as $reply) {
191
                        $quizReplyAnswers = $this->getQuizReplyAnswerMapper()->findByReplyAndQuestion(
192
                            $reply,
193
                            $question->getId()
194
                        );
195
                        $quizPoints = 0;
196
                        $quizCorrectAnswers = 0;
197
                        if ($quizReplyAnswers) {
198
                            foreach ($quizReplyAnswers as $quizReplyAnswer) {
199
                                if (2 != $question->getType()) {
200
                                    if ($answersarray[$quizReplyAnswer->getAnswerId()]) {
201
                                        $updatedAnswer = $answersarray[$quizReplyAnswer->getAnswerId()];
202
                                        $quizReplyAnswer->setPoints($updatedAnswer->getPoints());
203
                                        $quizPoints += $updatedAnswer->getPoints();
204
                                        $quizReplyAnswer->setCorrect($updatedAnswer->getCorrect());
205
                                        $quizCorrectAnswers += $updatedAnswer->getCorrect();
206
                                        $quizReplyAnswer = $this->getQuizReplyAnswerMapper()->update($quizReplyAnswer);
207
                                    }
208
                                } else {
209
                                    // question is a textarea
210
                                    // search for a matching answer
211
                                    foreach ($answers as $answer) {
212
                                        if (trim(strip_tags($answer->getAnswer())) == trim(strip_tags($quizReplyAnswer->getAnswer()))) {
213
                                            $quizReplyAnswer->setPoints($answer->getPoints());
214
                                            $quizPoints += $answer->getPoints();
215
                                            $quizReplyAnswer->setCorrect($answer->getCorrect());
216
                                            $quizCorrectAnswers += $answer->getCorrect();
217
                                            $quizReplyAnswer = $this->getQuizReplyAnswerMapper()->update($quizReplyAnswer);
218
                                            break;
219
                                        }
220
                                    }
221
                                }
222
                            }
223
                        }
224
                    }
225
                }
226
                $winner = $this->isWinner($quiz, $quizCorrectAnswers);
0 ignored issues
show
Bug introduced by
The variable $quizCorrectAnswers 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...
227
                $entry->setWinner($winner);
228
                $entry->setPoints($quizPoints);
0 ignored issues
show
Bug introduced by
The variable $quizPoints 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...
229
                $entry->setActive(false);
230
                $entry = $this->getEntryMapper()->update($entry);
231
            }
232
233
            $this->getEventManager()->trigger(
234
                __FUNCTION__.'.prediction',
235
                $this,
236
                array('question' => $question, 'data' => $data)
237
            );
238
        }
239
240
        $this->getEventManager()->trigger(
241
            __FUNCTION__,
242
            $this,
243
            array('question' => $question, 'data' => $data)
244
        );
245
        $this->getQuizQuestionMapper()->update($question);
246
        $this->getEventManager()->trigger(
247
            __FUNCTION__.'.post',
248
            $this,
249
            array('question' => $question, 'data' => $data)
250
        );
251
252
        $this->getQuizMapper()->update($quiz);
253
254
        return $question;
255
    }
256
257
    public function calculateMaxAnswersQuestion($question)
258
    {
259
        $question_max_points = 0;
260
        $question_max_correct_answers = 0;
261
        // Closed question : Only one answer allowed
262
        if ($question->getType() == 0) {
263
            foreach ($question->getAnswers() as $answer) {
264
                if ($answer->getPoints() > $question_max_points) {
265
                    $question_max_points = $answer->getPoints();
266
                }
267
                if ($answer->getCorrect() && $question_max_correct_answers==0) {
268
                    $question_max_correct_answers=1;
269
                }
270
            }
271
            if ($question_max_correct_answers == 0) {
272
                return false;
273
            }
274
        // Closed question : Many answers allowed
275
        } elseif ($question->getType() == 1) {
276
            foreach ($question->getAnswers() as $answer) {
277
                $question_max_points += $answer->getPoints();
278
279
                if ($answer->getCorrect()) {
280
                    ++$question_max_correct_answers;
281
                }
282
            }
283
            if ($question_max_correct_answers == 0) {
284
                return false;
285
            }
286
        // Not a question : A textarea to fill in
287
        } elseif ($question->getType() == 2) {
288
            $question_max_correct_answers = 0;
289
        }
290
291
        $question->setMaxPoints($question_max_points);
292
        $question->setMaxCorrectAnswers($question_max_correct_answers);
293
294
        return $question;
295
    }
296
297
    public function calculateMaxAnswersQuiz($quiz)
298
    {
299
        $question_max_points = 0;
300
        $question_max_correct_answers = 0;
301
        foreach ($quiz->getQuestions() as $question) {
302
            $question_max_points += $question->getMaxPoints();
303
            $question_max_correct_answers += $question->getMaxCorrectAnswers();
304
        }
305
        $quiz->setMaxPoints($question_max_points);
306
        $quiz->setMaxCorrectAnswers($question_max_correct_answers);
307
308
        return $quiz;
309
    }
310
311 View Code Duplication
    public function getNumberCorrectAnswersQuiz($user, $count = 'count')
0 ignored issues
show
Unused Code introduced by
The parameter $count 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...
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...
312
    {
313
        $em = $this->getServiceManager()->get('doctrine.entitymanager.orm_default');
314
315
        $query = $em->createQuery(
316
            "SELECT COUNT(e.id) FROM PlaygroundGame\Entity\Entry e, PlaygroundGame\Entity\Game g
317
                WHERE e.user = :user
318
                AND g.classType = 'quiz'
319
                AND e.points > 0"
320
        );
321
        $query->setParameter('user', $user);
322
        $number = $query->getSingleScalarResult();
323
324
        return $number;
325
    }
326
327
    public function createQuizReply($data, $game, $user)
328
    {
329
        // Si mon nb de participation est < au nb autorisé, j'ajoute une entry + reponses au quiz et points
330
        $quizReplyMapper = $this->getQuizReplyMapper();
331
        $entryMapper = $this->getEntryMapper();
332
        $entry = $this->findLastActiveEntry($game, $user);
333
334
        if (!$entry) {
335
            return false;
336
        }
337
338
        $quizPoints          = 0;
339
        $quizCorrectAnswers  = 0;
340
        $maxCorrectAnswers = $game->getMaxCorrectAnswers();
341
        $totalQuestions = 0;
342
343
        $quizReply = new QuizReply();
344
345
        foreach ($data as $group) {
346
            foreach ($group as $q => $a) {
347
                if (strlen($q) > 5 && strpos($q, '-data', strlen($q) - 5) !== false) {
348
                    continue; // answer data is processed below
349
                }
350
                $question = $this->getQuizQuestionMapper()->findById((int) str_replace('q', '', $q));
351
                ++$totalQuestions;
352
                if (is_array($a)) {
353
                    foreach ($a as $k => $answer_id) {
354
                        $answer = $this->getQuizAnswerMapper()->findById($answer_id);
355 View Code Duplication
                        if ($answer) {
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...
356
                            $quizReplyAnswer = new QuizReplyAnswer();
357
                            $quizReplyAnswer->setAnswer($answer->getAnswer());
358
                            $quizReplyAnswer->setAnswerId($answer_id);
359
                            $quizReplyAnswer->setQuestion($question->getQuestion());
360
                            $quizReplyAnswer->setQuestionId($question->getId());
361
                            $quizReplyAnswer->setPoints($answer->getPoints());
362
                            $quizReplyAnswer->setCorrect($answer->getCorrect());
363
364
                            $quizReply->addAnswer($quizReplyAnswer);
365
                            $quizPoints += $answer->getPoints();
366
                            $quizCorrectAnswers += $answer->getCorrect();
367
368
                            if (isset($group[$q.'-'.$answer_id.'-data'])) {
369
                                $quizReplyAnswer->setAnswerData($group[$q.'-'.$answer_id.'-data']);
370
                            }
371
                        }
372
                    }
373
                } elseif ($question->getType() == 0 || $question->getType() == 1) {
374
                    ++$totalQuestions;
375
                    $answer = $this->getQuizAnswerMapper()->findById($a);
376 View Code Duplication
                    if ($answer) {
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...
377
                        $quizReplyAnswer = new QuizReplyAnswer();
378
                        $quizReplyAnswer->setAnswer($answer->getAnswer());
379
                        $quizReplyAnswer->setAnswerId($a);
380
                        $quizReplyAnswer->setQuestion($question->getQuestion());
381
                        $quizReplyAnswer->setQuestionId($question->getId());
382
                        $quizReplyAnswer->setPoints($answer->getPoints());
383
                        $quizReplyAnswer->setCorrect($answer->getCorrect());
384
385
                        $quizReply->addAnswer($quizReplyAnswer);
386
                        $quizPoints += $answer->getPoints();
387
                        $quizCorrectAnswers += $answer->getCorrect();
388
                        if (isset($group[$q.'-'.$a.'-data'])) {
389
                            $quizReplyAnswer->setAnswerData($group[$q.'-'.$a.'-data']);
390
                        }
391
                    }
392
                } elseif ($question->getType() == 2) {
393
                    ++$totalQuestions;
394
                    $quizReplyAnswer = new QuizReplyAnswer();
395
                    
396
                    $quizReplyAnswer->setAnswer($a);
397
                    $quizReplyAnswer->setAnswerId(0);
0 ignored issues
show
Documentation introduced by
0 is of type integer, but the function expects a object<PlaygroundGame\Entity\unknown_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...
398
                    $quizReplyAnswer->setQuestion($question->getQuestion());
399
                    $quizReplyAnswer->setQuestionId($question->getId());
400
                    $quizReplyAnswer->setPoints(0);
0 ignored issues
show
Documentation introduced by
0 is of type integer, 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...
401
                    $quizReplyAnswer->setCorrect(0);
0 ignored issues
show
Documentation introduced by
0 is of type integer, but the function expects a object<PlaygroundGame\Entity\unknown_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...
402
403
                    $quizReply->addAnswer($quizReplyAnswer);
404
                    $quizPoints += 0;
405
                    $quizCorrectAnswers += 0;
406
                    $qAnswers = $question->getAnswers();
407
                    foreach ($qAnswers as $qAnswer) {
408
                        if (trim(strip_tags($a)) == trim(strip_tags($qAnswer->getAnswer()))) {
409
                            $quizReplyAnswer->setPoints($qAnswer->getPoints());
410
                            $quizPoints += $qAnswer->getPoints();
411
                            $quizReplyAnswer->setCorrect($qAnswer->getCorrect());
412
                            $quizCorrectAnswers += $qAnswer->getCorrect();
413
                            break;
414
                        }
415
                    }
416
417
                    if (isset($group[$q.'-'.$a.'-data'])) {
418
                        $quizReplyAnswer->setAnswerData($group[$q.'-'.$a.'-data']);
419
                    }
420
                }
421
            }
422
        }
423
424
        $winner = $this->isWinner($game, $quizCorrectAnswers);
425
426
        $entry->setWinner($winner);
0 ignored issues
show
Bug introduced by
The method setWinner cannot be called on $entry (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
427
        // Every winning participation is eligible to draw
428
        // Make this modifiable in the admin (choose who can participate to draw)
429
        $entry->setDrawable($winner);
0 ignored issues
show
Bug introduced by
The method setDrawable cannot be called on $entry (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
430
        $entry->setPoints($quizPoints);
0 ignored issues
show
Bug introduced by
The method setPoints cannot be called on $entry (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
431
        $entry->setActive(false);
0 ignored issues
show
Bug introduced by
The method setActive cannot be called on $entry (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
432
        $entry = $entryMapper->update($entry);
433
434
        $quizReply->setEntry($entry);
435
        $quizReply->setTotalCorrectAnswers($quizCorrectAnswers);
436
        $quizReply->setMaxCorrectAnswers($maxCorrectAnswers);
437
        $quizReply->setTotalQuestions($totalQuestions);
438
439
        $quizReplyMapper->insert($quizReply);
440
441
        $this->getEventManager()->trigger(
442
            'complete_quiz.post',
443
            $this,
444
            array('user' => $user, 'entry' => $entry, 'reply' => $quizReply, 'game' => $game)
445
        );
446
447
        return $entry;
448
    }
449
450
    public function isWinner($game, $quizCorrectAnswers = 0)
451
    {
452
        // Pour déterminer le gagnant, je regarde le nombre max de reponses correctes possibles
453
        // dans le jeu, puis je calcule le ratio de bonnes réponses et le compare aux conditions
454
        // de victoire
455
        $winner = false;
0 ignored issues
show
Unused Code introduced by
$winner 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...
456
        $maxCorrectAnswers = $game->getMaxCorrectAnswers();
457
        if ($maxCorrectAnswers > 0) {
458
            $ratioCorrectAnswers = ($quizCorrectAnswers / $maxCorrectAnswers) * 100;
459
        } elseif ($game->getVictoryConditions() > 0) {
460
            // In the case I have a pronostic game for example
461
            $ratioCorrectAnswers = 0;
462
        } else {
463
            // In the case I want everybody to win
464
            $ratioCorrectAnswers = 100;
465
        }
466
467
        $winner = false;
468
        if ($game->getVictoryConditions() >= 0) {
469
            if ($ratioCorrectAnswers >= $game->getVictoryConditions()) {
470
                $winner = true;
471
            }
472
        }
473
        return $winner;
474
    }
475
476
    public function getEntriesHeader($game)
477
    {
478
        $header = parent::getEntriesHeader($game);
479
        $header['totalCorrectAnswers'] = 1;
480
481
        return $header;
482
    }
483
484 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...
485
    {
486
        $em = $this->getServiceManager()->get('doctrine.entitymanager.orm_default');
487
488
        $qb = $em->createQueryBuilder();
489
        $qb->select('
490
            r.id,
491
            u.username,
492
            u.title,
493
            u.firstname,
494
            u.lastname,
495
            u.email,
496
            u.optin,
497
            u.optinPartner,
498
            u.address,
499
            u.address2,
500
            u.postalCode,
501
            u.city,
502
            u.telephone,
503
            u.mobile,
504
            u.created_at,
505
            u.dob,
506
            e.winner,
507
            e.socialShares,
508
            e.playerData,
509
            e.updated_at,
510
            r.totalCorrectAnswers
511
            ')
512
            ->from('PlaygroundGame\Entity\QuizReply', 'r')
513
            ->innerJoin('r.entry', 'e')
514
            ->leftJoin('e.user', 'u')
515
            ->where($qb->expr()->eq('e.game', ':game'));
516
        
517
        $qb->setParameter('game', $game);
518
519
        return $qb->getQuery();
520
    }
521
522
    public function getGameEntity()
523
    {
524
        return new \PlaygroundGame\Entity\Quiz;
525
    }
526
527
    /**
528
     * getQuizMapper
529
     *
530
     * @return QuizMapperInterface
531
     */
532
    public function getQuizMapper()
533
    {
534
        if (null === $this->quizMapper) {
535
            $this->quizMapper = $this->getServiceManager()->get('playgroundgame_quiz_mapper');
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->getServiceManager...roundgame_quiz_mapper') can also be of type array. However, the property $quizMapper is declared as type object<PlaygroundGame\Se...ce\QuizMapperInterface>. Maybe add an additional type check?

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

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

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

class Id
{
    public $id;

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

}

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

$account_id = false;

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

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
536
        }
537
538
        return $this->quizMapper;
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->quizMapper; of type object|array adds the type array to the return on line 538 which is incompatible with the return type documented by PlaygroundGame\Service\Quiz::getQuizMapper of type PlaygroundGame\Service\QuizMapperInterface.
Loading history...
539
    }
540
541
    /**
542
     * setQuizMapper
543
     *
544
     * @param  QuizMapperInterface $quizMapper
545
     * @return Game
546
     */
547
    public function setQuizMapper(GameMapperInterface $quizMapper)
548
    {
549
        $this->quizMapper = $quizMapper;
0 ignored issues
show
Documentation Bug introduced by
It seems like $quizMapper of type object<PlaygroundGame\Mapper\GameInterface> is incompatible with the declared type object<PlaygroundGame\Se...ce\QuizMapperInterface> of property $quizMapper.

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...
550
551
        return $this;
552
    }
553
554
    /**
555
     * getQuizQuestionMapper
556
     *
557
     * @return QuizQuestionMapperInterface
558
     */
559
    public function getQuizQuestionMapper()
560
    {
561
        if (null === $this->quizQuestionMapper) {
562
            $this->quizQuestionMapper = $this->getServiceManager()->get('playgroundgame_quizquestion_mapper');
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->getServiceManager...e_quizquestion_mapper') can also be of type array. However, the property $quizQuestionMapper is declared as type object<PlaygroundGame\Se...uestionMapperInterface>. Maybe add an additional type check?

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

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

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

class Id
{
    public $id;

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

}

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

$account_id = false;

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

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
563
        }
564
565
        return $this->quizQuestionMapper;
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->quizQuestionMapper; of type object|array adds the type array to the return on line 565 which is incompatible with the return type documented by PlaygroundGame\Service\Quiz::getQuizQuestionMapper of type PlaygroundGame\Service\QuizQuestionMapperInterface.
Loading history...
566
    }
567
568
    /**
569
     * setQuizQuestionMapper
570
     *
571
     * @param  QuizQuestionMapperInterface $quizquestionMapper
572
     * @return Quiz
573
     */
574
    public function setQuizQuestionMapper($quizquestionMapper)
575
    {
576
        $this->quizQuestionMapper = $quizquestionMapper;
577
578
        return $this;
579
    }
580
581
    /**
582
     * setQuizAnswerMapper
583
     *
584
     * @param  QuizAnswerMapperInterface $quizAnswerMapper
585
     * @return Quiz
586
     */
587
    public function setQuizAnswerMapper($quizAnswerMapper)
588
    {
589
        $this->quizAnswerMapper = $quizAnswerMapper;
590
591
        return $this;
592
    }
593
594
    /**
595
     * getQuizAnswerMapper
596
     *
597
     * @return QuizAnswerMapperInterface
598
     */
599
    public function getQuizAnswerMapper()
600
    {
601
        if (null === $this->quizAnswerMapper) {
602
            $this->quizAnswerMapper = $this->getServiceManager()->get('playgroundgame_quizanswer_mapper');
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->getServiceManager...ame_quizanswer_mapper') can also be of type array. However, the property $quizAnswerMapper is declared as type object<PlaygroundGame\Se...zAnswerMapperInterface>. Maybe add an additional type check?

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

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

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

class Id
{
    public $id;

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

}

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

$account_id = false;

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

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
603
        }
604
605
        return $this->quizAnswerMapper;
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->quizAnswerMapper; of type object|array adds the type array to the return on line 605 which is incompatible with the return type documented by PlaygroundGame\Service\Quiz::getQuizAnswerMapper of type PlaygroundGame\Service\QuizAnswerMapperInterface.
Loading history...
606
    }
607
608
    /**
609
     * getQuizReplyMapper
610
     *
611
     * @return QuizReplyMapperInterface
612
     */
613
    public function getQuizReplyMapper()
614
    {
615
        if (null === $this->quizReplyMapper) {
616
            $this->quizReplyMapper = $this->getServiceManager()->get('playgroundgame_quizreply_mapper');
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->getServiceManager...game_quizreply_mapper') can also be of type array. However, the property $quizReplyMapper is declared as type object<PlaygroundGame\Se...izReplyMapperInterface>. Maybe add an additional type check?

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

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

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

class Id
{
    public $id;

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

}

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

$account_id = false;

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

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
617
        }
618
619
        return $this->quizReplyMapper;
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->quizReplyMapper; of type object|array adds the type array to the return on line 619 which is incompatible with the return type documented by PlaygroundGame\Service\Quiz::getQuizReplyMapper of type PlaygroundGame\Service\QuizReplyMapperInterface.
Loading history...
620
    }
621
622
    /**
623
     * setQuizReplyMapper
624
     *
625
     * @param  QuizReplyMapperInterface $quizreplyMapper
626
     * @return Quiz
627
     */
628
    public function setQuizReplyMapper($quizreplyMapper)
629
    {
630
        $this->quizReplyMapper = $quizreplyMapper;
631
632
        return $this;
633
    }
634
635
    /**
636
     * getQuizReplyAnswerMapper
637
     *
638
     * @return QuizReplyAnswerMapper
639
     */
640
    public function getQuizReplyAnswerMapper()
641
    {
642
        if (null === $this->quizReplyAnswerMapper) {
643
            $this->quizReplyAnswerMapper = $this->getServiceManager()->get('playgroundgame_quizreplyanswer_mapper');
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->getServiceManager...uizreplyanswer_mapper') can also be of type array. However, the property $quizReplyAnswerMapper is declared as type object<PlaygroundGame\Se...\QuizReplyAnswerMapper>. Maybe add an additional type check?

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

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

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

class Id
{
    public $id;

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

}

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

$account_id = false;

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

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
644
        }
645
646
        return $this->quizReplyAnswerMapper;
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->quizReplyAnswerMapper; of type object|array adds the type array to the return on line 646 which is incompatible with the return type documented by PlaygroundGame\Service\Q...etQuizReplyAnswerMapper of type PlaygroundGame\Service\QuizReplyAnswerMapper.
Loading history...
647
    }
648
649
     /**
650
     * setQuizReplyAnswerMapper
651
     *
652
     * @param  QuizReplyAnswerMapper $quizReplyAnswerMapper
653
     * @return Quiz
654
     */
655
    public function setQuizReplyAnswerMapper($quizReplyAnswerMapper)
656
    {
657
        $this->quizReplyAnswerMapper = $quizReplyAnswerMapper;
658
659
        return $this;
660
    }
661
}
662