Completed
Push — develop ( cd67db...5214f5 )
by
unknown
07:35
created

BuildReferer::__invoke()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 16
Code Lines 9

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 16
rs 8.8571
cc 5
eloc 9
nc 8
nop 2
1
<?php
2
/**
3
 * YAWIK
4
 *
5
 * @filesource
6
 * @copyright (c) 2013-2015 Cross Solution (http://cross-solution.de)
7
 * @license   MIT
8
 */
9
10
/** Auth view helper */
11
namespace Auth\View\Helper;
12
13
use Zend\View\Helper\AbstractHelper;
14
use Auth\Filter\StripQueryParams as StripQueryParamsFilter;
15
16
/**
17
 * View helper to access authentication service and the
18
 * authenticated user (and its properties).
19
 *
20
 */
21
class BuildReferer extends AbstractHelper
22
{
23
    
24
    protected $filter;
25
    
26
    public function setFilter($filter)
27
    {
28
        $this->filter = $filter;
29
        return $this;
30
    }
31
    
32
    public function getFilter()
33
    {
34
        if (!$this->filter) {
35
            $this->setFilter(new StripQueryParamsFilter());
36
        }
37
        return $this->filter;
38
    }
39
    
40
    /**
41
     * Entry point.
42
     *
43
     */
44
    public function __invoke($uri = null, array $stripParams = null)
0 ignored issues
show
Coding Style introduced by
__invoke uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
45
    {
46
        if (is_array($uri)) {
47
            $stripParams = $uri;
48
            $uri = null;
49
        }
50
        
51
        if (null === $uri && isset($_SERVER['REQUEST_URI'])) {
52
            $uri = preg_replace('~^' . $this->getView()->basePath() . '~', '', $_SERVER['REQUEST_URI']);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\View\Renderer\RendererInterface as the method basePath() does only exist in the following implementations of said interface: Zend\View\Renderer\PhpRenderer.

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...
53
        }
54
        
55
        if (null === $stripParams) {
56
            return $this->getFilter()->filter($uri);
57
        }
58
        return $this->getFilter()->filter($uri, $stripParams);
59
    }
60
}
61