Completed
Pull Request — master (#309)
by greg
06:22 queued 03:06
created

GameController::fangateAction()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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