Completed
Push — develop ( 54744b...29957b )
by greg
03:57
created

Quiz::getEntriesHeader()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
rs 9.4286
cc 1
eloc 4
nc 1
nop 1
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($path, $question->getId() . "-" . $data['upload_image']['name']);
78
            move_uploaded_file($data['upload_image']['tmp_name'], $path . $data['upload_image']['name']);
79
            $question->setImage($media_url . $data['upload_image']['name']);
80
            ErrorHandler::stop(true);
81
        }
82
83
        $this->getQuizQuestionMapper()->update($question);
84
        $this->getQuizMapper()->update($quiz);
85
86
        return $question;
87
    }
88
89
    /**
90
     * @param  array                  $data
91
     * @return \PlaygroundGame\Entity\Game
92
     */
93
    public function updateQuestion(array $data, $question)
94
    {
95
        $path = $this->getOptions()->getMediaPath() . DIRECTORY_SEPARATOR;
96
        $media_url = $this->getOptions()->getMediaUrl() . '/';
97
98
        $form  = $this->getServiceManager()->get('playgroundgame_quizquestion_form');
99
        $form->bind($question);
100
        $form->setData($data);
101
102
        if (!$form->isValid()) {
103
            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...
104
        }
105
106
        // If question is a prediction, no need to calculate max good answers
107
        if (!$question->getPrediction()) {
108
            // Max points and correct answers calculation for the question
109
            if (!$question = $this->calculateMaxAnswersQuestion($question)) {
110
                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...
111
            }
112
        }
113
114 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...
115
            ErrorHandler::start();
116
            $data['upload_image']['name'] = $this->fileNewname($path, $question->getId() . "-" . $data['upload_image']['name']);
117
            move_uploaded_file($data['upload_image']['tmp_name'], $path . $data['upload_image']['name']);
118
            $question->setImage($media_url . $data['upload_image']['name']);
119
            ErrorHandler::stop(true);
120
        }
121
122 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...
123
            ErrorHandler::start();
124
            $image = $question->getImage();
125
            $image = str_replace($media_url, '', $image);
126
            if (file_exists($path .$image)) {
127
                unlink($path .$image);
128
            }
129
            $question->setImage(null);
130
            ErrorHandler::stop(true);
131
        }
132
        
133
        $i = 0;
134
        foreach ($question->getAnswers() as $answer) {
135
            if (!empty($data['answers'][$i]['upload_image']['tmp_name'])) {
136
                ErrorHandler::start();
137
                $data['answers'][$i]['upload_image']['name'] = $this->fileNewname($path, $question->getId() . "-" . $data['answers'][$i]['upload_image']['name']);
138
                move_uploaded_file($data['answers'][$i]['upload_image']['tmp_name'], $path . $data['answers'][$i]['upload_image']['name']);
139
                $answer->setImage($media_url . $data['answers'][$i]['upload_image']['name']);
140
                ErrorHandler::stop(true);
141
            }
142
            
143
            /*if(isset($data['delete_image']) && empty($data['upload_image']['tmp_name'])) {
144
                ErrorHandler::start();
145
                $image = $question->getImage();
146
                $image = str_replace($media_url, '', $image);
147
                unlink($path .$image);
148
                $question->setImage(null);
149
                ErrorHandler::stop(true);
150
            }*/
151
            
152
            $i++;
153
        }
154
155
        // Max points and correct answers recalculation for the quiz
156
        $quiz = $this->calculateMaxAnswersQuiz($question->getQuiz());
157
158
        // If the question was a pronostic, I update entries with the results !
159
        if ($question->getPrediction()) {
160
            // je recherche toutes les participations au jeu
161
            $entries = $this->getEntryMapper()->findByGameId($question->getQuiz());
162
163
            $answers = $question->getAnswers();
164
165
            $answersarray = array();
166
            foreach ($answers as $answer) {
167
                $answersarray[$answer->getId()] = $answer;
168
            }
169
170
            // I update all answers with points and correctness
171
            // Refactorer findByEntryAndQuestion pour qu'elle fonctionne avec QuizReplyAnswer
172
            /**
173
             * 1. Je recherche $this->getQuizReplyMapper()->findByEntry($entry)
174
             * 2. Pour chaque entrée trouvée, je recherche $this->getQuizReplyAnswerMapper()->findByReplyAndQuestion($reply, $question->getId())
175
             * 3. Je mets à jour reply avec le nb de bonnes réponses
176
             * 4. Je trigger une story ?
177
             */
178
            foreach ($entries as $entry) {
179
                $quizReplies = $this->getQuizReplyMapper()->findByEntry($entry);
180
                if ($quizReplies) {
181
                    foreach ($quizReplies as $reply) {
182
                        $quizReplyAnswers = $this->getQuizReplyAnswerMapper()->findByReplyAndQuestion($reply, $question->getId());
183
                        $quizPoints = 0;
184
                        $quizCorrectAnswers = 0;
185
                        if ($quizReplyAnswers) {
186
                            foreach ($quizReplyAnswers as $quizReplyAnswer) {
187
                                if (2 != $question->getType()) {
188
                                    if ($answersarray[$quizReplyAnswer->getAnswerId()]) {
189
                                        $updatedAnswer = $answersarray[$quizReplyAnswer->getAnswerId()];
190
                                        $quizReplyAnswer->setPoints($updatedAnswer->getPoints());
191
                                        $quizPoints += $updatedAnswer->getPoints();
192
                                        $quizReplyAnswer->setCorrect($updatedAnswer->getCorrect());
193
                                        $quizCorrectAnswers += $updatedAnswer->getCorrect();
194
                                        $quizReplyAnswer = $this->getQuizReplyAnswerMapper()->update($quizReplyAnswer);
195
                                    }
196
                                } else {
197
                                    // question is a textarea
198
                                    // search for a matching answer
199
                                    foreach ($answers as $answer) {
200
                                        if (trim(strip_tags($answer->getAnswer())) == trim(strip_tags($quizReplyAnswer->getAnswer()))) {
201
                                            $quizReplyAnswer->setPoints($answer->getPoints());
202
                                            $quizPoints += $answer->getPoints();
203
                                            $quizReplyAnswer->setCorrect($answer->getCorrect());
204
                                            $quizCorrectAnswers += $answer->getCorrect();
205
                                            $quizReplyAnswer = $this->getQuizReplyAnswerMapper()->update($quizReplyAnswer);
206
                                            break;
207
                                        }
208
                                    }
209
                                }
210
                            }
211
                        }
212
                    }
213
                }
214
                $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...
215
                $entry->setWinner($winner);
216
                $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...
217
                $entry->setActive(false);
218
                $entry = $this->getEntryMapper()->update($entry);
219
            }
220
221
            $this->getEventManager()->trigger(__FUNCTION__.'.prediction', $this, array('question' => $question, 'data' => $data));
222
        }
223
224
        $this->getEventManager()->trigger(__FUNCTION__, $this, array('question' => $question, 'data' => $data));
225
        $this->getQuizQuestionMapper()->update($question);
226
        $this->getEventManager()->trigger(__FUNCTION__.'.post', $this, array('question' => $question, 'data' => $data));
227
228
        $this->getQuizMapper()->update($quiz);
229
230
        return $question;
231
    }
232
233
    public function calculateMaxAnswersQuestion($question)
234
    {
235
        $question_max_points = 0;
236
        $question_max_correct_answers = 0;
237
        // Closed question : Only one answer allowed
238
        if ($question->getType() == 0) {
239
            foreach ($question->getAnswers() as $answer) {
240
                if ($answer->getPoints() > $question_max_points) {
241
                    $question_max_points = $answer->getPoints();
242
                }
243
                if ($answer->getCorrect() && $question_max_correct_answers==0) {
244
                    $question_max_correct_answers=1;
245
                }
246
            }
247
            if ($question_max_correct_answers == 0) {
248
                return false;
249
            }
250
        // Closed question : Many answers allowed
251
        } elseif ($question->getType() == 1) {
252
            foreach ($question->getAnswers() as $answer) {
253
                $question_max_points += $answer->getPoints();
254
255
                if ($answer->getCorrect()) {
256
                    ++$question_max_correct_answers;
257
                }
258
            }
259
            if ($question_max_correct_answers == 0) {
260
                return false;
261
            }
262
        // Not a question : A textarea to fill in
263
        } elseif ($question->getType() == 2) {
264
            $question_max_correct_answers = 0;
265
        }
266
267
        $question->setMaxPoints($question_max_points);
268
        $question->setMaxCorrectAnswers($question_max_correct_answers);
269
270
        return $question;
271
    }
272
273
    public function calculateMaxAnswersQuiz($quiz)
274
    {
275
        $question_max_points = 0;
276
        $question_max_correct_answers = 0;
277
        foreach ($quiz->getQuestions() as $question) {
278
            $question_max_points += $question->getMaxPoints();
279
            $question_max_correct_answers += $question->getMaxCorrectAnswers();
280
        }
281
        $quiz->setMaxPoints($question_max_points);
282
        $quiz->setMaxCorrectAnswers($question_max_correct_answers);
283
284
        return $quiz;
285
    }
286
287 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...
288
    {
289
        $em = $this->getServiceManager()->get('doctrine.entitymanager.orm_default');
290
291
        $query = $em->createQuery(
292
            "SELECT COUNT(e.id) FROM PlaygroundGame\Entity\Entry e, PlaygroundGame\Entity\Game g
293
                WHERE e.user = :user
294
                AND g.classType = 'quiz'
295
                AND e.points > 0"
296
        );
297
        $query->setParameter('user', $user);
298
        $number = $query->getSingleScalarResult();
299
300
        return $number;
301
    }
302
303
    public function createQuizReply($data, $game, $user)
304
    {
305
        // Si mon nb de participation est < au nb autorisé, j'ajoute une entry + reponses au quiz et points
306
        $quizReplyMapper = $this->getQuizReplyMapper();
307
        $entryMapper = $this->getEntryMapper();
308
        $entry = $this->findLastActiveEntry($game, $user);
309
310
        if (!$entry) {
311
            return false;
312
        }
313
314
        $quizPoints          = 0;
315
        $quizCorrectAnswers  = 0;
316
        $maxCorrectAnswers = $game->getMaxCorrectAnswers();
317
        $totalQuestions = 0;
318
319
        $quizReply = new QuizReply();
320
321
        foreach ($data as $group) {
322
            foreach ($group as $q => $a) {
323
                if (strlen($q) > 5 && strpos($q, '-data', strlen($q) - 5) !== false) {
324
                    continue; // answer data is processed below
325
                }
326
                $question = $this->getQuizQuestionMapper()->findById((int) str_replace('q', '', $q));
327
                ++$totalQuestions;
328
                if (is_array($a)) {
329
                    foreach ($a as $k => $answer_id) {
330
                        $answer = $this->getQuizAnswerMapper()->findById($answer_id);
331 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...
332
                            $quizReplyAnswer = new QuizReplyAnswer();
333
                            $quizReplyAnswer->setAnswer($answer->getAnswer());
334
                            $quizReplyAnswer->setAnswerId($answer_id);
335
                            $quizReplyAnswer->setQuestion($question->getQuestion());
336
                            $quizReplyAnswer->setQuestionId($question->getId());
337
                            $quizReplyAnswer->setPoints($answer->getPoints());
338
                            $quizReplyAnswer->setCorrect($answer->getCorrect());
339
340
                            $quizReply->addAnswer($quizReplyAnswer);
341
                            $quizPoints += $answer->getPoints();
342
                            $quizCorrectAnswers += $answer->getCorrect();
343
344
                            if (isset($group[$q.'-'.$answer_id.'-data'])) {
345
                                $quizReplyAnswer->setAnswerData($group[$q.'-'.$answer_id.'-data']);
346
                            }
347
                        }
348
                    }
349
                } elseif ($question->getType() == 0 || $question->getType() == 1) {
350
                    ++$totalQuestions;
351
                    $answer = $this->getQuizAnswerMapper()->findById($a);
352 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...
353
                        $quizReplyAnswer = new QuizReplyAnswer();
354
                        $quizReplyAnswer->setAnswer($answer->getAnswer());
355
                        $quizReplyAnswer->setAnswerId($a);
356
                        $quizReplyAnswer->setQuestion($question->getQuestion());
357
                        $quizReplyAnswer->setQuestionId($question->getId());
358
                        $quizReplyAnswer->setPoints($answer->getPoints());
359
                        $quizReplyAnswer->setCorrect($answer->getCorrect());
360
361
                        $quizReply->addAnswer($quizReplyAnswer);
362
                        $quizPoints += $answer->getPoints();
363
                        $quizCorrectAnswers += $answer->getCorrect();
364
                        if (isset($group[$q.'-'.$a.'-data'])) {
365
                            $quizReplyAnswer->setAnswerData($group[$q.'-'.$a.'-data']);
366
                        }
367
                    }
368
                } elseif ($question->getType() == 2) {
369
                    ++$totalQuestions;
370
                    $quizReplyAnswer = new QuizReplyAnswer();
371
                    
372
                    $quizReplyAnswer->setAnswer($a);
373
                    $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...
374
                    $quizReplyAnswer->setQuestion($question->getQuestion());
375
                    $quizReplyAnswer->setQuestionId($question->getId());
376
                    $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...
377
                    $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...
378
379
                    $quizReply->addAnswer($quizReplyAnswer);
380
                    $quizPoints += 0;
381
                    $quizCorrectAnswers += 0;
382
                    $qAnswers = $question->getAnswers();
383
                    foreach ($qAnswers as $qAnswer) {
384
                        if (trim(strip_tags($a)) == trim(strip_tags($qAnswer->getAnswer()))) {
385
                            $quizReplyAnswer->setPoints($qAnswer->getPoints());
386
                            $quizPoints += $qAnswer->getPoints();
387
                            $quizReplyAnswer->setCorrect($qAnswer->getCorrect());
388
                            $quizCorrectAnswers += $qAnswer->getCorrect();
389
                            // $quizReplyAnswer = $this->getQuizReplyAnswerMapper()->update($quizReplyAnswer);
390
                            break;
391
                        }
392
                    }
393
394
                    if (isset($group[$q.'-'.$a.'-data'])) {
395
                        $quizReplyAnswer->setAnswerData($group[$q.'-'.$a.'-data']);
396
                    }
397
                }
398
            }
399
        }
400
401
        $winner = $this->isWinner($game, $quizCorrectAnswers);
402
403
        $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...
404
        // Every winning participation is eligible to draw
405
        // Make this modifiable in the admin (choose who can participate to draw)
406
        $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...
407
        $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...
408
        $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...
409
        $entry = $entryMapper->update($entry);
410
411
        $quizReply->setEntry($entry);
412
        $quizReply->setTotalCorrectAnswers($quizCorrectAnswers);
413
        $quizReply->setMaxCorrectAnswers($maxCorrectAnswers);
414
        $quizReply->setTotalQuestions($totalQuestions);
415
416
        $quizReplyMapper->insert($quizReply);
417
418
        $this->getEventManager()->trigger('complete_quiz.post', $this, array('user' => $user, 'entry' => $entry, 'reply' => $quizReply, 'game' => $game));
419
420
        return $entry;
421
    }
422
423
    public function isWinner($game, $quizCorrectAnswers = 0)
424
    {
425
        // Pour déterminer le gagnant, je regarde le nombre max de reponses correctes possibles
426
        // dans le jeu, puis je calcule le ratio de bonnes réponses et le compare aux conditions
427
        // de victoire
428
        $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...
429
        $maxCorrectAnswers = $game->getMaxCorrectAnswers();
430
        if ($maxCorrectAnswers > 0) {
431
            $ratioCorrectAnswers = ($quizCorrectAnswers / $maxCorrectAnswers) * 100;
432
        } elseif ($game->getVictoryConditions() > 0) {
433
            // In the case I have a pronostic game for example
434
            $ratioCorrectAnswers = 0;
435
        } else {
436
            // In the case I want everybody to win
437
            $ratioCorrectAnswers = 100;
438
        }
439
440
        $winner = false;
441
        if ($game->getVictoryConditions() >= 0) {
442
            if ($ratioCorrectAnswers >= $game->getVictoryConditions()) {
443
                $winner = true;
444
            }
445
        }
446
        return $winner;
447
    }
448
449
    public function getEntriesHeader($game){
450
        $header = parent::getEntriesHeader($game);
451
        $header['totalCorrectAnswers'] = 1;
452
453
        return $header;
454
    }
455
456 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...
457
        $em = $this->getServiceManager()->get('doctrine.entitymanager.orm_default');
458
459
        $qb = $em->createQueryBuilder();
460
        $qb->select('
461
            r.id,
462
            u.username,
463
            u.title,
464
            u.firstname,
465
            u.lastname,
466
            u.email,
467
            u.optin,
468
            u.optinPartner,
469
            u.address,
470
            u.address2,
471
            u.postalCode,
472
            u.city,
473
            u.telephone,
474
            u.mobile,
475
            u.created_at,
476
            u.dob,
477
            e.winner,
478
            e.socialShares,
479
            e.playerData,
480
            e.updated_at,
481
            r.totalCorrectAnswers
482
            ')
483
            ->from('PlaygroundGame\Entity\QuizReply', 'r')
484
            ->innerJoin('r.entry', 'e')
485
            ->leftJoin('e.user', 'u')
486
            ->where($qb->expr()->eq('e.game', ':game'));
487
        
488
        $qb->setParameter('game', $game);
489
490
        return $qb->getQuery();
491
    }
492
493
    public function getGameEntity()
494
    {
495
        return new \PlaygroundGame\Entity\Quiz;
496
    }
497
498
    /**
499
     * getQuizMapper
500
     *
501
     * @return QuizMapperInterface
502
     */
503
    public function getQuizMapper()
504
    {
505
        if (null === $this->quizMapper) {
506
            $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...
507
        }
508
509
        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 509 which is incompatible with the return type documented by PlaygroundGame\Service\Quiz::getQuizMapper of type PlaygroundGame\Service\QuizMapperInterface.
Loading history...
510
    }
511
512
    /**
513
     * setQuizMapper
514
     *
515
     * @param  QuizMapperInterface $quizMapper
516
     * @return Game
517
     */
518
    public function setQuizMapper(GameMapperInterface $quizMapper)
519
    {
520
        $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...
521
522
        return $this;
523
    }
524
525
    /**
526
     * getQuizQuestionMapper
527
     *
528
     * @return QuizQuestionMapperInterface
529
     */
530
    public function getQuizQuestionMapper()
531
    {
532
        if (null === $this->quizQuestionMapper) {
533
            $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...
534
        }
535
536
        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 536 which is incompatible with the return type documented by PlaygroundGame\Service\Quiz::getQuizQuestionMapper of type PlaygroundGame\Service\QuizQuestionMapperInterface.
Loading history...
537
    }
538
539
    /**
540
     * setQuizQuestionMapper
541
     *
542
     * @param  QuizQuestionMapperInterface $quizquestionMapper
543
     * @return Quiz
544
     */
545
    public function setQuizQuestionMapper($quizquestionMapper)
546
    {
547
        $this->quizQuestionMapper = $quizquestionMapper;
548
549
        return $this;
550
    }
551
552
    /**
553
     * setQuizAnswerMapper
554
     *
555
     * @param  QuizAnswerMapperInterface $quizAnswerMapper
556
     * @return Quiz
557
     */
558
    public function setQuizAnswerMapper($quizAnswerMapper)
559
    {
560
        $this->quizAnswerMapper = $quizAnswerMapper;
561
562
        return $this;
563
    }
564
565
    /**
566
     * getQuizAnswerMapper
567
     *
568
     * @return QuizAnswerMapperInterface
569
     */
570
    public function getQuizAnswerMapper()
571
    {
572
        if (null === $this->quizAnswerMapper) {
573
            $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...
574
        }
575
576
        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 576 which is incompatible with the return type documented by PlaygroundGame\Service\Quiz::getQuizAnswerMapper of type PlaygroundGame\Service\QuizAnswerMapperInterface.
Loading history...
577
    }
578
579
    /**
580
     * getQuizReplyMapper
581
     *
582
     * @return QuizReplyMapperInterface
583
     */
584
    public function getQuizReplyMapper()
585
    {
586
        if (null === $this->quizReplyMapper) {
587
            $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...
588
        }
589
590
        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 590 which is incompatible with the return type documented by PlaygroundGame\Service\Quiz::getQuizReplyMapper of type PlaygroundGame\Service\QuizReplyMapperInterface.
Loading history...
591
    }
592
593
    /**
594
     * setQuizReplyMapper
595
     *
596
     * @param  QuizReplyMapperInterface $quizreplyMapper
597
     * @return Quiz
598
     */
599
    public function setQuizReplyMapper($quizreplyMapper)
600
    {
601
        $this->quizReplyMapper = $quizreplyMapper;
602
603
        return $this;
604
    }
605
606
    /**
607
     * getQuizReplyAnswerMapper
608
     *
609
     * @return QuizReplyAnswerMapper
610
     */
611
    public function getQuizReplyAnswerMapper()
612
    {
613
        if (null === $this->quizReplyAnswerMapper) {
614
            $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...
615
        }
616
617
        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 617 which is incompatible with the return type documented by PlaygroundGame\Service\Q...etQuizReplyAnswerMapper of type PlaygroundGame\Service\QuizReplyAnswerMapper.
Loading history...
618
    }
619
620
     /**
621
     * setQuizReplyAnswerMapper
622
     *
623
     * @param  QuizReplyAnswerMapper $quizReplyAnswerMapper
624
     * @return Quiz
625
     */
626
    public function setQuizReplyAnswerMapper($quizReplyAnswerMapper)
627
    {
628
        $this->quizReplyAnswerMapper = $quizReplyAnswerMapper;
629
630
        return $this;
631
    }
632
}
633