Completed
Push — master ( 794574...c83386 )
by greg
11:38 queued 07:13
created

GameController::leaderboardAction()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 22
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 7
Bugs 1 Features 0
Metric Value
c 7
b 1
f 0
dl 0
loc 22
rs 9.2
cc 1
eloc 12
nc 1
nop 0
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
            if ($controller->game) {
86
                // this is possible to create a specific game design in /design/frontend/default/custom.
87
                //It will precede all others templates.
88
                $templatePathResolver = $controller->getServiceLocator()->get('Zend\View\Resolver\TemplatePathStack');
89
                $l = $templatePathResolver->getPaths();
90
                $templatePathResolver->addPath($l[0].'custom/'.$controller->game->getIdentifier());
91
            }
92
93
            $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...
94
            if ($controller->game &&
95
                !$controller->user &&
96
                !$controller->game->getAnonymousAllowed() &&
97
                in_array($controller->params('action'), $controller->withAnyUser)
98
            ) {
99
                $redirect = urlencode(
100
                    $controller->url()->fromRoute(
101
                        'frontend/'.$controller->game->getClassType() . '/' . $controller->params('action'),
102
                        array('id' => $controller->game->getIdentifier()),
103
                        array('force_canonical' => true)
104
                    )
105
                );
106
107
                $urlRegister = $controller->url()->fromRoute(
108
                    'frontend/zfcuser/register',
109
                    array(),
110
                    array('force_canonical' => true)
111
                ) . '?redirect='.$redirect;
112
113
                // code permettant d'identifier un custom game
114
                // ligne $config = $controller->getGameService()->getServiceManager()->get('config');
115
                // ligne $customUrl = str_replace('frontend.', '', $e->getRouteMatch()->getParam('area', ''));
116
                // ligne if ($config['custom_games'][$controller->game->getIdentifier()] &&
117
                // ligne    $controller->getRequest()->getUri()->getHost() === $customUrl
118
                // ligne ) {
119
                return $controller->redirect()->toUrl($urlRegister);
120
            }
121
122
            return;
123
        }, 100); // execute before executing action logic
124
    }
125
126
    /**
127
     * Action called if matched action does not exist
128
     * For this view not to be catched by Zend\Mvc\View\RouteNotFoundStrategy
129
     * it has to be rendered in the controller. Hence the code below.
130
     *
131
     * This action is injected as a catchall action for each custom_games definition
132
     * This way, when a custom_game is created, the 404 is it's responsability and the
133
     * view can be defined in design/frontend/default/custom/$slug/playground_game/$gametype/404.phtml
134
     *
135
     *
136
     * @return \Zend\Stdlib\ResponseInterface
137
     */
138
    public function notFoundAction()
139
    {
140
        $viewRender     = $this->getServiceLocator()->get('ViewRenderer');
141
142
        $this->getEvent()->getRouteMatch()->setParam('action', 'not-found');
143
        $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...
144
145
        $res = 'error/404';
146
147
        $viewModel = $this->buildView($this->game);
148
        $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...
149
150
        $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...
151
        $this->response->setContent($viewRender->render($this->layout()));
152
153
        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...
154
    }
155
156
    /**
157
     * This action acts as a hub : Depending on the first step of the game, it will forward the action to this step
158
     */
159
    public function homeAction()
160
    {
161
        // This fix exists only for safari in FB on Windows : we need to redirect the user to the page
162
        // outside of iframe for the cookie to be accepted. PlaygroundCore redirects to the FB Iframed page when
163
        // it discovers that the user arrives for the first time on the game in FB.
164
        // When core redirects, it adds a 'redir_fb_page_id' var in the querystring
165
        // Here, we test if this var exist, and then send the user back to the game in FB.
166
        // Now the cookie will be accepted by Safari...
167
        $pageId = $this->params()->fromQuery('redir_fb_page_id');
168
        if (!empty($pageId)) {
169
            $appId = 'app_'.$this->game->getFbAppId();
170
            $url = '//www.facebook.com/pages/game/'.$pageId.'?sk='.$appId;
171
172
            return $this->redirect()->toUrl($url);
173
        }
174
175
        // If an entry has already been done during this session, I reset the anonymous_identifier cookie
176
        // so that another person can play the same game (if game conditions are fullfilled)
177
        $session = new Container('anonymous_identifier');
178
        if ($session->offsetExists('anonymous_identifier')) {
179
            $session->offsetUnset('anonymous_identifier');
180
        }
181
        
182
        return $this->forward()->dispatch(
183
            'playgroundgame_'.$this->game->getClassType(),
184
            array(
185
                'controller' => 'playgroundgame_'.$this->game->getClassType(),
186
                'action' => $this->game->firstStep(),
187
                'id' => $this->game->getIdentifier()
188
            )
189
        );
190
    }
191
192
    /**
193
     * Homepage of the game
194
     */
195
    public function indexAction()
196
    {
197
        $isSubscribed = false;
198
199
        $entry = $this->getGameService()->checkExistingEntry($this->game, $this->user);
200
        if ($entry) {
201
            $isSubscribed = true;
202
        }
203
204
        $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 209 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...
205
        $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...
206
            'isSubscribed' => $isSubscribed
207
        ));
208
209
        return $viewModel;
210
    }
211
212
    /**
213
      * leaderboardAction
214
      *
215
      * @return ViewModel $viewModel
216
      */
217
    public function leaderboardAction()
218
    {
219
        $filter = $this->getEvent()->getRouteMatch()->getParam('filter');
220
        $p = $this->getEvent()->getRouteMatch()->getParam('p');
221
222
        $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...
223
        $subViewModel = $this->forward()->dispatch(
224
            'playgroundreward',
225
            array('action' => 'leaderboard', 'filter' => $filter, 'p' => $p)
226
        );
227
        
228
        // suite au forward, le template de layout a changé, je dois le rétablir...
229
        $this->layout()->setTemplate($beforeLayout);
230
231
        // give the ability to the game to have its customized look and feel.
232
        $templatePathResolver = $this->getServiceLocator()->get('Zend\View\Resolver\TemplatePathStack');
233
        $l = $templatePathResolver->getPaths();
234
235
        $templatePathResolver->addPath($l[0].'custom/'.$this->game->getIdentifier());
236
237
        return $subViewModel;
238
    }
239
240
    /**
241
     * This action has been designed to be called by other controllers
242
     * It gives the ability to display an information form and persist it in the game entry
243
     *
244
     * @return \Zend\View\Model\ViewModel
245
     */
246
    public function registerAction()
247
    {
248
        $form = $this->getGameService()->createFormFromJson($this->game->getPlayerForm()->getForm(), 'playerForm');
249
250
        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...
251
            // POST Request: Process form
252
            $data = array_merge_recursive(
253
                $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...
254
                $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...
255
            );
256
            
257
            $form->setData($data);
258
259
            if ($form->isValid()) {
260
                // steps of the game
261
                $steps = $this->game->getStepsArray();
262
                // sub steps of the game
263
                $viewSteps = $this->game->getStepsViewsArray();
264
265
                // register position
266
                $key = array_search($this->params('action'), $viewSteps);
267 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...
268
                    // register is not a substep of the game so it's a step
269
                    $key = array_search($this->params('action'), $steps);
270
                    $keyStep = true;
271
                } else {
272
                    // register was a substep, i search the index of its parent
273
                    $key = array_search($key, $steps);
274
                    $keyStep = false;
275
                }
276
277
                // play position
278
                $keyplay = array_search('play', $viewSteps);
279
280 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...
281
                    // play is not a substep, so it's a step
282
                    $keyplay = array_search('play', $steps);
283
                    $keyplayStep = true;
284
                } else {
285
                    // play is a substep so I search the index of its parent
286
                    $keyplay = array_search($keyplay, $steps);
287
                    $keyplayStep = false;
288
                }
289
290
                // If register step before play, I don't have no entry yet. I have to create one
291
                // If register after play step, I search for the last entry created by play step.
292
293
                if ($key < $keyplay || ($keyStep && !$keyplayStep && $key <= $keyplay)) {
294
                    $entry = $this->getGameService()->play($this->game, $this->user);
295
                    if (!$entry) {
296
                        // the user has already taken part of this game and the participation limit has been reached
297
                        $this->flashMessenger()->addMessage('Vous avez déjà participé');
298
                    
299
                        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...
300
                            $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...
301
                                $this->game->getClassType().'/result',
302
                                array(
303
                                    'id' => $this->game->getIdentifier(),
304
                                    
305
                                )
306
                            )
307
                        );
308
                    }
309
                } else {
310
                    // I'm looking for an entry without anonymousIdentifier (the active entry in fact).
311
                    $entry = $this->getGameService()->findLastEntry($this->game, $this->user);
312
                    if ($this->getGameService()->hasReachedPlayLimit($this->game, $this->user)) {
313
                        // the user has already taken part of this game and the participation limit has been reached
314
                        $this->flashMessenger()->addMessage('Vous avez déjà participé');
315
                    
316
                        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...
317
                            $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...
318
                                $this->game->getClassType().'/result',
319
                                array(
320
                                    'id' => $this->game->getIdentifier(),
321
                                    
322
                                )
323
                            )
324
                        );
325
                    }
326
                }
327
328
                $this->getGameService()->updateEntryPlayerForm($form->getData(), $this->game, $this->user, $entry);
329
330
                if (!empty($this->game->nextStep($this->params('action')))) {
331
                    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...
332
                        $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...
333
                            $this->game->getClassType() .'/' . $this->game->nextStep($this->params('action')),
334
                            array('id' => $this->game->getIdentifier()),
335
                            array('force_canonical' => true)
336
                        )
337
                    );
338
                }
339
            }
340
        }
341
342
        $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 347 which is incompatible with the return type documented by PlaygroundGame\Controlle...troller::registerAction of type Zend\View\Model\ViewModel.
Loading history...
343
        $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...
344
            'form' => $form
345
        ));
346
347
        return $viewModel;
348
    }
349
350
    /**
351
     * This action takes care of the terms of the game
352
     */
353
    public function termsAction()
354
    {
355
        $viewModel = $this->buildView($this->game);
356
357
        return $viewModel;
358
    }
359
360
    /**
361
     * This action takes care of the conditions of the game
362
     */
363
    public function conditionsAction()
364
    {
365
        $viewModel = $this->buildView($this->game);
366
367
        return $viewModel;
368
    }
369
370
    /**
371
     * This action takes care of bounce page of the game
372
     */
373
    public function bounceAction()
374
    {
375
        $availableGames = $this->getGameService()->getAvailableGames($this->user);
376
377
        $rssUrl = '';
378
        $config = $this->getGameService()->getServiceManager()->get('config');
379
        if (isset($config['rss']['url'])) {
380
            $rssUrl = $config['rss']['url'];
381
        }
382
383
        $viewModel = $this->buildView($this->game);
384
        $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...
385
            'rssUrl'         => $rssUrl,
386
            'user'           => $this->user,
387
            'availableGames' => $availableGames,
388
        ));
389
390
        return $viewModel;
391
    }
392
393
394
    /**
395
     * This action displays the Prizes page associated to the game
396
     */
397
    public function prizesAction()
398
    {
399
        if (count($this->game->getPrizes()) == 0) {
400
            return $this->notFoundAction();
401
        }
402
403
        $viewModel = $this->buildView($this->game);
404
405
        return $viewModel;
406
    }
407
408
    /**
409
     * This action displays a specific Prize page among those associated to the game
410
     */
411
    public function prizeAction()
412
    {
413
        $prizeIdentifier = $this->getEvent()->getRouteMatch()->getParam('prize');
414
        $prize = $this->getPrizeService()->getPrizeMapper()->findByIdentifier($prizeIdentifier);
415
        
416
        if (!$prize) {
417
            return $this->notFoundAction();
418
        }
419
420
        $viewModel = $this->buildView($this->game);
421
        $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...
422
423
        return $viewModel;
424
    }
425
426
    public function gameslistAction()
427
    {
428
        $layoutViewModel = $this->layout();
429
430
        $slider = new ViewModel();
431
        $slider->setTemplate('playground-game/common/top_promo');
432
433
        $sliderItems = $this->getGameService()->getActiveSliderGames();
434
435
        $slider->setVariables(array('sliderItems' => $sliderItems));
436
437
        $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...
438
439
        $games = $this->getGameService()->getActiveGames(false, '', 'endDate');
440
        if (is_array($games)) {
441
            $paginator = new \Zend\Paginator\Paginator(new \Zend\Paginator\Adapter\ArrayAdapter($games));
442
        } else {
443
            $paginator = $games;
444
        }
445
446
        $paginator->setItemCountPerPage(7);
447
        $paginator->setCurrentPageNumber($this->getEvent()->getRouteMatch()->getParam('p'));
448
449
        $bitlyclient = $this->getOptions()->getBitlyUrl();
450
        $bitlyuser = $this->getOptions()->getBitlyUsername();
451
        $bitlykey = $this->getOptions()->getBitlyApiKey();
452
453
        $this->getViewHelper('HeadMeta')->setProperty('bt:client', $bitlyclient);
454
        $this->getViewHelper('HeadMeta')->setProperty('bt:user', $bitlyuser);
455
        $this->getViewHelper('HeadMeta')->setProperty('bt:key', $bitlykey);
456
457
        $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...
458
            array(
459
            'sliderItems'   => $sliderItems,
460
            'currentPage' => array(
461
                'pageGames' => 'games',
462
                'pageWinners' => ''
463
            ),
464
            )
465
        );
466
467
        return new ViewModel(
468
            array(
469
                'games' => $paginator
470
            )
471
        );
472
    }
473
474
    public function fangateAction()
475
    {
476
        $viewModel = $this->buildView($this->game);
477
478
        return $viewModel;
479
    }
480
    
481
    public function shareAction()
482
    {
483
        $statusMail = null;
484
        $lastEntry = null;
485
    
486
        // steps of the game
487
        $steps = $this->game->getStepsArray();
488
        // sub steps of the game
489
        $viewSteps = $this->game->getStepsViewsArray();
490
491
        // share position
492
        $key = array_search($this->params('action'), $viewSteps);
493 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...
494
            // share is not a substep of the game so it's a step
495
            $key = array_search($this->params('action'), $steps);
496
            $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...
497
        } else {
498
            // share was a substep, I search the index of its parent
499
            $key = array_search($key, $steps);
500
            $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...
501
        }
502
503
        // play position
504
        $keyplay = array_search('play', $viewSteps);
505
506 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...
507
            // play is not a substep, so it's a step
508
            $keyplay = array_search('play', $steps);
509
            $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...
510
        } else {
511
            // play is a substep so I search the index of its parent
512
            $keyplay = array_search($keyplay, $steps);
513
            $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...
514
        }
515
516
        if ($key && $keyplay && $keyplay <= $key) {
517
            // Has the user finished the game ?
518
            $lastEntry = $this->getGameService()->findLastInactiveEntry($this->game, $this->user);
519
    
520 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...
521
                return $this->redirect()->toUrl(
522
                    $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...
523
                        $this->game->getClassType(),
524
                        array('id' => $this->game->getIdentifier())
525
                    )
526
                );
527
            }
528
        }
529
    
530
        $form = $this->getServiceLocator()->get('playgroundgame_sharemail_form');
531
        $form->setAttribute('method', 'post');
532
533
        // buildView must be before sendMail because it adds the game template path to the templateStack
534
        $viewModel = $this->buildView($this->game);
535
    
536
        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...
537
            $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...
538
            $form->setData($data);
539 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...
540
                $result = $this->getGameService()->sendShareMail($data, $this->game, $this->user, $lastEntry);
541
                if ($result) {
542
                    $statusMail = true;
543
                }
544
            }
545
        }
546
547
        $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...
548
            'statusMail'       => $statusMail,
549
            'form'             => $form,
550
        ));
551
    
552
        return $viewModel;
553
    }
554
    
555 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...
556
    {
557
        $viewModel = new JsonModel();
558
        $viewModel->setTerminal(true);
559
        $fbId = $this->params()->fromQuery('fbId');
560
        if (!$this->game) {
561
            return $this->errorJson();
562
        }
563
        $entry = $this->getGameService()->checkExistingEntry($this->game, $this->user);
564
        if (! $entry) {
565
            return $this->errorJson();
566
        }
567
        if (!$fbId) {
568
            return $this->errorJson();
569
        }
570
    
571
        $this->getGameService()->postFbWall($fbId, $this->game, $this->user, $entry);
572
    
573
        return $this->successJson();
574
    }
575
    
576
    public function fbrequestAction()
577
    {
578
        $viewModel = new ViewModel();
579
        $viewModel->setTerminal(true);
580
        $fbId = $this->params()->fromQuery('fbId');
581
        $to = $this->params()->fromQuery('to');
582
    
583
        if (!$this->game) {
584
            return $this->errorJson();
585
        }
586
        $entry = $this->getGameService()->checkExistingEntry($this->game, $this->user);
587
        if (! $entry) {
588
            return $this->errorJson();
589
        }
590
        if (!$fbId) {
591
            return $this->errorJson();
592
        }
593
    
594
        $this->getGameService()->postFbRequest($fbId, $this->game, $this->user, $entry, $to);
595
    
596
        return $this->successJson();
597
    }
598
    
599
    public function tweetAction()
600
    {
601
        $tweetId = $this->params()->fromQuery('tweetId');
602
    
603
        if (!$this->game) {
604
            return $this->errorJson();
605
        }
606
        $entry = $this->getGameService()->checkExistingEntry($this->game, $this->user);
607
        if (! $entry) {
608
            return $this->errorJson();
609
        }
610
        if (!$tweetId) {
611
            return $this->errorJson();
612
        }
613
    
614
        $this->getGameService()->postTwitter($tweetId, $this->game, $this->user, $entry);
615
    
616
        return $this->successJson();
617
    }
618
    
619 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...
620
    {
621
        $viewModel = new ViewModel();
622
        $viewModel->setTerminal(true);
623
        $googleId = $this->params()->fromQuery('googleId');
624
625
        if (!$this->game) {
626
            return $this->errorJson();
627
        }
628
        $entry = $this->getGameService()->checkExistingEntry($this->game, $this->user);
629
        if (! $entry) {
630
            return $this->errorJson();
631
        }
632
        if (!$googleId) {
633
            return $this->errorJson();
634
        }
635
    
636
        $this->getGameService()->postGoogle($googleId, $this->game, $this->user, $entry);
637
    
638
        return $this->successJson();
639
    }
640
641
    public function optinAction()
642
    {
643
        $userService = $this->getServiceLocator()->get('zfcuser_user_service');
644
645
        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...
646
            $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...
647
            $data['optinPartner'] = ($this->params()->fromPost('optinPartner'))? 1:0;
648
649
            $userService->updateNewsletter($data);
650
        }
651
652
        return $this->redirect()->toUrl(
653
            $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...
654
                'frontend/' . $this->game->getClassType() . '/index',
655
                array('id' => $this->game->getIdentifier())
656
            )
657
        );
658
    }
659
    
660
    public function loginAction()
661
    {
662
        $request = $this->getRequest();
663
        $form = $this->getServiceLocator()->get('zfcuser_login_form');
664
    
665
        if ($request->isPost()) {
666
            $form->setData($request->getPost());
667
            
668
            if (!$form->isValid()) {
669
                $this->flashMessenger()->addMessage(
670
                    'Authentication failed. Please try again.'
671
                );
672
673
                $viewModel = $this->buildView($this->game);
674
                $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...
675
                    'form' => $form,
676
                    'flashMessages' => $this->flashMessenger()->getMessages(),
677
                ));
678
                
679
                return $viewModel;
680
            }
681
            
682
            // clear adapters
683
            $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...
684
            $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...
685
686
            $logged = $this->forward()->dispatch('playgrounduser_user', array('action' => 'ajaxauthenticate'));
687
688
            if (!$logged) {
689
                $this->flashMessenger()->addMessage(
690
                    'Authentication failed. Please try again.'
691
                );
692
                
693
                return $this->redirect()->toUrl(
694
                    $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...
695
                        $this->game->getClassType() . '/login',
696
                        array('id' => $this->game->getIdentifier())
697
                    )
698
                );
699
            } else {
700
                return $this->redirect()->toUrl(
701
                    $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...
702
                        $this->game->getClassType() . '/index',
703
                        array('id' => $this->game->getIdentifier())
704
                    )
705
                );
706
            }
707
        }
708
        
709
        $form->setAttribute(
710
            'action',
711
            $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...
712
                $this->game->getClassType().'/login',
713
                array('id' => $this->game->getIdentifier())
714
            )
715
        );
716
        $viewModel = $this->buildView($this->game);
717
        $viewModel->setVariables(array(
718
            'form' => $form,
719
            'flashMessages' => $this->flashMessenger()->getMessages(),
720
        ));
721
        return $viewModel;
722
    }
723
724
    public function userregisterAction()
725
    {
726
        $userOptions = $this->getServiceLocator()->get('zfcuser_module_options');
727
728
        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...
729
            return $this->redirect()->toUrl(
730
                $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...
731
                    $this->game->getClassType().'/'.$this->game->nextStep('index'),
732
                    array('id' => $this->game->getIdentifier())
733
                )
734
            );
735
        }
736
        $request = $this->getRequest();
737
        $service = $this->getServiceLocator()->get('zfcuser_user_service');
738
        $form = $this->getServiceLocator()->get('playgroundgame_register_form');
739
        $socialnetwork = $this->params()->fromRoute('socialnetwork', false);
740
        $form->setAttribute(
741
            'action',
742
            $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...
743
                $this->game->getClassType().'/user-register',
744
                array('id' => $this->game->getIdentifier())
745
            )
746
        );
747
        $params = array();
748
        $socialCredentials = array();
749
750
        if ($userOptions->getUseRedirectParameterIfPresent() && $request->getQuery()->get('redirect')) {
751
            $redirect = $request->getQuery()->get('redirect');
752
        } else {
753
            $redirect = false;
754
        }
755
756
        if ($socialnetwork) {
757
            $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...
758
759
            if (!empty($infoMe)) {
760
                $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...
761
                    $infoMe->identifier,
762
                    $socialnetwork
763
                );
764
765
                if ($user || $service->getOptions()->getCreateUserAutoSocial() === true) {
766
                    //on le dirige vers l'action d'authentification
767
                    if (! $redirect && $userOptions->getLoginRedirectRoute() != '') {
768
                        $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...
769
                            $this->game->getClassType().'/login',
770
                            array('id' => $this->game->getIdentifier())
771
                        );
772
                    }
773
                    $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...
774
                        $this->game->getClassType().'/login',
775
                        array('id' => $this->game->getIdentifier())
776
                    ) .'/' . $socialnetwork . ($redirect ? '?redirect=' . $redirect : '');
777
778
                    return $this->redirect()->toUrl($redir);
779
                }
780
781
                // Je retire la saisie du login/mdp
782
                $form->setAttribute(
783
                    'action',
784
                    $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...
785
                        $this->game->getClassType().'/user-register',
786
                        array(
787
                            'id' => $this->game->getIdentifier(),
788
                            'socialnetwork' => $socialnetwork,
789
                            
790
                        )
791
                    )
792
                );
793
                $form->remove('password');
794
                $form->remove('passwordVerify');
795
796
                $birthMonth = $infoMe->birthMonth;
797
                if (strlen($birthMonth) <= 1) {
798
                    $birthMonth = '0'.$birthMonth;
799
                }
800
                $birthDay = $infoMe->birthDay;
801
                if (strlen($birthDay) <= 1) {
802
                    $birthDay = '0'.$birthDay;
803
                }
804
805
                $gender = $infoMe->gender;
806
                if ($gender == 'female') {
807
                    $title = 'Me';
808
                } else {
809
                    $title = 'M';
810
                }
811
812
                $params = array(
813
                    //'birth_year'  => $infoMe->birthYear,
814
                    'title'      => $title,
815
                    'dob'      => $birthDay.'/'.$birthMonth.'/'.$infoMe->birthYear,
816
                    'firstname'   => $infoMe->firstName,
817
                    'lastname'    => $infoMe->lastName,
818
                    'email'       => $infoMe->email,
819
                    'postalCode' => $infoMe->zip,
820
                );
821
                $socialCredentials = array(
822
                    'socialNetwork' => strtolower($socialnetwork),
823
                    'socialId'      => $infoMe->identifier,
824
                );
825
            }
826
        }
827
828
        $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...
829
            $this->game->getClassType().'/user-register',
830
            array('id' => $this->game->getIdentifier())
831
        ) .($socialnetwork ? '/' . $socialnetwork : ''). ($redirect ? '?redirect=' . $redirect : '');
832
        $prg = $this->prg($redirectUrl, true);
833
834
        if ($prg instanceof Response) {
835
            return $prg;
836
        } elseif ($prg === false) {
837
            $form->setData($params);
838
            $viewModel = $this->buildView($this->game);
839
            $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...
840
                'registerForm' => $form,
841
                'enableRegistration' => $userOptions->getEnableRegistration(),
842
                'redirect' => $redirect,
843
            ));
844
            return $viewModel;
845
        }
846
847
        $post = $prg;
848
        $post = array_merge(
849
            $post,
850
            $socialCredentials
851
        );
852
853
        if ($this->game->getOnInvitation()) {
854
            $credential = trim(
855
                $post[$this->getGameService()->getOptions()->getOnInvitationField()]
856
            );
857
            if (!$credential) {
858
                $credential = $this->params()->fromQuery(
859
                    $this->getGameService()->getOptions()->getOnInvitationField()
860
                );
861
            }
862
            $found = $this->getGameService()->getInvitationMapper()->findOneBy(array('requestKey'=>$credential));
863
864
            if (!$found || !empty($found->getUser())) {
865
                $this->flashMessenger()->addMessage(
866
                    'Authentication failed. Please try again.'
867
                );
868
                $form->setData($post);
869
                $viewModel = $this->buildView($this->game);
870
                $viewModel->setVariables(array(
871
                    'registerForm' => $form,
872
                    'enableRegistration' => $userOptions->getEnableRegistration(),
873
                    'redirect' => $redirect,
874
                    'flashMessages'    => $this->flashMessenger()->getMessages(),
875
                    'flashErrors'      => $this->flashMessenger()->getErrorMessages(),
876
                ));
877
878
                return $viewModel;
879
            }
880
        }
881
882
        $user = $service->register($post, 'playgroundgame_register_form');
883
884
        if (! $user) {
885
            $viewModel = $this->buildView($this->game);
886
            $viewModel->setVariables(array(
887
                'registerForm' => $form,
888
                'enableRegistration' => $userOptions->getEnableRegistration(),
889
                'redirect' => $redirect,
890
            ));
891
            
892
            return $viewModel;
893
        }
894
895
        if ($this->game->getOnInvitation()) {
896
            // user has been created, associate the code with the userId
897
            $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...
898
            $this->getGameService()->getInvitationMapper()->update($found);
899
        }
900
901
        if ($service->getOptions()->getEmailVerification()) {
902
            $vm = new ViewModel(array('userEmail' => $user->getEmail()));
903
            $vm->setTemplate('playground-user/register/registermail');
904
905
            return $vm;
906
        } elseif ($service->getOptions()->getLoginAfterRegistration()) {
907
            $identityFields = $service->getOptions()->getAuthIdentityFields();
908
            if (in_array('email', $identityFields)) {
909
                $post['identity'] = $user->getEmail();
910
            } elseif (in_array('username', $identityFields)) {
911
                $post['identity'] = $user->getUsername();
912
            }
913
            $post['credential'] = isset($post['password'])?$post['password']:'';
914
            $request->setPost(new Parameters($post));
915
916
            // clear adapters
917
            $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...
918
            $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...
919
920
            $logged = $this->forward()->dispatch('playgrounduser_user', array('action' => 'ajaxauthenticate'));
921
922
            if ($logged) {
923
                return $this->redirect()->toUrl(
924
                    $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...
925
                        $this->game->getClassType(),
926
                        array('id' => $this->game->getIdentifier())
927
                    )
928
                );
929
            } else {
930
                $this->flashMessenger()->setNamespace('zfcuser-login-form')->addMessage(
931
                    'Authentication failed. Please try again.'
932
                );
933
                return $this->redirect()->toUrl(
934
                    $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...
935
                        $this->game->getClassType() . '/login',
936
                        array('id' => $this->game->getIdentifier())
937
                    )
938
                );
939
            }
940
        }
941
942
        $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...
943
            $this->game->getClassType().'/login',
944
            array(
945
                'id' => $this->game->getIdentifier(),
946
                
947
            )
948
        ) . ($socialnetwork ? '/' . $socialnetwork : ''). ($redirect ? '?redirect=' . $redirect : '');
949
950
        return $this->redirect()->toUrl($redirect);
951
    }
952
953 View Code Duplication
    public function cmsPageAction()
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...
954
    {
955
        $viewModel = $this->forward()->dispatch(
956
            'playgroundcms',
957
            array(
958
                'controller' => 'playgroundcms',
959
                'action' => 'index',
960
                'id' => $this->game->getIdentifier(),
961
                'pid' => $this->getEvent()->getRouteMatch()->getParam('pid')
962
            )
963
        );
964
965
        if ($viewModel && $viewModel instanceof \Zend\View\Model\ViewModel) {
966
            $this->layout()->setVariables(array('game' => $this->game));
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...
967
            $viewModel->setVariables(array('game' => $this->game));
968
        }
969
970
        return $viewModel;
971
    }
972
973 View Code Duplication
    public function cmsListAction()
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...
974
    {
975
976
        $viewModel = $this->forward()->dispatch(
977
            'playgroundcms',
978
            array(
979
                'controller' => 'playgroundcms',
980
                'action' => 'list',
981
                'id' => $this->game->getIdentifier(),
982
                'category' => $this->game->getIdentifier()
983
            )
984
        );
985
986
        if ($viewModel && $viewModel instanceof \Zend\View\Model\ViewModel) {
987
            $this->layout()->setVariables(array('game' => $this->game));
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...
988
            $viewModel->setVariables(array('game' => $this->game));
989
        }
990
991
        return $viewModel;
992
    }
993
994
    /**
995
     *
996
     * @param \PlaygroundGame\Entity\Game $game
997
     * @param \PlaygroundUser\Entity\User $user
998
     */
999
    public function checkFbRegistration($user, $game)
1000
    {
1001
        $redirect = false;
1002
        $session = new Container('facebook');
1003
        if ($session->offsetExists('signed_request')) {
1004
            if (!$user) {
1005
                // Get Playground user from Facebook info
1006
                $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...
1007
                $view = $this->forward()->dispatch(
1008
                    'playgrounduser_user',
1009
                    array(
1010
                        'controller' => 'playgrounduser_user',
1011
                        'action' => 'registerFacebookUser',
1012
                        'provider' => 'facebook'
1013
                    )
1014
                );
1015
1016
                $this->layout()->setTemplate($beforeLayout);
1017
                $user = $view->user;
1018
1019
                // If the user can not be created/retrieved from Facebook info, redirect to login/register form
1020
                if (!$user) {
1021
                    $redirectUrl = urlencode(
1022
                        $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...
1023
                            $game->getClassType() .'/play',
1024
                            array('id' => $game->getIdentifier()),
1025
                            array('force_canonical' => true)
1026
                        )
1027
                    );
1028
                    $redirect =  $this->redirect()->toUrl(
1029
                        $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...
1030
                            'zfcuser/register'
1031
                        ) . '?redirect='.$redirectUrl
1032
                    );
1033
                }
1034
            }
1035
1036
            if ($game->getFbFan()) {
1037
                if ($this->getGameService()->checkIsFan($game) === false) {
1038
                    $redirect =  $this->redirect()->toRoute(
1039
                        $game->getClassType().'/fangate',
1040
                        array('id' => $game->getIdentifier())
1041
                    );
1042
                }
1043
            }
1044
        }
1045
1046
        return $redirect;
1047
    }
1048
1049
    /**
1050
     * This method create the basic Game view
1051
     * @param \PlaygroundGame\Entity\Game $game
1052
     */
1053
    public function buildView($game)
1054
    {
1055
        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...
1056
            $viewModel = new JsonModel();
1057
            if ($game) {
1058
                $view = $this->addAdditionalView($game);
1059
                if ($view && $view instanceof \Zend\View\Model\ViewModel) {
1060
                    $viewModel->setVariables($view->getVariables());
1061
                }
1062
            }
1063
        } else {
1064
            $viewModel = new ViewModel();
1065
1066
            if ($game) {
1067
                $this->addMetaTitle($game);
1068
                $this->addMetaBitly();
1069
                $this->addGaEvent($game);
1070
1071
                $this->customizeGameDesign($game);
1072
                
1073
                $view = $this->addAdditionalView($game);
1074
                if ($view && $view instanceof \Zend\View\Model\ViewModel) {
1075
                    $viewModel->addChild($view, 'additional');
1076
                } elseif ($view && $view instanceof \Zend\Http\PhpEnvironment\Response) {
1077
                    return $view;
1078
                }
1079
1080
                $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...
1081
                    array(
1082
                        'action' => $this->params('action'),
1083
                        'game' => $game,
1084
                        'flashMessages'    => $this->flashMessenger()->getMessages(),
1085
                        
1086
                    )
1087
                );
1088
            }
1089
        }
1090
        
1091
        if ($game) {
1092
            $viewModel->setVariables($this->getShareData($game));
1093
            $viewModel->setVariables(array('game' => $game));
1094
        }
1095
1096
        return $viewModel;
1097
    }
1098
1099
    /**
1100
     * @param \PlaygroundGame\Entity\Game $game
1101
     */
1102
    public function addAdditionalView($game)
1103
    {
1104
        $view = false;
1105
1106
        $actionName = $this->getEvent()->getRouteMatch()->getParam('action', 'not-found');
1107
        $stepsViews = json_decode($game->getStepsViews(), true);
1108
        if ($stepsViews && isset($stepsViews[$actionName])) {
1109
            $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...
1110
            $actionData = $stepsViews[$actionName];
1111
            if (is_string($actionData)) {
1112
                $action = $actionData;
1113
                $controller = $this->getEvent()->getRouteMatch()->getParam('controller', 'playgroundgame_game');
1114
                $view = $this->forward()->dispatch(
1115
                    $controller,
1116
                    array(
1117
                        'action' => $action,
1118
                        'id' => $game->getIdentifier()
1119
                    )
1120
                );
1121
            } elseif (is_array($actionData) && count($actionData)>0) {
1122
                $action = key($actionData);
1123
                $controller = $actionData[$action];
1124
                $view = $this->forward()->dispatch(
1125
                    $controller,
1126
                    array(
1127
                        'action' => $action,
1128
                        'id' => $game->getIdentifier()
1129
                    )
1130
                );
1131
            }
1132
            // suite au forward, le template de layout a changé, je dois le rétablir...
1133
            $this->layout()->setTemplate($beforeLayout);
1134
        }
1135
1136
        return $view;
1137
    }
1138
1139
    public function addMetaBitly()
1140
    {
1141
        $bitlyclient = $this->getOptions()->getBitlyUrl();
1142
        $bitlyuser = $this->getOptions()->getBitlyUsername();
1143
        $bitlykey = $this->getOptions()->getBitlyApiKey();
1144
1145
        $this->getViewHelper('HeadMeta')->setProperty('bt:client', $bitlyclient);
1146
        $this->getViewHelper('HeadMeta')->setProperty('bt:user', $bitlyuser);
1147
        $this->getViewHelper('HeadMeta')->setProperty('bt:key', $bitlykey);
1148
    }
1149
1150
    /**
1151
     * @param \PlaygroundGame\Entity\Game $game
1152
     */
1153
    public function addGaEvent($game)
1154
    {
1155
        // Google Analytics event
1156
        $ga = $this->getServiceLocator()->get('google-analytics');
1157
        $event = new \PlaygroundCore\Analytics\Event($game->getClassType(), $this->params('action'));
1158
        $event->setLabel($game->getTitle());
1159
        $ga->addEvent($event);
1160
    }
1161
1162
    /**
1163
     * @param \PlaygroundGame\Entity\Game $game
1164
     */
1165
    public function addMetaTitle($game)
1166
    {
1167
        $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...
1168
        $this->getGameService()->getServiceManager()->get('ViewHelperManager')->get('HeadTitle')->set($title);
1169
        // Meta set in the layout
1170
        $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...
1171
            array(
1172
                'breadcrumbTitle' => $title,
1173
                'currentPage' => array(
1174
                    'pageGames' => 'games',
1175
                    'pageWinners' => ''
1176
                ),
1177
                'headParams' => array(
1178
                    'headTitle' => $title,
1179
                    'headDescription' => $title,
1180
                ),
1181
                'bodyCss' => $game->getIdentifier()
1182
            )
1183
        );
1184
    }
1185
1186
    /**
1187
     * @param \PlaygroundGame\Entity\Game $game
1188
     */
1189
    public function customizeGameDesign($game)
1190
    {
1191
        // If this game has a specific layout...
1192
        if ($game->getLayout()) {
1193
            $layoutViewModel = $this->layout();
1194
            $layoutViewModel->setTemplate($game->getLayout());
1195
        }
1196
1197
        // If this game has a specific stylesheet...
1198
        if ($game->getStylesheet()) {
1199
            $this->getViewHelper('HeadLink')->appendStylesheet(
1200
                $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...
1201
            );
1202
        }
1203
    }
1204
1205
    /**
1206
     * @param \PlaygroundGame\Entity\Game $game
1207
     */
1208
    public function getShareData($game)
1209
    {
1210
        $fo = $this->getServiceLocator()->get('facebook-opengraph');
1211
        $session = new Container('facebook');
1212
1213
        // I change the fbappid if i'm in fb
1214
        if ($session->offsetExists('signed_request')) {
1215
            $fo->setId($game->getFbAppId());
1216
        }
1217
1218
        // If I want to add a share block in my view
1219 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...
1220
            $fbShareMessage = $game->getFbShareMessage();
1221
        } else {
1222
            $fbShareMessage = str_replace(
1223
                '__placeholder__',
1224
                $game->getTitle(),
1225
                $this->getOptions()->getDefaultShareMessage()
1226
            );
1227
        }
1228
1229
        if ($game->getFbShareImage()) {
1230
            $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...
1231
                '',
1232
                array(),
1233
                array('force_canonical' => true),
1234
                false
1235
            ) . $game->getFbShareImage();
1236
        } else {
1237
            $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...
1238
                '',
1239
                array(),
1240
                array('force_canonical' => true),
1241
                false
1242
            ) . $game->getMainImage();
1243
        }
1244
1245
        $secretKey = strtoupper(substr(sha1(uniqid('pg_', true).'####'.time()), 0, 15));
1246
1247
        // Without bit.ly shortener
1248
        $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...
1249
            $game->getClassType(),
1250
            array('id' => $game->getIdentifier()),
1251
            array('force_canonical' => true)
1252
        );
1253
        // With core shortener helper
1254
        $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...
1255
1256
        // FB Requests only work when it's a FB app
1257
        if ($game->getFbRequestMessage()) {
1258
            $fbRequestMessage = urlencode($game->getFbRequestMessage());
1259
        } else {
1260
            $fbRequestMessage = str_replace(
1261
                '__placeholder__',
1262
                $game->getTitle(),
1263
                $this->getOptions()->getDefaultShareMessage()
1264
            );
1265
        }
1266
1267 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...
1268
            $twShareMessage = $game->getTwShareMessage() . $socialLinkUrl;
1269
        } else {
1270
            $twShareMessage = str_replace(
1271
                '__placeholder__',
1272
                $game->getTitle(),
1273
                $this->getOptions()->getDefaultShareMessage()
1274
            ) . $socialLinkUrl;
1275
        }
1276
1277
        $ogTitle = new \PlaygroundCore\Opengraph\Tag('og:title', $fbShareMessage);
1278
        $ogImage = new \PlaygroundCore\Opengraph\Tag('og:image', $fbShareImage);
1279
        
1280
        $fo->addTag($ogTitle);
1281
        $fo->addTag($ogImage);
1282
        
1283
        $data = array(
1284
            'socialLinkUrl'       => $socialLinkUrl,
1285
            'secretKey'           => $secretKey,
1286
            'fbShareMessage'      => $fbShareMessage,
1287
            'fbShareImage'        => $fbShareImage,
1288
            'fbRequestMessage'    => $fbRequestMessage,
1289
            'twShareMessage'      => $twShareMessage,
1290
        );
1291
1292
        return $data;
1293
    }
1294
    
1295
    /**
1296
     * return ajax response in json format
1297
     *
1298
     * @param array $data
1299
     * @return \Zend\View\Model\JsonModel
1300
     */
1301 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...
1302
    {
1303
        $model = new JsonModel(array(
1304
            'success' => true,
1305
            'data' => $data
1306
        ));
1307
        return $model->setTerminal(true);
1308
    }
1309
    
1310
    /**
1311
     * return ajax response in json format
1312
     *
1313
     * @param string $message
1314
     * @return \Zend\View\Model\JsonModel
1315
     */
1316 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...
1317
    {
1318
        $model = new JsonModel(array(
1319
            'success' => false,
1320
            'message' => $message
1321
        ));
1322
        return $model->setTerminal(true);
1323
    }
1324
1325
    /**
1326
     * @param string $helperName
1327
     */
1328
    protected function getViewHelper($helperName)
1329
    {
1330
        return $this->getServiceLocator()->get('viewhelpermanager')->get($helperName);
1331
    }
1332
1333
    public function getGameService()
1334
    {
1335
        if (!$this->gameService) {
1336
            $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...
1337
        }
1338
1339
        return $this->gameService;
1340
    }
1341
1342
    public function setGameService(GameService $gameService)
1343
    {
1344
        $this->gameService = $gameService;
1345
1346
        return $this;
1347
    }
1348
1349
    public function getPrizeService()
1350
    {
1351
        if (!$this->prizeService) {
1352
            $this->prizeService = $this->getServiceLocator()->get('playgroundgame_prize_service');
1353
        }
1354
1355
        return $this->prizeService;
1356
    }
1357
1358
    public function setPrizeService(PrizeService $prizeService)
1359
    {
1360
        $this->prizeService = $prizeService;
1361
1362
        return $this;
1363
    }
1364
1365
    public function getOptions()
1366
    {
1367
        if (!$this->options) {
1368
            $this->setOptions($this->getServiceLocator()->get('playgroundcore_module_options'));
1369
        }
1370
1371
        return $this->options;
1372
    }
1373
1374
    public function setOptions($options)
1375
    {
1376
        $this->options = $options;
1377
1378
        return $this;
1379
    }
1380
}
1381