Completed
Push — master ( f27c8b...b35943 )
by greg
06:40 queued 03:40
created

GameController::checkFbRegistration()   B

Complexity

Conditions 6
Paths 10

Size

Total Lines 49
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 6
Bugs 0 Features 0
Metric Value
c 6
b 0
f 0
dl 0
loc 49
rs 8.5907
cc 6
eloc 30
nc 10
nop 2
1
<?php
2
3
namespace PlaygroundGame\Controller\Frontend;
4
5
use Zend\Mvc\Controller\AbstractActionController;
6
use Zend\View\Model\ViewModel;
7
use Zend\Session\Container;
8
use PlaygroundGame\Service\GameService;
9
use PlaygroundGame\Service\Prize as PrizeService;
10
use Zend\View\Model\JsonModel;
11
use Zend\Http\PhpEnvironment\Response;
12
use Zend\Stdlib\Parameters;
13
14
class GameController extends AbstractActionController
15
{
16
    /**
17
     * @var \PlaygroundGame\Service\GameService
18
     */
19
    protected $gameService;
20
21
    protected $prizeService;
22
23
    protected $options;
24
25
    protected $game;
26
27
    protected $user;
28
29
    protected $withGame = array(
30
        'home',
31
        'index',
32
        'terms',
33
        'conditions',
34
        'leaderboard',
35
        'register',
36
        'bounce',
37
        'prizes',
38
        'prize',
39
        'fangate',
40
        'share',
41
        'optin',
42
        'login',
43
        'play',
44
        'result',
45
        'preview',
46
        'list'
47
    );
48
49
    protected $withOnlineGame = array(
50
        'leaderboard',
51
        'register',
52
        'bounce',
53
        'play',
54
        'result'
55
    );
56
57
    protected $withAnyUser = array(
58
        'share',
59
        'result',
60
        'play'
61
    );
62
63
    public function setEventManager(\Zend\EventManager\EventManagerInterface $events)
64
    {
65
        parent::setEventManager($events);
66
67
        $controller = $this;
68
        $events->attach('dispatch', function (\Zend\Mvc\MvcEvent $e) use ($controller) {
69
70
            $identifier = $e->getRouteMatch()->getParam('id');
71
            $controller->game = $controller->getGameService()->checkGame($identifier, false);
72
            if (!$controller->game &&
73
                in_array($controller->params('action'), $controller->withGame)
74
            ) {
75
                return $controller->notFoundAction();
76
            }
77
78
            if ($controller->game &&
79
                $controller->game->isClosed() &&
80
                in_array($controller->params('action'), $controller->withOnlineGame)
81
            ) {
82
                return $controller->notFoundAction();
83
            }
84
85
            $controller->user = $controller->zfcUserAuthentication()->getIdentity();
0 ignored issues
show
Documentation Bug introduced by
The method zfcUserAuthentication does not exist on object<PlaygroundGame\Co...rontend\GameController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
86
            if ($controller->game &&
87
                !$controller->user &&
88
                !$controller->game->getAnonymousAllowed() &&
89
                in_array($controller->params('action'), $controller->withAnyUser)
90
            ) {
91
                $redirect = urlencode(
92
                    $controller->url()->fromRoute(
93
                        'frontend/'.$controller->game->getClassType() . '/' . $controller->params('action'),
94
                        array('id' => $controller->game->getIdentifier()),
95
                        array('force_canonical' => true)
96
                    )
97
                );
98
99
                $urlRegister = $controller->url()->fromRoute(
100
                    'frontend/zfcuser/register',
101
                    array(),
102
                    array('force_canonical' => true)
103
                ) . '?redirect='.$redirect;
104
105
                // code permettant d'identifier un custom game
106
                // ligne $config = $controller->getGameService()->getServiceManager()->get('config');
107
                // ligne $customUrl = str_replace('frontend.', '', $e->getRouteMatch()->getParam('area', ''));
108
                // ligne if ($config['custom_games'][$controller->game->getIdentifier()] &&
109
                // ligne    $controller->getRequest()->getUri()->getHost() === $customUrl
110
                // ligne ) {
111
                return $controller->redirect()->toUrl($urlRegister);
112
            }
113
114
            return;
115
        }, 100); // execute before executing action logic
116
    }
117
118
    /**
119
     * Action called if matched action does not exist
120
     * For this view not to be catched by Zend\Mvc\View\RouteNotFoundStrategy
121
     * it has to be rendered in the controller. Hence the code below.
122
     *
123
     * This action is injected as a catchall action for each custom_games definition
124
     * This way, when a custom_game is created, the 404 is it's responsability and the
125
     * view can be defined in design/frontend/default/custom/$slug/playground_game/$gametype/404.phtml
126
     *
127
     *
128
     * @return \Zend\Stdlib\ResponseInterface
129
     */
130
    public function notFoundAction()
131
    {
132
        $viewRender     = $this->getServiceLocator()->get('ViewRenderer');
133
134
        $this->getEvent()->getRouteMatch()->setParam('action', 'not-found');
135
        $this->response->setStatusCode(404);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Stdlib\ResponseInterface as the method setStatusCode() does only exist in the following implementations of said interface: Zend\Http\PhpEnvironment\Response, Zend\Http\Response, Zend\Http\Response\Stream.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
136
137
        $res = 'error/404';
138
139
        $viewModel = $this->buildView($this->game);
140
        $viewModel->setTemplate($res);
0 ignored issues
show
Bug introduced by
The method setTemplate does only exist in Zend\View\Model\ViewModel, but not in Zend\Http\PhpEnvironment\Response.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
141
142
        $this->layout()->setVariable("content", $viewRender->render($viewModel));
0 ignored issues
show
Bug introduced by
The method setVariable does only exist in Zend\View\Model\ModelInterface, but not in Zend\Mvc\Controller\Plugin\Layout.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
143
        $this->response->setContent($viewRender->render($this->layout()));
144
145
        return $this->response;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->response; (Zend\Stdlib\ResponseInterface) is incompatible with the return type of the parent method Zend\Mvc\Controller\Abst...troller::notFoundAction of type array.

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...
146
    }
147
148
    /**
149
     * This action acts as a hub : Depending on the first step of the game, it will forward the action to this step
150
     */
151
    public function homeAction()
152
    {
153
        // This fix exists only for safari in FB on Windows : we need to redirect the user to the page
154
        // outside of iframe for the cookie to be accepted. PlaygroundCore redirects to the FB Iframed page when
155
        // it discovers that the user arrives for the first time on the game in FB.
156
        // When core redirects, it adds a 'redir_fb_page_id' var in the querystring
157
        // Here, we test if this var exist, and then send the user back to the game in FB.
158
        // Now the cookie will be accepted by Safari...
159
        $pageId = $this->params()->fromQuery('redir_fb_page_id');
160
        if (!empty($pageId)) {
161
            $appId = 'app_'.$this->game->getFbAppId();
162
            $url = '//www.facebook.com/pages/game/'.$pageId.'?sk='.$appId;
163
164
            return $this->redirect()->toUrl($url);
165
        }
166
167
        // If an entry has already been done during this session, I reset the anonymous_identifier cookie
168
        // so that another person can play the same game (if game conditions are fullfilled)
169
        $session = new Container('anonymous_identifier');
170
        if ($session->offsetExists('anonymous_identifier')) {
171
            $session->offsetUnset('anonymous_identifier');
172
        }
173
        
174
        return $this->forward()->dispatch(
175
            'playgroundgame_'.$this->game->getClassType(),
176
            array(
177
                'controller' => 'playgroundgame_'.$this->game->getClassType(),
178
                'action' => $this->game->firstStep(),
179
                'id' => $this->game->getIdentifier()
180
            )
181
        );
182
    }
183
184
    /**
185
     * Homepage of the game
186
     */
187
    public function indexAction()
188
    {
189
        $isSubscribed = false;
190
191
        $entry = $this->getGameService()->checkExistingEntry($this->game, $this->user);
192
        if ($entry) {
193
            $isSubscribed = true;
194
        }
195
196
        $viewModel = $this->buildView($this->game);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->buildView($this->game); of type Zend\Http\PhpEnvironment...nd\View\Model\ViewModel adds the type Zend\Http\PhpEnvironment\Response to the return on line 201 which is incompatible with the return type of the parent method Zend\Mvc\Controller\Abst...Controller::indexAction of type Zend\View\Model\ViewModel.
Loading history...
197
        $viewModel->setVariables(array(
0 ignored issues
show
Bug introduced by
The method setVariables does only exist in Zend\View\Model\ViewModel, but not in Zend\Http\PhpEnvironment\Response.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
198
            'isSubscribed' => $isSubscribed
199
        ));
200
201
        return $viewModel;
202
    }
203
204
    /**
205
      * leaderboardAction
206
      *
207
      * @return ViewModel $viewModel
208
      */
209
    public function leaderboardAction()
210
    {
211
        $filter = $this->getEvent()->getRouteMatch()->getParam('filter');
212
        $p = $this->getEvent()->getRouteMatch()->getParam('p');
213
214
        $beforeLayout = $this->layout()->getTemplate();
0 ignored issues
show
Bug introduced by
The method getTemplate does only exist in Zend\View\Model\ModelInterface, but not in Zend\Mvc\Controller\Plugin\Layout.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
215
        $subViewModel = $this->forward()->dispatch(
216
            'playgroundreward',
217
            array('action' => 'leaderboard', 'filter' => $filter, 'p' => $p)
218
        );
219
        
220
        // suite au forward, le template de layout a changé, je dois le rétablir...
221
        $this->layout()->setTemplate($beforeLayout);
222
223
        // give the ability to the game to have its customized look and feel.
224
        $templatePathResolver = $this->getServiceLocator()->get('Zend\View\Resolver\TemplatePathStack');
225
        $l = $templatePathResolver->getPaths();
226
227
        $templatePathResolver->addPath($l[0].'custom/'.$this->game->getIdentifier());
228
229
        return $subViewModel;
230
    }
231
232
    /**
233
     * This action has been designed to be called by other controllers
234
     * It gives the ability to display an information form and persist it in the game entry
235
     *
236
     * @return \Zend\View\Model\ViewModel
237
     */
238
    public function registerAction()
239
    {
240
        $form = $this->getGameService()->createFormFromJson($this->game->getPlayerForm()->getForm(), 'playerForm');
241
242
        if ($this->getRequest()->isPost()) {
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Stdlib\RequestInterface as the method isPost() does only exist in the following implementations of said interface: Zend\Http\PhpEnvironment\Request, Zend\Http\Request.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
243
            // POST Request: Process form
244
            $data = array_merge_recursive(
245
                $this->getRequest()->getPost()->toArray(),
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Stdlib\RequestInterface as the method getPost() does only exist in the following implementations of said interface: Zend\Http\PhpEnvironment\Request, Zend\Http\Request.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
246
                $this->getRequest()->getFiles()->toArray()
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Stdlib\RequestInterface as the method getFiles() does only exist in the following implementations of said interface: Zend\Http\PhpEnvironment\Request, Zend\Http\Request.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
247
            );
248
            
249
            $form->setData($data);
250
251
            if ($form->isValid()) {
252
                // steps of the game
253
                $steps = $this->game->getStepsArray();
254
                // sub steps of the game
255
                $viewSteps = $this->game->getStepsViewsArray();
256
257
                // register position
258
                $key = array_search($this->params('action'), $viewSteps);
259 View Code Duplication
                if (!$key) {
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...
260
                    // register is not a substep of the game so it's a step
261
                    $key = array_search($this->params('action'), $steps);
262
                    $keyStep = true;
263
                } else {
264
                    // register was a substep, i search the index of its parent
265
                    $key = array_search($key, $steps);
266
                    $keyStep = false;
267
                }
268
269
                // play position
270
                $keyplay = array_search('play', $viewSteps);
271
272 View Code Duplication
                if (!$keyplay) {
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...
273
                    // play is not a substep, so it's a step
274
                    $keyplay = array_search('play', $steps);
275
                    $keyplayStep = true;
276
                } else {
277
                    // play is a substep so I search the index of its parent
278
                    $keyplay = array_search($keyplay, $steps);
279
                    $keyplayStep = false;
280
                }
281
282
                // If register step before play, I don't have no entry yet. I have to create one
283
                // If register after play step, I search for the last entry created by play step.
284
285
                if ($key < $keyplay || ($keyStep && !$keyplayStep && $key <= $keyplay)) {
286
                    $entry = $this->getGameService()->play($this->game, $this->user);
287
                    if (!$entry) {
288
                        // the user has already taken part of this game and the participation limit has been reached
289
                        $this->flashMessenger()->addMessage('Vous avez déjà participé');
290
                    
291
                        return $this->redirect()->toUrl(
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->redirect()...me->getIdentifier()))); (Zend\Http\Response) is incompatible with the return type documented by PlaygroundGame\Controlle...troller::registerAction of type Zend\View\Model\ViewModel.

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...
292
                            $this->frontendUrl()->fromRoute(
0 ignored issues
show
Documentation Bug introduced by
The method frontendUrl does not exist on object<PlaygroundGame\Co...rontend\GameController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
293
                                $this->game->getClassType().'/result',
294
                                array(
295
                                    'id' => $this->game->getIdentifier(),
296
                                    
297
                                )
298
                            )
299
                        );
300
                    }
301
                } else {
302
                    // I'm looking for an entry without anonymousIdentifier (the active entry in fact).
303
                    $entry = $this->getGameService()->findLastEntry($this->game, $this->user);
304
                    if ($this->getGameService()->hasReachedPlayLimit($this->game, $this->user)) {
305
                        // the user has already taken part of this game and the participation limit has been reached
306
                        $this->flashMessenger()->addMessage('Vous avez déjà participé');
307
                    
308
                        return $this->redirect()->toUrl(
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->redirect()...me->getIdentifier()))); (Zend\Http\Response) is incompatible with the return type documented by PlaygroundGame\Controlle...troller::registerAction of type Zend\View\Model\ViewModel.

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...
309
                            $this->frontendUrl()->fromRoute(
0 ignored issues
show
Documentation Bug introduced by
The method frontendUrl does not exist on object<PlaygroundGame\Co...rontend\GameController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
310
                                $this->game->getClassType().'/result',
311
                                array(
312
                                    'id' => $this->game->getIdentifier(),
313
                                    
314
                                )
315
                            )
316
                        );
317
                    }
318
                }
319
320
                $this->getGameService()->updateEntryPlayerForm($form->getData(), $this->game, $this->user, $entry);
321
322
                if (!empty($this->game->nextStep($this->params('action')))) {
323
                    return $this->redirect()->toUrl(
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->redirect()..._canonical' => true))); (Zend\Http\Response) is incompatible with the return type documented by PlaygroundGame\Controlle...troller::registerAction of type Zend\View\Model\ViewModel.

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...
324
                        $this->frontendUrl()->fromRoute(
0 ignored issues
show
Documentation Bug introduced by
The method frontendUrl does not exist on object<PlaygroundGame\Co...rontend\GameController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
325
                            $this->game->getClassType() .'/' . $this->game->nextStep($this->params('action')),
326
                            array('id' => $this->game->getIdentifier()),
327
                            array('force_canonical' => true)
328
                        )
329
                    );
330
                }
331
            }
332
        }
333
334
        $viewModel = $this->buildView($this->game);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->buildView($this->game); of type Zend\Http\PhpEnvironment...nd\View\Model\ViewModel adds the type Zend\Http\PhpEnvironment\Response to the return on line 339 which is incompatible with the return type documented by PlaygroundGame\Controlle...troller::registerAction of type Zend\View\Model\ViewModel.
Loading history...
335
        $viewModel->setVariables(array(
0 ignored issues
show
Bug introduced by
The method setVariables does only exist in Zend\View\Model\ViewModel, but not in Zend\Http\PhpEnvironment\Response.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
336
            'form' => $form
337
        ));
338
339
        return $viewModel;
340
    }
341
342
    /**
343
     * This action takes care of the terms of the game
344
     */
345
    public function termsAction()
346
    {
347
        $viewModel = $this->buildView($this->game);
348
349
        return $viewModel;
350
    }
351
352
    /**
353
     * This action takes care of the conditions of the game
354
     */
355
    public function conditionsAction()
356
    {
357
        $viewModel = $this->buildView($this->game);
358
359
        return $viewModel;
360
    }
361
362
    /**
363
     * This action takes care of bounce page of the game
364
     */
365
    public function bounceAction()
366
    {
367
        $availableGames = $this->getGameService()->getAvailableGames($this->user);
368
369
        $rssUrl = '';
370
        $config = $this->getGameService()->getServiceManager()->get('config');
371
        if (isset($config['rss']['url'])) {
372
            $rssUrl = $config['rss']['url'];
373
        }
374
375
        $viewModel = $this->buildView($this->game);
376
        $viewModel->setVariables(array(
0 ignored issues
show
Bug introduced by
The method setVariables does only exist in Zend\View\Model\ViewModel, but not in Zend\Http\PhpEnvironment\Response.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
377
            'rssUrl'         => $rssUrl,
378
            'user'           => $this->user,
379
            'availableGames' => $availableGames,
380
        ));
381
382
        return $viewModel;
383
    }
384
385
386
    /**
387
     * This action displays the Prizes page associated to the game
388
     */
389
    public function prizesAction()
390
    {
391
        if (count($this->game->getPrizes()) == 0) {
392
            return $this->notFoundAction();
393
        }
394
395
        $viewModel = $this->buildView($this->game);
396
397
        return $viewModel;
398
    }
399
400
    /**
401
     * This action displays a specific Prize page among those associated to the game
402
     */
403
    public function prizeAction()
404
    {
405
        $prizeIdentifier = $this->getEvent()->getRouteMatch()->getParam('prize');
406
        $prize = $this->getPrizeService()->getPrizeMapper()->findByIdentifier($prizeIdentifier);
407
        
408
        if (!$prize) {
409
            return $this->notFoundAction();
410
        }
411
412
        $viewModel = $this->buildView($this->game);
413
        $viewModel->setVariables(array('prize'=> $prize));
0 ignored issues
show
Bug introduced by
The method setVariables does only exist in Zend\View\Model\ViewModel, but not in Zend\Http\PhpEnvironment\Response.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
414
415
        return $viewModel;
416
    }
417
418
    public function gameslistAction()
419
    {
420
        $layoutViewModel = $this->layout();
421
422
        $slider = new ViewModel();
423
        $slider->setTemplate('playground-game/common/top_promo');
424
425
        $sliderItems = $this->getGameService()->getActiveSliderGames();
426
427
        $slider->setVariables(array('sliderItems' => $sliderItems));
428
429
        $layoutViewModel->addChild($slider, 'slider');
0 ignored issues
show
Bug introduced by
The method addChild does only exist in Zend\View\Model\ModelInterface, but not in Zend\Mvc\Controller\Plugin\Layout.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
430
431
        $games = $this->getGameService()->getActiveGames(false, '', 'endDate');
432
        if (is_array($games)) {
433
            $paginator = new \Zend\Paginator\Paginator(new \Zend\Paginator\Adapter\ArrayAdapter($games));
434
        } else {
435
            $paginator = $games;
436
        }
437
438
        $paginator->setItemCountPerPage(7);
439
        $paginator->setCurrentPageNumber($this->getEvent()->getRouteMatch()->getParam('p'));
440
441
        $bitlyclient = $this->getOptions()->getBitlyUrl();
442
        $bitlyuser = $this->getOptions()->getBitlyUsername();
443
        $bitlykey = $this->getOptions()->getBitlyApiKey();
444
445
        $this->getViewHelper('HeadMeta')->setProperty('bt:client', $bitlyclient);
446
        $this->getViewHelper('HeadMeta')->setProperty('bt:user', $bitlyuser);
447
        $this->getViewHelper('HeadMeta')->setProperty('bt:key', $bitlykey);
448
449
        $this->layout()->setVariables(
0 ignored issues
show
Bug introduced by
The method setVariables does only exist in Zend\View\Model\ModelInterface, but not in Zend\Mvc\Controller\Plugin\Layout.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
450
            array(
451
            'sliderItems'   => $sliderItems,
452
            'currentPage' => array(
453
                'pageGames' => 'games',
454
                'pageWinners' => ''
455
            ),
456
            )
457
        );
458
459
        return new ViewModel(
460
            array(
461
                'games' => $paginator
462
            )
463
        );
464
    }
465
466
    public function fangateAction()
467
    {
468
        $viewModel = $this->buildView($this->game);
469
470
        return $viewModel;
471
    }
472
    
473
    public function shareAction()
474
    {
475
        $statusMail = null;
476
        $lastEntry = null;
477
    
478
        // steps of the game
479
        $steps = $this->game->getStepsArray();
480
        // sub steps of the game
481
        $viewSteps = $this->game->getStepsViewsArray();
482
483
        // share position
484
        $key = array_search($this->params('action'), $viewSteps);
485 View Code Duplication
        if (!$key) {
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...
486
            // share is not a substep of the game so it's a step
487
            $key = array_search($this->params('action'), $steps);
488
            $keyStep = true;
0 ignored issues
show
Unused Code introduced by
$keyStep 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...
489
        } else {
490
            // share was a substep, I search the index of its parent
491
            $key = array_search($key, $steps);
492
            $keyStep = false;
0 ignored issues
show
Unused Code introduced by
$keyStep 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...
493
        }
494
495
        // play position
496
        $keyplay = array_search('play', $viewSteps);
497
498 View Code Duplication
        if (!$keyplay) {
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...
499
            // play is not a substep, so it's a step
500
            $keyplay = array_search('play', $steps);
501
            $keyplayStep = true;
0 ignored issues
show
Unused Code introduced by
$keyplayStep 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...
502
        } else {
503
            // play is a substep so I search the index of its parent
504
            $keyplay = array_search($keyplay, $steps);
505
            $keyplayStep = false;
0 ignored issues
show
Unused Code introduced by
$keyplayStep 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...
506
        }
507
508
        if ($key && $keyplay && $keyplay <= $key) {
509
            // Has the user finished the game ?
510
            $lastEntry = $this->getGameService()->findLastInactiveEntry($this->game, $this->user);
511
    
512 View Code Duplication
            if ($lastEntry === null) {
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...
513
                return $this->redirect()->toUrl(
514
                    $this->frontendUrl()->fromRoute(
0 ignored issues
show
Documentation Bug introduced by
The method frontendUrl does not exist on object<PlaygroundGame\Co...rontend\GameController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
515
                        $this->game->getClassType(),
516
                        array('id' => $this->game->getIdentifier())
517
                    )
518
                );
519
            }
520
        }
521
    
522
        $form = $this->getServiceLocator()->get('playgroundgame_sharemail_form');
523
        $form->setAttribute('method', 'post');
524
525
        // buildView must be before sendMail because it adds the game template path to the templateStack
526
        $viewModel = $this->buildView($this->game);
527
    
528
        if ($this->getRequest()->isPost()) {
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Stdlib\RequestInterface as the method isPost() does only exist in the following implementations of said interface: Zend\Http\PhpEnvironment\Request, Zend\Http\Request.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
529
            $data = $this->getRequest()->getPost()->toArray();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Stdlib\RequestInterface as the method getPost() does only exist in the following implementations of said interface: Zend\Http\PhpEnvironment\Request, Zend\Http\Request.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
530
            $form->setData($data);
531 View Code Duplication
            if ($form->isValid()) {
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...
532
                $result = $this->getGameService()->sendShareMail($data, $this->game, $this->user, $lastEntry);
533
                if ($result) {
534
                    $statusMail = true;
535
                }
536
            }
537
        }
538
539
        $viewModel->setVariables(array(
0 ignored issues
show
Bug introduced by
The method setVariables does only exist in Zend\View\Model\ViewModel, but not in Zend\Http\PhpEnvironment\Response.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
540
            'statusMail'       => $statusMail,
541
            'form'             => $form,
542
        ));
543
    
544
        return $viewModel;
545
    }
546
    
547 View Code Duplication
    public function fbshareAction()
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...
548
    {
549
        $viewModel = new JsonModel();
550
        $viewModel->setTerminal(true);
551
        $fbId = $this->params()->fromQuery('fbId');
552
        if (!$this->game) {
553
            return $this->errorJson();
554
        }
555
        $entry = $this->getGameService()->checkExistingEntry($this->game, $this->user);
556
        if (! $entry) {
557
            return $this->errorJson();
558
        }
559
        if (!$fbId) {
560
            return $this->errorJson();
561
        }
562
    
563
        $this->getGameService()->postFbWall($fbId, $this->game, $this->user, $entry);
564
    
565
        return $this->successJson();
566
    }
567
    
568
    public function fbrequestAction()
569
    {
570
        $viewModel = new ViewModel();
571
        $viewModel->setTerminal(true);
572
        $fbId = $this->params()->fromQuery('fbId');
573
        $to = $this->params()->fromQuery('to');
574
    
575
        if (!$this->game) {
576
            return $this->errorJson();
577
        }
578
        $entry = $this->getGameService()->checkExistingEntry($this->game, $this->user);
579
        if (! $entry) {
580
            return $this->errorJson();
581
        }
582
        if (!$fbId) {
583
            return $this->errorJson();
584
        }
585
    
586
        $this->getGameService()->postFbRequest($fbId, $this->game, $this->user, $entry, $to);
587
    
588
        return $this->successJson();
589
    }
590
    
591
    public function tweetAction()
592
    {
593
        $tweetId = $this->params()->fromQuery('tweetId');
594
    
595
        if (!$this->game) {
596
            return $this->errorJson();
597
        }
598
        $entry = $this->getGameService()->checkExistingEntry($this->game, $this->user);
599
        if (! $entry) {
600
            return $this->errorJson();
601
        }
602
        if (!$tweetId) {
603
            return $this->errorJson();
604
        }
605
    
606
        $this->getGameService()->postTwitter($tweetId, $this->game, $this->user, $entry);
607
    
608
        return $this->successJson();
609
    }
610
    
611 View Code Duplication
    public function googleAction()
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...
612
    {
613
        $viewModel = new ViewModel();
614
        $viewModel->setTerminal(true);
615
        $googleId = $this->params()->fromQuery('googleId');
616
617
        if (!$this->game) {
618
            return $this->errorJson();
619
        }
620
        $entry = $this->getGameService()->checkExistingEntry($this->game, $this->user);
621
        if (! $entry) {
622
            return $this->errorJson();
623
        }
624
        if (!$googleId) {
625
            return $this->errorJson();
626
        }
627
    
628
        $this->getGameService()->postGoogle($googleId, $this->game, $this->user, $entry);
629
    
630
        return $this->successJson();
631
    }
632
633
    public function optinAction()
634
    {
635
        $userService = $this->getServiceLocator()->get('zfcuser_user_service');
636
637
        if ($this->getRequest()->isPost()) {
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Stdlib\RequestInterface as the method isPost() does only exist in the following implementations of said interface: Zend\Http\PhpEnvironment\Request, Zend\Http\Request.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
638
            $data['optin'] = ($this->params()->fromPost('optin'))? 1:0;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$data was never initialized. Although not strictly required by PHP, it is generally a good practice to add $data = array(); before regardless.

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

Let’s take a look at an example:

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

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

    // do something with $myArray
}

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

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

Loading history...
639
            $data['optinPartner'] = ($this->params()->fromPost('optinPartner'))? 1:0;
640
641
            $userService->updateNewsletter($data);
642
        }
643
644
        return $this->redirect()->toUrl(
645
            $this->frontendUrl()->fromRoute(
0 ignored issues
show
Documentation Bug introduced by
The method frontendUrl does not exist on object<PlaygroundGame\Co...rontend\GameController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
646
                'frontend/' . $this->game->getClassType() . '/index',
647
                array('id' => $this->game->getIdentifier())
648
            )
649
        );
650
    }
651
    
652
    public function loginAction()
653
    {
654
        $request = $this->getRequest();
655
        $form = $this->getServiceLocator()->get('zfcuser_login_form');
656
    
657
        if ($request->isPost()) {
658
            $form->setData($request->getPost());
659
            
660
            if (!$form->isValid()) {
661
                $this->flashMessenger()->addMessage(
662
                    'Authentication failed. Please try again.'
663
                );
664
665
                $viewModel = $this->buildView($this->game);
666
                $viewModel->setVariables(array(
0 ignored issues
show
Bug introduced by
The method setVariables does only exist in Zend\View\Model\ViewModel, but not in Zend\Http\PhpEnvironment\Response.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
667
                    'form' => $form,
668
                    'flashMessages' => $this->flashMessenger()->getMessages(),
669
                ));
670
                
671
                return $viewModel;
672
            }
673
            
674
            // clear adapters
675
            $this->zfcUserAuthentication()->getAuthAdapter()->resetAdapters();
0 ignored issues
show
Documentation Bug introduced by
The method zfcUserAuthentication does not exist on object<PlaygroundGame\Co...rontend\GameController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
676
            $this->zfcUserAuthentication()->getAuthService()->clearIdentity();
0 ignored issues
show
Documentation Bug introduced by
The method zfcUserAuthentication does not exist on object<PlaygroundGame\Co...rontend\GameController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
677
678
            $logged = $this->forward()->dispatch('playgrounduser_user', array('action' => 'ajaxauthenticate'));
679
680 View Code Duplication
            if (!$logged) {
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...
681
                $this->flashMessenger()->setNamespace('zfcuser-login-form')->addMessage(
682
                    'Authentication failed. Please try again.'
683
                );
684
                
685
                return $this->redirect()->toUrl(
686
                    $this->frontendUrl()->fromRoute(
0 ignored issues
show
Documentation Bug introduced by
The method frontendUrl does not exist on object<PlaygroundGame\Co...rontend\GameController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
687
                        $this->game->getClassType() . '/login',
688
                        array('id' => $this->game->getIdentifier())
689
                    )
690
                );
691
            } else {
692
                return $this->redirect()->toUrl(
693
                    $this->frontendUrl()->fromRoute(
0 ignored issues
show
Documentation Bug introduced by
The method frontendUrl does not exist on object<PlaygroundGame\Co...rontend\GameController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
694
                        $this->game->getClassType() . '/index',
695
                        array('id' => $this->game->getIdentifier())
696
                    )
697
                );
698
            }
699
        }
700
        
701
        $form->setAttribute(
702
            'action',
703
            $this->frontendUrl()->fromRoute(
0 ignored issues
show
Documentation Bug introduced by
The method frontendUrl does not exist on object<PlaygroundGame\Co...rontend\GameController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
704
                $this->game->getClassType().'/login',
705
                array('id' => $this->game->getIdentifier())
706
            )
707
        );
708
        $viewModel = $this->buildView($this->game);
709
        $viewModel->setVariables(array(
710
            'form' => $form,
711
            'flashMessages' => $this->flashMessenger()->getMessages(),
712
        ));
713
        return $viewModel;
714
    }
715
716
    public function userregisterAction()
717
    {
718
        $userOptions = $this->getServiceLocator()->get('zfcuser_module_options');
719
720
        if ($this->zfcUserAuthentication()->hasIdentity()) {
0 ignored issues
show
Documentation Bug introduced by
The method zfcUserAuthentication does not exist on object<PlaygroundGame\Co...rontend\GameController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
721
            return $this->redirect()->toUrl(
722
                $this->frontendUrl()->fromRoute(
0 ignored issues
show
Documentation Bug introduced by
The method frontendUrl does not exist on object<PlaygroundGame\Co...rontend\GameController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
723
                    $this->game->getClassType().'/'.$this->game->nextStep('index'),
724
                    array('id' => $this->game->getIdentifier())
725
                )
726
            );
727
        }
728
        $request = $this->getRequest();
729
        $service = $this->getServiceLocator()->get('zfcuser_user_service');
730
        $form = $this->getServiceLocator()->get('playgroundgame_register_form');
731
        $socialnetwork = $this->params()->fromRoute('socialnetwork', false);
732
        $form->setAttribute(
733
            'action',
734
            $this->frontendUrl()->fromRoute(
0 ignored issues
show
Documentation Bug introduced by
The method frontendUrl does not exist on object<PlaygroundGame\Co...rontend\GameController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
735
                $this->game->getClassType().'/user-register',
736
                array('id' => $this->game->getIdentifier())
737
            )
738
        );
739
        $params = array();
740
        $socialCredentials = array();
741
742
        if ($userOptions->getUseRedirectParameterIfPresent() && $request->getQuery()->get('redirect')) {
743
            $redirect = $request->getQuery()->get('redirect');
744
        } else {
745
            $redirect = false;
746
        }
747
748
        if ($socialnetwork) {
749
            $infoMe = $this->getProviderService()->getInfoMe($socialnetwork);
0 ignored issues
show
Documentation Bug introduced by
The method getProviderService does not exist on object<PlaygroundGame\Co...rontend\GameController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
750
751
            if (!empty($infoMe)) {
752
                $user = $this->getProviderService()->getUserProviderMapper()->findUserByProviderId(
0 ignored issues
show
Documentation Bug introduced by
The method getProviderService does not exist on object<PlaygroundGame\Co...rontend\GameController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
753
                    $infoMe->identifier,
754
                    $socialnetwork
755
                );
756
757
                if ($user || $service->getOptions()->getCreateUserAutoSocial() === true) {
758
                    //on le dirige vers l'action d'authentification
759
                    if (! $redirect && $userOptions->getLoginRedirectRoute() != '') {
760
                        $redirect = $this->frontendUrl()->fromRoute(
0 ignored issues
show
Documentation Bug introduced by
The method frontendUrl does not exist on object<PlaygroundGame\Co...rontend\GameController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
761
                            $this->game->getClassType().'/login',
762
                            array('id' => $this->game->getIdentifier())
763
                        );
764
                    }
765
                    $redir = $this->frontendUrl()->fromRoute(
0 ignored issues
show
Documentation Bug introduced by
The method frontendUrl does not exist on object<PlaygroundGame\Co...rontend\GameController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
766
                        $this->game->getClassType().'/login',
767
                        array('id' => $this->game->getIdentifier())
768
                    ) .'/' . $socialnetwork . ($redirect ? '?redirect=' . $redirect : '');
769
770
                    return $this->redirect()->toUrl($redir);
771
                }
772
773
                // Je retire la saisie du login/mdp
774
                $form->setAttribute(
775
                    'action',
776
                    $this->frontendUrl()->fromRoute(
0 ignored issues
show
Documentation Bug introduced by
The method frontendUrl does not exist on object<PlaygroundGame\Co...rontend\GameController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
777
                        $this->game->getClassType().'/user-register',
778
                        array(
779
                            'id' => $this->game->getIdentifier(),
780
                            'socialnetwork' => $socialnetwork,
781
                            
782
                        )
783
                    )
784
                );
785
                $form->remove('password');
786
                $form->remove('passwordVerify');
787
788
                $birthMonth = $infoMe->birthMonth;
789
                if (strlen($birthMonth) <= 1) {
790
                    $birthMonth = '0'.$birthMonth;
791
                }
792
                $birthDay = $infoMe->birthDay;
793
                if (strlen($birthDay) <= 1) {
794
                    $birthDay = '0'.$birthDay;
795
                }
796
797
                $gender = $infoMe->gender;
798
                if ($gender == 'female') {
799
                    $title = 'Me';
800
                } else {
801
                    $title = 'M';
802
                }
803
804
                $params = array(
805
                    //'birth_year'  => $infoMe->birthYear,
806
                    'title'      => $title,
807
                    'dob'      => $birthDay.'/'.$birthMonth.'/'.$infoMe->birthYear,
808
                    'firstname'   => $infoMe->firstName,
809
                    'lastname'    => $infoMe->lastName,
810
                    'email'       => $infoMe->email,
811
                    'postalCode' => $infoMe->zip,
812
                );
813
                $socialCredentials = array(
814
                    'socialNetwork' => strtolower($socialnetwork),
815
                    'socialId'      => $infoMe->identifier,
816
                );
817
            }
818
        }
819
820
        $redirectUrl = $this->frontendUrl()->fromRoute(
0 ignored issues
show
Documentation Bug introduced by
The method frontendUrl does not exist on object<PlaygroundGame\Co...rontend\GameController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
821
            $this->game->getClassType().'/user-register',
822
            array('id' => $this->game->getIdentifier())
823
        ) .($socialnetwork ? '/' . $socialnetwork : ''). ($redirect ? '?redirect=' . $redirect : '');
824
        $prg = $this->prg($redirectUrl, true);
825
826
        if ($prg instanceof Response) {
827
            return $prg;
828
        } elseif ($prg === false) {
829
            $form->setData($params);
830
            $viewModel = $this->buildView($this->game);
831
            $viewModel->setVariables(array(
0 ignored issues
show
Bug introduced by
The method setVariables does only exist in Zend\View\Model\ViewModel, but not in Zend\Http\PhpEnvironment\Response.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
832
                'registerForm' => $form,
833
                'enableRegistration' => $userOptions->getEnableRegistration(),
834
                'redirect' => $redirect,
835
            ));
836
            return $viewModel;
837
        }
838
839
        $post = $prg;
840
        $post = array_merge(
841
            $post,
842
            $socialCredentials
843
        );
844
845
        if ($this->game->getOnInvitation()) {
846
            $credential = trim(
847
                $post[$this->getGameService()->getOptions()->getOnInvitationField()]
848
            );
849
            if (!$credential) {
850
                $credential = $this->params()->fromQuery(
851
                    $this->getGameService()->getOptions()->getOnInvitationField()
852
                );
853
            }
854
            $found = $this->getGameService()->getInvitationMapper()->findOneBy(array('requestKey'=>$credential));
855
856
            if (!$found || !empty($found->getUser())) {
857
                $form->setData($post);
858
                $viewModel = $this->buildView($this->game);
859
                $viewModel->setVariables(array(
860
                    'registerForm' => $form,
861
                    'enableRegistration' => $userOptions->getEnableRegistration(),
862
                    'redirect' => $redirect,
863
                    'flashMessages'    => $this->flashMessenger()->getMessages(),
864
                    'flashErrors'      => $this->flashMessenger()->getErrorMessages(),
865
                ));
866
867
                return $viewModel;
868
            }
869
        }
870
871
        $user = $service->register($post, 'playgroundgame_register_form');
872
873
        if (! $user) {
874
            $viewModel = $this->buildView($this->game);
875
            $viewModel->setVariables(array(
876
                'registerForm' => $form,
877
                'enableRegistration' => $userOptions->getEnableRegistration(),
878
                'redirect' => $redirect,
879
            ));
880
            
881
            return $viewModel;
882
        }
883
884
        if ($this->game->getOnInvitation()) {
885
            // user has been created, associate the code with the userId
886
            $found->setUser($user);
0 ignored issues
show
Bug introduced by
The variable $found 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...
887
            $this->getGameService()->getInvitationMapper()->update($found);
888
        }
889
890
        if ($service->getOptions()->getEmailVerification()) {
891
            $vm = new ViewModel(array('userEmail' => $user->getEmail()));
892
            $vm->setTemplate('playground-user/register/registermail');
893
894
            return $vm;
895
        } elseif ($service->getOptions()->getLoginAfterRegistration()) {
896
            $identityFields = $service->getOptions()->getAuthIdentityFields();
897
            if (in_array('email', $identityFields)) {
898
                $post['identity'] = $user->getEmail();
899
            } elseif (in_array('username', $identityFields)) {
900
                $post['identity'] = $user->getUsername();
901
            }
902
            $post['credential'] = isset($post['password'])?$post['password']:'';
903
            $request->setPost(new Parameters($post));
904
905
            // clear adapters
906
            $this->zfcUserAuthentication()->getAuthAdapter()->resetAdapters();
0 ignored issues
show
Documentation Bug introduced by
The method zfcUserAuthentication does not exist on object<PlaygroundGame\Co...rontend\GameController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
907
            $this->zfcUserAuthentication()->getAuthService()->clearIdentity();
0 ignored issues
show
Documentation Bug introduced by
The method zfcUserAuthentication does not exist on object<PlaygroundGame\Co...rontend\GameController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
908
909
            $logged = $this->forward()->dispatch('playgrounduser_user', array('action' => 'ajaxauthenticate'));
910
911 View Code Duplication
            if ($logged) {
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...
912
                return $this->redirect()->toUrl(
913
                    $this->frontendUrl()->fromRoute(
0 ignored issues
show
Documentation Bug introduced by
The method frontendUrl does not exist on object<PlaygroundGame\Co...rontend\GameController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
914
                        $this->game->getClassType(),
915
                        array('id' => $this->game->getIdentifier())
916
                    )
917
                );
918
            } else {
919
                $this->flashMessenger()->setNamespace('zfcuser-login-form')->addMessage(
920
                    'Authentication failed. Please try again.'
921
                );
922
                return $this->redirect()->toUrl(
923
                    $this->frontendUrl()->fromRoute(
0 ignored issues
show
Documentation Bug introduced by
The method frontendUrl does not exist on object<PlaygroundGame\Co...rontend\GameController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
924
                        $this->game->getClassType() . '/login',
925
                        array('id' => $this->game->getIdentifier())
926
                    )
927
                );
928
            }
929
        }
930
931
        $redirect = $this->frontendUrl()->fromRoute(
0 ignored issues
show
Documentation Bug introduced by
The method frontendUrl does not exist on object<PlaygroundGame\Co...rontend\GameController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
932
            $this->game->getClassType().'/login',
933
            array(
934
                'id' => $this->game->getIdentifier(),
935
                
936
            )
937
        ) . ($socialnetwork ? '/' . $socialnetwork : ''). ($redirect ? '?redirect=' . $redirect : '');
938
939
        return $this->redirect()->toUrl($redirect);
940
    }
941
942
    /**
943
     *
944
     * @param \PlaygroundGame\Entity\Game $game
945
     * @param \PlaygroundUser\Entity\User $user
946
     */
947
    public function checkFbRegistration($user, $game)
948
    {
949
        $redirect = false;
950
        $session = new Container('facebook');
951
        if ($session->offsetExists('signed_request')) {
952
            if (!$user) {
953
                // Get Playground user from Facebook info
954
                $beforeLayout = $this->layout()->getTemplate();
0 ignored issues
show
Bug introduced by
The method getTemplate does only exist in Zend\View\Model\ModelInterface, but not in Zend\Mvc\Controller\Plugin\Layout.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
955
                $view = $this->forward()->dispatch(
956
                    'playgrounduser_user',
957
                    array(
958
                        'controller' => 'playgrounduser_user',
959
                        'action' => 'registerFacebookUser',
960
                        'provider' => 'facebook'
961
                    )
962
                );
963
964
                $this->layout()->setTemplate($beforeLayout);
965
                $user = $view->user;
966
967
                // If the user can not be created/retrieved from Facebook info, redirect to login/register form
968
                if (!$user) {
969
                    $redirectUrl = urlencode(
970
                        $this->frontendUrl()->fromRoute(
0 ignored issues
show
Documentation Bug introduced by
The method frontendUrl does not exist on object<PlaygroundGame\Co...rontend\GameController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
971
                            $game->getClassType() .'/play',
972
                            array('id' => $game->getIdentifier()),
973
                            array('force_canonical' => true)
974
                        )
975
                    );
976
                    $redirect =  $this->redirect()->toUrl(
977
                        $this->frontendUrl()->fromRoute(
0 ignored issues
show
Documentation Bug introduced by
The method frontendUrl does not exist on object<PlaygroundGame\Co...rontend\GameController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
978
                            'zfcuser/register'
979
                        ) . '?redirect='.$redirectUrl
980
                    );
981
                }
982
            }
983
984
            if ($game->getFbFan()) {
985
                if ($this->getGameService()->checkIsFan($game) === false) {
986
                    $redirect =  $this->redirect()->toRoute(
987
                        $game->getClassType().'/fangate',
988
                        array('id' => $game->getIdentifier())
989
                    );
990
                }
991
            }
992
        }
993
994
        return $redirect;
995
    }
996
997
    /**
998
     * This method create the basic Game view
999
     * @param \PlaygroundGame\Entity\Game $game
1000
     */
1001
    public function buildView($game)
1002
    {
1003
        if ($this->getRequest()->isXmlHttpRequest()) {
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Stdlib\RequestInterface as the method isXmlHttpRequest() does only exist in the following implementations of said interface: Zend\Http\PhpEnvironment\Request, Zend\Http\Request.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
1004
            $viewModel = new JsonModel();
1005
            if ($game) {
1006
                $view = $this->addAdditionalView($game);
1007
                if ($view && $view instanceof \Zend\View\Model\ViewModel) {
1008
                    $viewModel->setVariables($view->getVariables());
1009
                }
1010
            }
1011
        } else {
1012
            $viewModel = new ViewModel();
1013
1014
            if ($game) {
1015
                $this->addMetaTitle($game);
1016
                $this->addMetaBitly();
1017
                $this->addGaEvent($game);
1018
1019
                $this->customizeGameDesign($game);
1020
                
1021
                // this is possible to create a specific game design in /design/frontend/default/custom.
1022
                //It will precede all others templates.
1023
                $templatePathResolver = $this->getServiceLocator()->get('Zend\View\Resolver\TemplatePathStack');
1024
                $l = $templatePathResolver->getPaths();
1025
                $templatePathResolver->addPath($l[0].'custom/'.$game->getIdentifier());
1026
                
1027
                $view = $this->addAdditionalView($game);
1028
                if ($view && $view instanceof \Zend\View\Model\ViewModel) {
1029
                    $viewModel->addChild($view, 'additional');
1030
                } elseif ($view && $view instanceof \Zend\Http\PhpEnvironment\Response) {
1031
                    return $view;
1032
                }
1033
1034
                $this->layout()->setVariables(
0 ignored issues
show
Bug introduced by
The method setVariables does only exist in Zend\View\Model\ModelInterface, but not in Zend\Mvc\Controller\Plugin\Layout.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
1035
                    array(
1036
                        'action' => $this->params('action'),
1037
                        'game' => $game,
1038
                        'flashMessages'    => $this->flashMessenger()->getMessages(),
1039
                        
1040
                    )
1041
                );
1042
            }
1043
        }
1044
        
1045
        if ($game) {
1046
            $viewModel->setVariables($this->getShareData($game));
1047
            $viewModel->setVariables(array('game' => $game));
1048
        }
1049
1050
        return $viewModel;
1051
    }
1052
1053
    /**
1054
     * @param \PlaygroundGame\Entity\Game $game
1055
     */
1056
    public function addAdditionalView($game)
1057
    {
1058
        $view = false;
1059
1060
        $actionName = $this->getEvent()->getRouteMatch()->getParam('action', 'not-found');
1061
        $stepsViews = json_decode($game->getStepsViews(), true);
1062
        if ($stepsViews && isset($stepsViews[$actionName])) {
1063
            $beforeLayout = $this->layout()->getTemplate();
0 ignored issues
show
Bug introduced by
The method getTemplate does only exist in Zend\View\Model\ModelInterface, but not in Zend\Mvc\Controller\Plugin\Layout.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
1064
            $actionData = $stepsViews[$actionName];
1065
            if (is_string($actionData)) {
1066
                $action = $actionData;
1067
                $controller = $this->getEvent()->getRouteMatch()->getParam('controller', 'playgroundgame_game');
1068
                $view = $this->forward()->dispatch(
1069
                    $controller,
1070
                    array(
1071
                        'action' => $action,
1072
                        'id' => $game->getIdentifier()
1073
                    )
1074
                );
1075
            } elseif (is_array($actionData) && count($actionData)>0) {
1076
                $action = key($actionData);
1077
                $controller = $actionData[$action];
1078
                $view = $this->forward()->dispatch(
1079
                    $controller,
1080
                    array(
1081
                        'action' => $action,
1082
                        'id' => $game->getIdentifier()
1083
                    )
1084
                );
1085
            }
1086
            // suite au forward, le template de layout a changé, je dois le rétablir...
1087
            $this->layout()->setTemplate($beforeLayout);
1088
        }
1089
1090
        return $view;
1091
    }
1092
1093
    public function addMetaBitly()
1094
    {
1095
        $bitlyclient = $this->getOptions()->getBitlyUrl();
1096
        $bitlyuser = $this->getOptions()->getBitlyUsername();
1097
        $bitlykey = $this->getOptions()->getBitlyApiKey();
1098
1099
        $this->getViewHelper('HeadMeta')->setProperty('bt:client', $bitlyclient);
1100
        $this->getViewHelper('HeadMeta')->setProperty('bt:user', $bitlyuser);
1101
        $this->getViewHelper('HeadMeta')->setProperty('bt:key', $bitlykey);
1102
    }
1103
1104
    /**
1105
     * @param \PlaygroundGame\Entity\Game $game
1106
     */
1107
    public function addGaEvent($game)
1108
    {
1109
        // Google Analytics event
1110
        $ga = $this->getServiceLocator()->get('google-analytics');
1111
        $event = new \PlaygroundCore\Analytics\Event($game->getClassType(), $this->params('action'));
1112
        $event->setLabel($game->getTitle());
1113
        $ga->addEvent($event);
1114
    }
1115
1116
    /**
1117
     * @param \PlaygroundGame\Entity\Game $game
1118
     */
1119
    public function addMetaTitle($game)
1120
    {
1121
        $title = $this->translate($game->getTitle());
0 ignored issues
show
Documentation Bug introduced by
The method translate does not exist on object<PlaygroundGame\Co...rontend\GameController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
1122
        $this->getGameService()->getServiceManager()->get('ViewHelperManager')->get('HeadTitle')->set($title);
1123
        // Meta set in the layout
1124
        $this->layout()->setVariables(
0 ignored issues
show
Bug introduced by
The method setVariables does only exist in Zend\View\Model\ModelInterface, but not in Zend\Mvc\Controller\Plugin\Layout.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
1125
            array(
1126
                'breadcrumbTitle' => $title,
1127
                'currentPage' => array(
1128
                    'pageGames' => 'games',
1129
                    'pageWinners' => ''
1130
                ),
1131
                'headParams' => array(
1132
                    'headTitle' => $title,
1133
                    'headDescription' => $title,
1134
                ),
1135
                'bodyCss' => $game->getIdentifier()
1136
            )
1137
        );
1138
    }
1139
1140
    /**
1141
     * @param \PlaygroundGame\Entity\Game $game
1142
     */
1143
    public function customizeGameDesign($game)
1144
    {
1145
        // If this game has a specific layout...
1146
        if ($game->getLayout()) {
1147
            $layoutViewModel = $this->layout();
1148
            $layoutViewModel->setTemplate($game->getLayout());
1149
        }
1150
1151
        // If this game has a specific stylesheet...
1152
        if ($game->getStylesheet()) {
1153
            $this->getViewHelper('HeadLink')->appendStylesheet(
1154
                $this->getRequest()->getBaseUrl(). '/' . $game->getStylesheet()
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Stdlib\RequestInterface as the method getBaseUrl() does only exist in the following implementations of said interface: Zend\Http\PhpEnvironment\Request.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
1155
            );
1156
        }
1157
    }
1158
1159
    /**
1160
     * @param \PlaygroundGame\Entity\Game $game
1161
     */
1162
    public function getShareData($game)
1163
    {
1164
        $fo = $this->getServiceLocator()->get('facebook-opengraph');
1165
        $session = new Container('facebook');
1166
1167
        // I change the fbappid if i'm in fb
1168
        if ($session->offsetExists('signed_request')) {
1169
            $fo->setId($game->getFbAppId());
1170
        }
1171
1172
        // If I want to add a share block in my view
1173 View Code Duplication
        if ($game->getFbShareMessage()) {
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...
1174
            $fbShareMessage = $game->getFbShareMessage();
1175
        } else {
1176
            $fbShareMessage = str_replace(
1177
                '__placeholder__',
1178
                $game->getTitle(),
1179
                $this->getOptions()->getDefaultShareMessage()
1180
            );
1181
        }
1182
1183
        if ($game->getFbShareImage()) {
1184
            $fbShareImage = $this->frontendUrl()->fromRoute(
0 ignored issues
show
Documentation Bug introduced by
The method frontendUrl does not exist on object<PlaygroundGame\Co...rontend\GameController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
1185
                '',
1186
                array(),
1187
                array('force_canonical' => true),
1188
                false
1189
            ) . $game->getFbShareImage();
1190
        } else {
1191
            $fbShareImage = $this->frontendUrl()->fromRoute(
0 ignored issues
show
Documentation Bug introduced by
The method frontendUrl does not exist on object<PlaygroundGame\Co...rontend\GameController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
1192
                '',
1193
                array(),
1194
                array('force_canonical' => true),
1195
                false
1196
            ) . $game->getMainImage();
1197
        }
1198
1199
        $secretKey = strtoupper(substr(sha1(uniqid('pg_', true).'####'.time()), 0, 15));
1200
1201
        // Without bit.ly shortener
1202
        $socialLinkUrl = $this->frontendUrl()->fromRoute(
0 ignored issues
show
Documentation Bug introduced by
The method frontendUrl does not exist on object<PlaygroundGame\Co...rontend\GameController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
1203
            $game->getClassType(),
1204
            array('id' => $game->getIdentifier()),
1205
            array('force_canonical' => true)
1206
        );
1207
        // With core shortener helper
1208
        $socialLinkUrl = $this->shortenUrl()->shortenUrl($socialLinkUrl);
0 ignored issues
show
Documentation Bug introduced by
The method shortenUrl does not exist on object<PlaygroundGame\Co...rontend\GameController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
1209
1210
        // FB Requests only work when it's a FB app
1211
        if ($game->getFbRequestMessage()) {
1212
            $fbRequestMessage = urlencode($game->getFbRequestMessage());
1213
        } else {
1214
            $fbRequestMessage = str_replace(
1215
                '__placeholder__',
1216
                $game->getTitle(),
1217
                $this->getOptions()->getDefaultShareMessage()
1218
            );
1219
        }
1220
1221 View Code Duplication
        if ($game->getTwShareMessage()) {
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...
1222
            $twShareMessage = $game->getTwShareMessage() . $socialLinkUrl;
1223
        } else {
1224
            $twShareMessage = str_replace(
1225
                '__placeholder__',
1226
                $game->getTitle(),
1227
                $this->getOptions()->getDefaultShareMessage()
1228
            ) . $socialLinkUrl;
1229
        }
1230
1231
        $ogTitle = new \PlaygroundCore\Opengraph\Tag('og:title', $fbShareMessage);
1232
        $ogImage = new \PlaygroundCore\Opengraph\Tag('og:image', $fbShareImage);
1233
        
1234
        $fo->addTag($ogTitle);
1235
        $fo->addTag($ogImage);
1236
        
1237
        $data = array(
1238
            'socialLinkUrl'       => $socialLinkUrl,
1239
            'secretKey'           => $secretKey,
1240
            'fbShareMessage'      => $fbShareMessage,
1241
            'fbShareImage'        => $fbShareImage,
1242
            'fbRequestMessage'    => $fbRequestMessage,
1243
            'twShareMessage'      => $twShareMessage,
1244
        );
1245
1246
        return $data;
1247
    }
1248
    
1249
    /**
1250
     * return ajax response in json format
1251
     *
1252
     * @param array $data
1253
     * @return \Zend\View\Model\JsonModel
1254
     */
1255 View Code Duplication
    protected function successJson($data = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1256
    {
1257
        $model = new JsonModel(array(
1258
            'success' => true,
1259
            'data' => $data
1260
        ));
1261
        return $model->setTerminal(true);
1262
    }
1263
    
1264
    /**
1265
     * return ajax response in json format
1266
     *
1267
     * @param string $message
1268
     * @return \Zend\View\Model\JsonModel
1269
     */
1270 View Code Duplication
    protected function errorJson($message = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1271
    {
1272
        $model = new JsonModel(array(
1273
            'success' => false,
1274
            'message' => $message
1275
        ));
1276
        return $model->setTerminal(true);
1277
    }
1278
1279
    /**
1280
     * @param string $helperName
1281
     */
1282
    protected function getViewHelper($helperName)
1283
    {
1284
        return $this->getServiceLocator()->get('viewhelpermanager')->get($helperName);
1285
    }
1286
1287
    public function getGameService()
1288
    {
1289
        if (!$this->gameService) {
1290
            $this->gameService = $this->getServiceLocator()->get('playgroundgame_lottery_service');
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->getServiceLocator...dgame_lottery_service') can also be of type array. However, the property $gameService is declared as type object<PlaygroundGame\Service\GameService>. 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...
1291
        }
1292
1293
        return $this->gameService;
1294
    }
1295
1296
    public function setGameService(GameService $gameService)
1297
    {
1298
        $this->gameService = $gameService;
1299
1300
        return $this;
1301
    }
1302
1303
    public function getPrizeService()
1304
    {
1305
        if (!$this->prizeService) {
1306
            $this->prizeService = $this->getServiceLocator()->get('playgroundgame_prize_service');
1307
        }
1308
1309
        return $this->prizeService;
1310
    }
1311
1312
    public function setPrizeService(PrizeService $prizeService)
1313
    {
1314
        $this->prizeService = $prizeService;
1315
1316
        return $this;
1317
    }
1318
1319
    public function getOptions()
1320
    {
1321
        if (!$this->options) {
1322
            $this->setOptions($this->getServiceLocator()->get('playgroundcore_module_options'));
1323
        }
1324
1325
        return $this->options;
1326
    }
1327
1328
    public function setOptions($options)
1329
    {
1330
        $this->options = $options;
1331
1332
        return $this;
1333
    }
1334
}
1335