Completed
Pull Request — master (#455)
by
unknown
03:13
created

Session   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 193
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 2

Importance

Changes 2
Bugs 1 Features 0
Metric Value
wmc 27
lcom 2
cbo 2
dl 0
loc 193
rs 10
c 2
b 1
f 0

13 Methods

Rating   Name   Duplication   Size   Complexity  
A hasAccessToken() 0 4 1
A hasAuthorizationState() 0 4 1
B __construct() 0 19 5
A retrieveAccessToken() 0 8 2
A storeAccessToken() 0 17 3
A clearToken() 0 9 2
A clearAllTokens() 0 7 1
A storeAuthorizationState() 0 15 3
A retrieveAuthorizationState() 0 8 2
A clearAuthorizationState() 0 9 2
A clearAllAuthorizationStates() 0 7 1
A __destruct() 0 6 2
A sessionHasStarted() 0 10 2
1
<?php
2
3
namespace OAuth\Common\Storage;
4
5
use OAuth\Common\Token\TokenInterface;
6
use OAuth\Common\Storage\Exception\TokenNotFoundException;
7
use OAuth\Common\Storage\Exception\AuthorizationStateNotFoundException;
8
9
/**
10
 * Stores a token in a PHP session.
11
 */
12
class Session implements TokenStorageInterface
13
{
14
    /**
15
     * @var bool
16
     */
17
    protected $startSession;
18
19
    /**
20
     * @var string
21
     */
22
    protected $sessionVariableName;
23
24
    /**
25
     * @var string
26
     */
27
    protected $stateVariableName;
28
29
    /**
30
     * @param bool $startSession Whether or not to start the session upon construction.
31
     * @param string $sessionVariableName the variable name to use within the _SESSION superglobal
32
     * @param string $stateVariableName
33
     */
34
    public function __construct(
0 ignored issues
show
Coding Style introduced by
__construct uses the super-global variable $_SESSION 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...
35
        $startSession = true,
36
        $sessionVariableName = 'lusitanian-oauth-token',
37
        $stateVariableName = 'lusitanian-oauth-state'
38
    ) {
39
        if ($startSession && !$this->sessionHasStarted()) {
40
            session_start();
41
        }
42
43
        $this->startSession = $startSession;
44
        $this->sessionVariableName = $sessionVariableName;
45
        $this->stateVariableName = $stateVariableName;
46
        if (!isset($_SESSION[$sessionVariableName])) {
47
            $_SESSION[$sessionVariableName] = array();
48
        }
49
        if (!isset($_SESSION[$stateVariableName])) {
50
            $_SESSION[$stateVariableName] = array();
51
        }
52
    }
53
54
    /**
55
     * {@inheritDoc}
56
     */
57
    public function retrieveAccessToken($service)
0 ignored issues
show
Coding Style introduced by
retrieveAccessToken uses the super-global variable $_SESSION 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...
58
    {
59
        if ($this->hasAccessToken($service)) {
60
            return unserialize($_SESSION[$this->sessionVariableName][$service]);
61
        }
62
63
        throw new TokenNotFoundException('Token not found in session, are you sure you stored it?');
64
    }
65
66
    /**
67
     * {@inheritDoc}
68
     */
69
    public function storeAccessToken($service, TokenInterface $token)
0 ignored issues
show
Coding Style introduced by
storeAccessToken uses the super-global variable $_SESSION 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...
70
    {
71
        $serializedToken = serialize($token);
72
73
        if (isset($_SESSION[$this->sessionVariableName])
74
            && is_array($_SESSION[$this->sessionVariableName])
75
        ) {
76
            $_SESSION[$this->sessionVariableName][$service] = $serializedToken;
77
        } else {
78
            $_SESSION[$this->sessionVariableName] = array(
79
                $service => $serializedToken,
80
            );
81
        }
82
83
        // allow chaining
84
        return $this;
85
    }
86
87
    /**
88
     * {@inheritDoc}
89
     */
90
    public function hasAccessToken($service)
0 ignored issues
show
Coding Style introduced by
hasAccessToken uses the super-global variable $_SESSION 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...
91
    {
92
        return isset($_SESSION[$this->sessionVariableName], $_SESSION[$this->sessionVariableName][$service]);
93
    }
94
95
    /**
96
     * {@inheritDoc}
97
     */
98
    public function clearToken($service)
0 ignored issues
show
Coding Style introduced by
clearToken uses the super-global variable $_SESSION 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...
99
    {
100
        if (array_key_exists($service, $_SESSION[$this->sessionVariableName])) {
101
            unset($_SESSION[$this->sessionVariableName][$service]);
102
        }
103
104
        // allow chaining
105
        return $this;
106
    }
107
108
    /**
109
     * {@inheritDoc}
110
     */
111
    public function clearAllTokens()
0 ignored issues
show
Coding Style introduced by
clearAllTokens uses the super-global variable $_SESSION 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...
112
    {
113
        unset($_SESSION[$this->sessionVariableName]);
114
115
        // allow chaining
116
        return $this;
117
    }
118
119
    /**
120
     * {@inheritDoc}
121
     */
122
    public function storeAuthorizationState($service, $state)
0 ignored issues
show
Coding Style introduced by
storeAuthorizationState uses the super-global variable $_SESSION 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...
123
    {
124
        if (isset($_SESSION[$this->stateVariableName])
125
            && is_array($_SESSION[$this->stateVariableName])
126
        ) {
127
            $_SESSION[$this->stateVariableName][$service] = $state;
128
        } else {
129
            $_SESSION[$this->stateVariableName] = array(
130
                $service => $state,
131
            );
132
        }
133
134
        // allow chaining
135
        return $this;
136
    }
137
138
    /**
139
     * {@inheritDoc}
140
     */
141
    public function hasAuthorizationState($service)
0 ignored issues
show
Coding Style introduced by
hasAuthorizationState uses the super-global variable $_SESSION 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...
142
    {
143
        return isset($_SESSION[$this->stateVariableName], $_SESSION[$this->stateVariableName][$service]);
144
    }
145
146
    /**
147
     * {@inheritDoc}
148
     */
149
    public function retrieveAuthorizationState($service)
0 ignored issues
show
Coding Style introduced by
retrieveAuthorizationState uses the super-global variable $_SESSION 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...
150
    {
151
        if ($this->hasAuthorizationState($service)) {
152
            return $_SESSION[$this->stateVariableName][$service];
153
        }
154
155
        throw new AuthorizationStateNotFoundException('State not found in session, are you sure you stored it?');
156
    }
157
158
    /**
159
     * {@inheritDoc}
160
     */
161
    public function clearAuthorizationState($service)
0 ignored issues
show
Coding Style introduced by
clearAuthorizationState uses the super-global variable $_SESSION 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...
162
    {
163
        if (array_key_exists($service, $_SESSION[$this->stateVariableName])) {
164
            unset($_SESSION[$this->stateVariableName][$service]);
165
        }
166
167
        // allow chaining
168
        return $this;
169
    }
170
171
    /**
172
     * {@inheritDoc}
173
     */
174
    public function clearAllAuthorizationStates()
0 ignored issues
show
Coding Style introduced by
clearAllAuthorizationStates uses the super-global variable $_SESSION 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...
175
    {
176
        unset($_SESSION[$this->stateVariableName]);
177
178
        // allow chaining
179
        return $this;
180
    }
181
182
    public function __destruct()
183
    {
184
        if ($this->startSession) {
185
            session_write_close();
186
        }
187
    }
188
189
    /**
190
     * Determine if the session has started.
191
     * @url http://stackoverflow.com/a/18542272/1470961
192
     * @return bool
193
     */
194
    protected function sessionHasStarted()
195
    {
196
        // For more modern PHP versions we use a more reliable method.
197
        if (version_compare(PHP_VERSION, '5.4.0') >= 0) {
198
            return session_status() != PHP_SESSION_NONE;
199
        }
200
201
        // Below PHP 5.4 we should test for the current session ID.
202
        return session_id() !== '';
203
    }
204
}
205