Passed
Pull Request — master (#1107)
by Tim
05:50
created

StandardSessionManager::create()   B

Complexity

Conditions 7
Paths 64

Size

Total Lines 50
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 0
Metric Value
cc 7
eloc 16
nc 64
nop 8
dl 0
loc 50
ccs 0
cts 29
cp 0
crap 56
rs 8.8333
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/**
4
 * \AppserverIo\Appserver\ServletEngine\StandardSessionManager
5
 *
6
 * NOTICE OF LICENSE
7
 *
8
 * This source file is subject to the Open Software License (OSL 3.0)
9
 * that is available through the world-wide-web at this URL:
10
 * http://opensource.org/licenses/osl-3.0.php
11
 *
12
 * PHP version 5
13
 *
14
 * @author    Tim Wagner <[email protected]>
15
 * @copyright 2015 TechDivision GmbH <[email protected]>
16
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
17
 * @link      https://github.com/appserver-io/appserver
18
 * @link      http://www.appserver.io
19
 */
20
21
namespace AppserverIo\Appserver\ServletEngine;
22
23
use AppserverIo\Logger\LoggerUtils;
24
use AppserverIo\Collections\HashMap;
25
use AppserverIo\Collections\CollectionInterface;
26
use AppserverIo\Appserver\ServletEngine\Http\Session;
27
use AppserverIo\Psr\Naming\NamingException;
28
use AppserverIo\Psr\Servlet\ServletContextInterface;
29
use AppserverIo\Psr\Servlet\ServletSessionInterface;
30
use AppserverIo\Psr\Application\ApplicationInterface;
31
use AppserverIo\Psr\Application\ManagerConfigurationInterface;
32
33
/**
34
 * A simple session manager implementation implementation using
35
 * session handlers to persist the sessions.
36
 *
37
 * @author    Tim Wagner <[email protected]>
38
 * @copyright 2015 TechDivision GmbH <[email protected]>
39
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
40
 * @link      https://github.com/appserver-io/appserver
41
 * @link      http://www.appserver.io
42
 */
43
class StandardSessionManager implements SessionManagerInterface
44
{
45
46
    /**
47
     * The HashMap containing the sessions.
48
     *
49
     * @var \AppserverIo\Collections\HashMap
50
     */
51
    protected $sessions;
52
53
    /**
54
     * The HashMap containing the session handlers.
55
     *
56
     * @var \AppserverIo\Collections\HashMap
57
     */
58
    protected $sessionHandlers;
59
60
    /**
61
     * The application instance.
62
     *
63
     * @var \AppserverIo\Psr\Application\ApplicationInterface
64
     */
65
    protected $application;
66
67
    /**
68
     * The settings for the session handling.
69
     *
70
     * @var \AppserverIo\Appserver\ServletEngine\SessionSettingsInterface
71
     */
72
    protected $sessionSettings;
73
74
    /**
75
     * The session marshaller instance.
76
     *
77
     * @var \AppserverIo\Appserver\ServletEngine\SessionMarshallerInterface
78
     */
79
    protected $sessionMarshaller;
80
81
    /**
82
     * The manager configuration instance.
83
     *
84
     * @var  \AppserverIo\Psr\Application\ManagerConfigurationInterface
85
     */
86
    protected $managerConfiguration;
87
88
    /**
89
     * The garbage collector instance.
90
     *
91
     * @var \AppserverIo\Appserver\ServletEngine\GarbageCollectorInterface
92
     */
93
    protected $garbageCollector;
94
95
    /**
96
     * Initialize the session manager.
97
     */
98
    public function __construct()
99
    {
100
        $this->sessions = new HashMap();
101
        $this->sessionHandlers = new HashMap();
102
    }
103
104
    /**
105
     * Inject the application instance.
106
     *
107
     * @param \AppserverIo\Psr\Application\ApplicationInterface $application The application instance
108
     *
109
     * @return void
110
     */
111
    public function injectApplication(ApplicationInterface $application)
112
    {
113
        $this->application = $application;
114
    }
115
116
    /**
117
     * Returns the application instance.
118
     *
119
     * @return \AppserverIo\Psr\Application\ApplicationInterface|\AppserverIo\Psr\Naming\NamingDirectoryInterface The application instance
120
     */
121
    public function getApplication()
122
    {
123
        return $this->application;
124
    }
125
126
    /**
127
     * Injects the session settings.
128
     *
129
     * @param \AppserverIo\Appserver\ServletEngine\SessionSettingsInterface $sessionSettings Settings for the session handling
130
     *
131
     * @return void
132
     */
133
    public function injectSessionSettings($sessionSettings)
134
    {
135
        $this->sessionSettings = $sessionSettings;
136
    }
137
138
    /**
139
     * Returns the session settings.
140
     *
141
     * @return \AppserverIo\Appserver\ServletEngine\SessionSettingsInterface The session settings
142
     */
143
    public function getSessionSettings()
144
    {
145
        return $this->sessionSettings;
146
    }
147
148
    /**
149
     * Injects the session marshaller.
150
     *
151
     * @param \AppserverIo\Appserver\ServletEngine\SessionMarshallerInterface $sessionMarshaller The session marshaller instance
152
     *
153
     * @return void
154
     */
155
    public function injectSessionMarshaller($sessionMarshaller)
156
    {
157
        $this->sessionMarshaller = $sessionMarshaller;
158
    }
159
160
    /**
161
     * Returns the session marshaller.
162
     *
163
     * @return \AppserverIo\Appserver\ServletEngine\SessionMarshallerInterface The session marshaller
164
     */
165
    public function getSessionMarshaller()
166
    {
167
        return $this->sessionMarshaller;
168
    }
169
170
    /**
171
     * Inject the configuration for this manager.
172
     *
173
     * @param \AppserverIo\Psr\Application\ManagerConfigurationInterface $managerConfiguration The managers configuration
174
     *
175
     * @return void
176
     */
177
    public function injectManagerConfiguration(ManagerConfigurationInterface $managerConfiguration)
178
    {
179
        $this->managerConfiguration = $managerConfiguration;
180
    }
181
182
    /**
183
     * Return's the manager configuration.
184
     *
185
     * @return \AppserverIo\Psr\Application\ManagerConfigurationInterface The manager configuration
186
     */
187
    public function getManagerConfiguration()
188
    {
189
        return $this->managerConfiguration;
190
    }
191
192
    /**
193
     * Inject the session handlers.
194
     *
195
     * @param \AppserverIo\Collections\CollectionInterface $sessionHandlers The session handlers
196
     *
197
     * @return void
198
     */
199
    public function injectSessionHandlers(CollectionInterface $sessionHandlers)
200
    {
201
        $this->sessionHandlers = $sessionHandlers;
0 ignored issues
show
Documentation Bug introduced by
$sessionHandlers is of type AppserverIo\Collections\CollectionInterface, but the property $sessionHandlers was declared to be of type AppserverIo\Collections\HashMap. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof 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 given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
202
    }
203
204
    /**
205
     * Returns all registered session handlers.
206
     *
207
     * @return \AppserverIo\Collections\ArrayList The session handlers
208
     */
209
    public function getSessionHandlers()
210
    {
211
        return $this->sessionHandlers;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->sessionHandlers returns the type AppserverIo\Collections\HashMap which is incompatible with the documented return type AppserverIo\Collections\ArrayList.
Loading history...
212
    }
213
214
    /**
215
     * Injects the garbage collector.
216
     *
217
     * @param \AppserverIo\Appserver\ServletEngine\GarbageCollectorInterface $garbageCollector The garbage collector
218
     *
219
     * @return void
220
     */
221
    public function injectGarbageCollector(GarbageCollectorInterface $garbageCollector)
222
    {
223
        $this->garbageCollector = $garbageCollector;
224
    }
225
226
    /**
227
     * Returns the garbage collector instance.
228
     *
229
     * @return \AppserverIo\Appserver\ServletEngine\GarbageCollectorInterface The garbage collector instance
230
     */
231
    public function getGarbageCollector()
232
    {
233
        return $this->garbageCollector;
234
    }
235
236
    /**
237
     * Returns all sessions actually attached to the session manager.
238
     *
239
     * @return \AppserverIo\Collections\HashMap The container with sessions
240
     */
241
    public function getSessions()
242
    {
243
        return $this->sessions;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->sessions returns the type AppserverIo\Collections\HashMap which is incompatible with the return type mandated by AppserverIo\Appserver\Se...nterface::getSessions() of AppserverIo\Appserver\Se...essionSettingsInterface.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
244
    }
245
246
    /**
247
     * Returns the attribute with the passed key from the container.
248
     *
249
     * @param string $key The key the requested value is registered with
250
     *
251
     * @return mixed|null The requested value if available
252
     */
253
    public function getAttribute($key)
254
    {
255
        // do nothing here
256
    }
257
258
    /**
259
     * Returns the session factory.
260
     *
261
     * @return \AppserverIo\Appserver\ServletEngine\Session\SessionHandlerFactory The session factory instance
262
     */
263
    public function getSessionFactory()
264
    {
265
        // do nothing here
266
    }
267
268
    /**
269
     * Returns the servlet manager instance.
270
     *
271
     * @return \AppserverIo\Psr\Servlet\ServletContextInterface The servlet manager instance
272
     */
273
    public function getServletManager()
274
    {
275
        // do nothing here
276
    }
277
278
    /**
279
     * Returns the session pool instance.
280
     *
281
     * @return \AppserverIo\Storage\StorageInterface The session pool
282
     */
283
    public function getSessionPool()
284
    {
285
        // do nothing here
286
    }
287
288
    /**
289
     * Returns the persistence manager instance.
290
     *
291
     * @return \AppserverIo\Appserver\ServletEngine\Session\SessionHandlerInterface The persistence manager instance
292
     */
293
    public function getPersistenceManager()
294
    {
295
        // do nothing here
296
    }
297
298
    /**
299
     * Lifecycle callback that'll be invoked after the application has been started.
300
     *
301
     * @param \AppserverIo\Psr\Application\ApplicationInterface $application The application instance
302
     *
303
     * @return void
304
     * @see \AppserverIo\Psr\Application\ManagerInterface::postStartup()
305
     */
306
    public function postStartup(ApplicationInterface $application)
307
    {
308
    }
309
310
    /**
311
     * Initializes the session manager.
312
     *
313
     * @param \AppserverIo\Psr\Application\ApplicationInterface $application The application instance
314
     *
315
     * @return void
316
     * @see \AppserverIo\Psr\Application\ManagerInterface::initialize()
317
     */
318
    public function initialize(ApplicationInterface $application)
319
    {
320
321
        // load the servlet manager with the session settings configured in web.xml
322
        /** @var \AppserverIo\Psr\Servlet\ServletContextInterface|\AppserverIo\Psr\Application\ManagerInterface $servletManager */
323
        $servletManager = $application->search(ServletContextInterface::IDENTIFIER);
324
325
        // load the settings, set the default session save path
326
        $sessionSettings = $this->getSessionSettings();
327
        $sessionSettings->setSessionSavePath($application->getSessionDir());
0 ignored issues
show
Bug introduced by
The method getSessionDir() does not exist on AppserverIo\Psr\Application\ApplicationInterface. It seems like you code against a sub-type of AppserverIo\Psr\Application\ApplicationInterface such as AppserverIo\Appserver\Application\Application. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

327
        $sessionSettings->setSessionSavePath($application->/** @scrutinizer ignore-call */ getSessionDir());
Loading history...
Bug introduced by
The method setSessionSavePath() does not exist on AppserverIo\Appserver\Se...essionSettingsInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to AppserverIo\Appserver\Se...essionSettingsInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

327
        $sessionSettings->/** @scrutinizer ignore-call */ 
328
                          setSessionSavePath($application->getSessionDir());
Loading history...
328
329
        // if we've session parameters defined in our servlet context
330
        if ($servletManager->hasSessionParameters()) {
0 ignored issues
show
Bug introduced by
The method hasSessionParameters() does not exist on AppserverIo\Psr\Application\ManagerInterface. It seems like you code against a sub-type of AppserverIo\Psr\Application\ManagerInterface such as AppserverIo\Appserver\ServletEngine\ServletManager. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

330
        if ($servletManager->/** @scrutinizer ignore-call */ hasSessionParameters()) {
Loading history...
331
            // we want to merge the session settings from the servlet context
332
            $sessionSettings->mergeServletContext($servletManager);
0 ignored issues
show
Bug introduced by
It seems like $servletManager can also be of type AppserverIo\Psr\Application\ManagerInterface; however, parameter $context of AppserverIo\Appserver\Se...::mergeServletContext() does only seem to accept AppserverIo\Psr\Servlet\ServletContextInterface, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

332
            $sessionSettings->mergeServletContext(/** @scrutinizer ignore-type */ $servletManager);
Loading history...
333
        }
334
    }
335
336
    /**
337
     * Creates a new session with the passed session ID and session name if given.
338
     *
339
     * @param mixed             $id         The session ID
340
     * @param string            $name       The session name
341
     * @param integer|\DateTime $lifetime   Date and time after the session expires
342
     * @param integer|null      $maximumAge Number of seconds until the session expires
343
     * @param string|null       $domain     The host to which the user agent will send this cookie
344
     * @param string            $path       The path describing the scope of this cookie
345
     * @param boolean           $secure     If this cookie should only be sent through a "secure" channel by the user agent
346
     * @param boolean           $httpOnly   If this cookie should only be used through the HTTP protocol
347
     *
348
     * @return \AppserverIo\Psr\Servlet\ServletSessionInterface The requested session
349
     */
350
    public function create(
351
        $id,
352
        $name,
353
        $lifetime = null,
354
        $maximumAge = null,
355
        $domain = null,
356
        $path = null,
357
        $secure = null,
358
        $httpOnly = null
359
    ) {
360
361
        // copy the default session configuration for lifetime from the settings
362
        if ($lifetime == null) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $lifetime of type null|integer|DateTime against null; this is ambiguous if the integer can be zero. Consider using a strict comparison === instead.
Loading history...
363
            $lifetime = time() + $this->getSessionSettings()->getSessionCookieLifetime();
364
        }
365
366
        // copy the default session configuration for maximum from the settings
367
        if ($maximumAge == null) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $maximumAge of type null|integer against null; this is ambiguous if the integer can be zero. Consider using a strict comparison === instead.
Loading history...
368
            $maximumAge = $this->getSessionSettings()->getSessionMaximumAge();
369
        }
370
371
        // copy the default session configuration for cookie domain from the settings
372
        if ($domain == null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $domain of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
373
            $domain = $this->getSessionSettings()->getSessionCookieDomain();
374
        }
375
376
        // copy the default session configuration for the cookie path from the settings
377
        if ($path == null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $path of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
378
            $path = $this->getSessionSettings()->getSessionCookiePath();
379
        }
380
381
        // copy the default session configuration for the secure flag from the settings
382
        if ($secure == null) {
383
            $secure = $this->getSessionSettings()->getSessionCookieSecure();
384
        }
385
386
        // copy the default session configuration for the http only flag from the settings
387
        if ($httpOnly == null) {
388
            $httpOnly = $this->getSessionSettings()->getSessionCookieHttpOnly();
389
        }
390
391
        // initialize and return the session instance
392
        $session = Session::emptyInstance();
393
        $session->init($id, $name, $lifetime, $maximumAge, $domain, $path, $secure, $httpOnly);
394
395
        // attach the session to the manager
396
        $this->attach($session);
397
398
        // return the session
399
        return $session;
400
    }
401
402
    /**
403
     * Attaches the passed session to the manager and returns the instance.
404
     * If a session
405
     * with the session identifier already exists, it will be overwritten.
406
     *
407
     * @param \AppserverIo\Psr\Servlet\ServletSessionInterface $session The session to attach
408
     *
409
     * @return void
410
     */
411
    public function attach(ServletSessionInterface $session)
412
    {
413
        $this->getSessions()->add($session->getId(), $session);
414
    }
415
416
    /**
417
     * Tries to find a session for the given request. The session-ID will be
418
     * searched in the cookie header of the request, and in the request query
419
     * string. If both values are present, the value in the query string takes
420
     * precedence. If no session id is found, a new one is created and assigned
421
     * to the request.
422
     *
423
     * @param string $id The unique session ID to that has to be returned
424
     *
425
     * @return \AppserverIo\Psr\Servlet\ServletSessionInterface|null The requested session
426
     */
427
    public function find($id)
428
    {
429
430
        // return immediately if the requested session ID is empty
431
        if (empty($id)) {
432
            return;
433
        }
434
435
        // declare the session variable
436
        $session = null;
437
438
        // query whether or not the session with the passed ID exists
439
        if ($this->getSessions()->exists($id)) {
440
            $session = $this->getSessions()->get($id);
441
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
442
        } else {
443
            // iterate over the session handlers and try to un-persist the session
444
            /** @var \AppserverIo\Appserver\ServletEngine\Session\SessionHandlerInterface $sessionHandler */
445
            foreach ($this->getSessionHandlers() as $sessionHandler) {
446
                try {
447
                    if ($session = $sessionHandler->load($id)) {
448
                        $this->attach($session);
449
                        break;
450
                    }
451
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
452
                } catch (\Exception $e) {
453
                    // log the exception if a system logger is available
454
                    if ($logger = $this->getLogger(LoggerUtils::SYSTEM)) {
455
                        // log the error message
456
                        $logger->error(sprintf('Can\'t load session data for session with ID "%s" because of: "%s"', $id, $e->getMessage()));
457
                        // log the stack trace in debug log level
458
                        $logger->debug($e->__toString());
459
                    }
460
                }
461
            }
462
        }
463
464
        // if we found a session, we've to check if it can be resumed
465
        if ($session instanceof ServletSessionInterface) {
466
            if ($session->canBeResumed()) {
467
                $session->resume();
468
                return $session;
469
            }
470
        }
471
    }
472
473
    /**
474
     * Flushes the session storage and persists all sessions.
475
     *
476
     * @return void
477
     */
478
    public function flush()
479
    {
480
481
        // persist all sessions
482
        /** @var \AppserverIo\Psr\Servlet\ServletSessionInterface $session */
483
        foreach ($this->getSessions() as $session) {
484
            // iterate over the session handlers and persist the sessions
485
            /** @var \AppserverIo\Appserver\ServletEngine\Session\SessionHandlerInterface $sessionHandler */
486
            foreach ($this->getSessionHandlers() as $sessionHandler) {
487
                try {
488
                    $sessionHandler->save($session);
489
                } catch (\Exception $e) {
490
                    // log the exception if a system logger is available
491
                    if ($logger = $this->getLogger(LoggerUtils::SYSTEM)) {
492
                        $logger->error($e->__toString());
493
                    }
494
                }
495
            }
496
        }
497
    }
498
499
    /**
500
     * Initializes the manager instance.
501
     *
502
     * @return string
503
     * @see \AppserverIo\Psr\Application\ManagerInterface::initialize()
504
     */
505
    public function getIdentifier()
506
    {
507
        return SessionManagerInterface::IDENTIFIER;
508
    }
509
510
    /**
511
     * Shutdown the session manager instance.
512
     *
513
     * @return void
514
     * \AppserverIo\Psr\Application\ManagerInterface::stop()
515
     */
516
    public function stop()
517
    {
518
        $this->getGarbageCollector()->stop();
519
    }
520
521
    /**
522
     * Return's the logger with the requested name. First we look in the
523
     * application and then in the system itself.
524
     *
525
     * @param string $loggerName The name of the logger to return
526
     *
527
     * @return \Psr\Log\LoggerInterface The logger with the requested name
528
     */
529
    public function getLogger($loggerName)
530
    {
531
532
        try {
533
            // first let's see if we've an application logger registered
534
            if ($logger = $this->getApplication()->getLogger($loggerName)) {
0 ignored issues
show
Bug introduced by
The method getLogger() does not exist on AppserverIo\Psr\Application\ApplicationInterface. It seems like you code against a sub-type of AppserverIo\Psr\Application\ApplicationInterface such as AppserverIo\Appserver\Application\Application. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

534
            if ($logger = $this->getApplication()->/** @scrutinizer ignore-call */ getLogger($loggerName)) {
Loading history...
535
                return $logger;
536
            }
537
538
            // then try to load the global logger instance if available
539
            return $this->getApplication()->getNamingDirectory()->search(sprintf('php:global/log/%s', $loggerName));
0 ignored issues
show
Bug introduced by
The method getNamingDirectory() does not exist on AppserverIo\Psr\Application\ApplicationInterface. It seems like you code against a sub-type of AppserverIo\Psr\Application\ApplicationInterface such as AppserverIo\Appserver\Application\Application. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

539
            return $this->getApplication()->/** @scrutinizer ignore-call */ getNamingDirectory()->search(sprintf('php:global/log/%s', $loggerName));
Loading history...
540
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
541
        } catch (NamingException $ne) {
542
            // do nothing, we simply have no logger with the requested name
543
        }
544
    }
545
}
546