Completed
Pull Request — master (#51)
by
unknown
01:23
created
src/Crypto/OpenSSLCrypto.php 2 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -75,7 +75,7 @@
 block discarded – undo
75 75
      *
76 76
      * @param string $data - The encrypted-and-signed message as base64 ASCII
77 77
      *
78
-     * @return bool|string - The decrypted cleartext or false if signature failed
78
+     * @return string|false - The decrypted cleartext or false if signature failed
79 79
      */
80 80
     public function decrypt($data)
81 81
     {
Please login to merge, or discard this patch.
Indentation   +76 added lines, -76 removed lines patch added patch discarded remove patch
@@ -8,90 +8,90 @@
 block discarded – undo
8 8
  */
9 9
 class OpenSSLCrypto implements CryptoHandler
10 10
 {
11
-    protected $key;
11
+	protected $key;
12 12
 
13
-    protected $salt;
13
+	protected $salt;
14 14
 
15
-    protected $saltedKey;
15
+	protected $saltedKey;
16 16
 
17
-    /**
18
-     * @return string
19
-     */
20
-    public function getKey()
21
-    {
22
-        return $this->key;
23
-    }
17
+	/**
18
+	 * @return string
19
+	 */
20
+	public function getKey()
21
+	{
22
+		return $this->key;
23
+	}
24 24
 
25
-    /**
26
-     * @return string
27
-     */
28
-    public function getSalt()
29
-    {
30
-        return $this->salt;
31
-    }
25
+	/**
26
+	 * @return string
27
+	 */
28
+	public function getSalt()
29
+	{
30
+		return $this->salt;
31
+	}
32 32
 
33
-    /**
34
-     * @param string $key a per-site secret string which is used as the base encryption key.
35
-     * @param string $salt a per-session random string which is used as a salt to generate a per-session key
36
-     *
37
-     * The base encryption key needs to stay secret. If an attacker ever gets it, they can read their session,
38
-     * and even modify & re-sign it.
39
-     *
40
-     * The salt is a random per-session string that is used with the base encryption key to create a per-session key.
41
-     * This (amongst other things) makes sure an attacker can't use a known-plaintext attack to guess the key.
42
-     *
43
-     * Normally we could create a salt on encryption, send it to the client as part of the session (it doesn't
44
-     * need to remain secret), then use the returned salt to decrypt. But we already have the Session ID which makes
45
-     * a great salt, so no need to generate & handle another one.
46
-     */
47
-    public function __construct($key, $salt)
48
-    {
49
-        $this->key = $key;
50
-        $this->salt = $salt;
51
-        $this->saltedKey = hash_pbkdf2('sha256', $this->key, $this->salt, 1000, 0, true);
52
-    }
33
+	/**
34
+	 * @param string $key a per-site secret string which is used as the base encryption key.
35
+	 * @param string $salt a per-session random string which is used as a salt to generate a per-session key
36
+	 *
37
+	 * The base encryption key needs to stay secret. If an attacker ever gets it, they can read their session,
38
+	 * and even modify & re-sign it.
39
+	 *
40
+	 * The salt is a random per-session string that is used with the base encryption key to create a per-session key.
41
+	 * This (amongst other things) makes sure an attacker can't use a known-plaintext attack to guess the key.
42
+	 *
43
+	 * Normally we could create a salt on encryption, send it to the client as part of the session (it doesn't
44
+	 * need to remain secret), then use the returned salt to decrypt. But we already have the Session ID which makes
45
+	 * a great salt, so no need to generate & handle another one.
46
+	 */
47
+	public function __construct($key, $salt)
48
+	{
49
+		$this->key = $key;
50
+		$this->salt = $salt;
51
+		$this->saltedKey = hash_pbkdf2('sha256', $this->key, $this->salt, 1000, 0, true);
52
+	}
53 53
 
54
-    /**
55
-     * Encrypt and then sign some cleartext
56
-     *
57
-     * @param string $cleartext - The cleartext to encrypt and sign
58
-     * @return string - The encrypted-and-signed message as base64 ASCII.
59
-     */
60
-    public function encrypt($cleartext)
61
-    {
62
-        $cipher = "AES-256-CBC";
63
-        $ivlen = openssl_cipher_iv_length($cipher);
64
-        $iv = openssl_random_pseudo_bytes($ivlen);
65
-        $ciphertext_raw = openssl_encrypt($cleartext, $cipher, $this->saltedKey, $options = OPENSSL_RAW_DATA, $iv);
66
-        $hmac = hash_hmac('sha256', $ciphertext_raw, $this->saltedKey, $as_binary = true);
67
-        $ciphertext = base64_encode($iv . $hmac . $ciphertext_raw);
54
+	/**
55
+	 * Encrypt and then sign some cleartext
56
+	 *
57
+	 * @param string $cleartext - The cleartext to encrypt and sign
58
+	 * @return string - The encrypted-and-signed message as base64 ASCII.
59
+	 */
60
+	public function encrypt($cleartext)
61
+	{
62
+		$cipher = "AES-256-CBC";
63
+		$ivlen = openssl_cipher_iv_length($cipher);
64
+		$iv = openssl_random_pseudo_bytes($ivlen);
65
+		$ciphertext_raw = openssl_encrypt($cleartext, $cipher, $this->saltedKey, $options = OPENSSL_RAW_DATA, $iv);
66
+		$hmac = hash_hmac('sha256', $ciphertext_raw, $this->saltedKey, $as_binary = true);
67
+		$ciphertext = base64_encode($iv . $hmac . $ciphertext_raw);
68 68
 
69
-        return base64_encode($iv . $hmac . $ciphertext_raw);
70
-    }
69
+		return base64_encode($iv . $hmac . $ciphertext_raw);
70
+	}
71 71
 
72
-    /**
73
-     * Check the signature on an encrypted-and-signed message, and if valid
74
-     * decrypt the content
75
-     *
76
-     * @param string $data - The encrypted-and-signed message as base64 ASCII
77
-     *
78
-     * @return bool|string - The decrypted cleartext or false if signature failed
79
-     */
80
-    public function decrypt($data)
81
-    {
82
-        $c = base64_decode($data);
83
-        $cipher = "AES-256-CBC";
84
-        $ivlen = openssl_cipher_iv_length($cipher);
85
-        $iv = substr($c, 0, $ivlen);
86
-        $hmac = substr($c, $ivlen, $sha2len = 32);
87
-        $ciphertext_raw = substr($c, $ivlen + $sha2len);
88
-        $cleartext = openssl_decrypt($ciphertext_raw, $cipher, $this->saltedKey, $options = OPENSSL_RAW_DATA, $iv);
89
-        $calcmac = hash_hmac('sha256', $ciphertext_raw, $this->saltedKey, $as_binary = true);
72
+	/**
73
+	 * Check the signature on an encrypted-and-signed message, and if valid
74
+	 * decrypt the content
75
+	 *
76
+	 * @param string $data - The encrypted-and-signed message as base64 ASCII
77
+	 *
78
+	 * @return bool|string - The decrypted cleartext or false if signature failed
79
+	 */
80
+	public function decrypt($data)
81
+	{
82
+		$c = base64_decode($data);
83
+		$cipher = "AES-256-CBC";
84
+		$ivlen = openssl_cipher_iv_length($cipher);
85
+		$iv = substr($c, 0, $ivlen);
86
+		$hmac = substr($c, $ivlen, $sha2len = 32);
87
+		$ciphertext_raw = substr($c, $ivlen + $sha2len);
88
+		$cleartext = openssl_decrypt($ciphertext_raw, $cipher, $this->saltedKey, $options = OPENSSL_RAW_DATA, $iv);
89
+		$calcmac = hash_hmac('sha256', $ciphertext_raw, $this->saltedKey, $as_binary = true);
90 90
 
91
-        if (hash_equals($hmac, $calcmac)) {
92
-            return $cleartext;
93
-        }
91
+		if (hash_equals($hmac, $calcmac)) {
92
+			return $cleartext;
93
+		}
94 94
 
95
-        return false;
96
-    }
95
+		return false;
96
+	}
97 97
 }
Please login to merge, or discard this patch.
src/Store/BaseStore.php 1 patch
Indentation   +52 added lines, -52 removed lines patch added patch discarded remove patch
@@ -8,56 +8,56 @@
 block discarded – undo
8 8
 
9 9
 abstract class BaseStore implements SessionHandlerInterface
10 10
 {
11
-    use Configurable;
12
-
13
-    /**
14
-     * Session secret key
15
-     *
16
-     * @var string
17
-     */
18
-    protected $key = null;
19
-
20
-    /**
21
-     * Assign a new session secret key
22
-     *
23
-     * @param string $key
24
-     */
25
-    public function setKey($key)
26
-    {
27
-        $this->key = $key;
28
-    }
29
-
30
-    /**
31
-     * Get the session secret key
32
-     *
33
-     * @return string
34
-     */
35
-    protected function getKey()
36
-    {
37
-        return $this->key;
38
-    }
39
-
40
-    /**
41
-     * Get lifetime in number of seconds
42
-     *
43
-     * @return int
44
-     */
45
-    protected function getLifetime()
46
-    {
47
-        $params = session_get_cookie_params();
48
-        $cookieLifetime = (int)$params['lifetime'];
49
-        $gcLifetime = (int)ini_get('session.gc_maxlifetime');
50
-
51
-        return $cookieLifetime ? min($cookieLifetime, $gcLifetime) : $gcLifetime;
52
-    }
53
-
54
-    /**
55
-     * Gets the current unix timestamp
56
-     *
57
-     * @return int
58
-     */
59
-    protected function getNow()
60
-    {
61
-        return (int) DBDatetime::now()->getTimestamp();
62
-    }
11
+	use Configurable;
12
+
13
+	/**
14
+	 * Session secret key
15
+	 *
16
+	 * @var string
17
+	 */
18
+	protected $key = null;
19
+
20
+	/**
21
+	 * Assign a new session secret key
22
+	 *
23
+	 * @param string $key
24
+	 */
25
+	public function setKey($key)
26
+	{
27
+		$this->key = $key;
28
+	}
29
+
30
+	/**
31
+	 * Get the session secret key
32
+	 *
33
+	 * @return string
34
+	 */
35
+	protected function getKey()
36
+	{
37
+		return $this->key;
38
+	}
39
+
40
+	/**
41
+	 * Get lifetime in number of seconds
42
+	 *
43
+	 * @return int
44
+	 */
45
+	protected function getLifetime()
46
+	{
47
+		$params = session_get_cookie_params();
48
+		$cookieLifetime = (int)$params['lifetime'];
49
+		$gcLifetime = (int)ini_get('session.gc_maxlifetime');
50
+
51
+		return $cookieLifetime ? min($cookieLifetime, $gcLifetime) : $gcLifetime;
52
+	}
53
+
54
+	/**
55
+	 * Gets the current unix timestamp
56
+	 *
57
+	 * @return int
58
+	 */
59
+	protected function getNow()
60
+	{
61
+		return (int) DBDatetime::now()->getTimestamp();
62
+	}
63 63
 }
Please login to merge, or discard this patch.
src/Model/HybridSessionDataObject.php 1 patch
Indentation   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -6,18 +6,18 @@
 block discarded – undo
6 6
 
7 7
 class HybridSessionDataObject extends DataObject
8 8
 {
9
-    private static $db = [
10
-        'SessionID' => 'Varchar(64)',
11
-        'Expiry' => 'Int',
12
-        'Data' => 'Text'
13
-    ];
9
+	private static $db = [
10
+		'SessionID' => 'Varchar(64)',
11
+		'Expiry' => 'Int',
12
+		'Data' => 'Text'
13
+	];
14 14
 
15
-    private static $indexes = [
16
-        'SessionID' => [
17
-            'type' => 'unique'
18
-        ],
19
-        'Expiry' => true
20
-    ];
15
+	private static $indexes = [
16
+		'SessionID' => [
17
+			'type' => 'unique'
18
+		],
19
+		'Expiry' => true
20
+	];
21 21
 
22
-    private static $table_name = 'HybridSessionDataObject';
22
+	private static $table_name = 'HybridSessionDataObject';
23 23
 }
Please login to merge, or discard this patch.
src/Crypto/CryptoHandler.php 1 patch
Indentation   +20 added lines, -20 removed lines patch added patch discarded remove patch
@@ -5,27 +5,27 @@
 block discarded – undo
5 5
 interface CryptoHandler
6 6
 {
7 7
 
8
-    /**
9
-     * @param string $data
10
-     *
11
-     * @return string
12
-     */
13
-    public function encrypt($data);
8
+	/**
9
+	 * @param string $data
10
+	 *
11
+	 * @return string
12
+	 */
13
+	public function encrypt($data);
14 14
 
15
-    /**
16
-     * @param string $data
17
-     *
18
-     * @return string
19
-     */
20
-    public function decrypt($data);
15
+	/**
16
+	 * @param string $data
17
+	 *
18
+	 * @return string
19
+	 */
20
+	public function decrypt($data);
21 21
 
22
-    /**
23
-     * @return string
24
-     */
25
-    public function getKey();
22
+	/**
23
+	 * @return string
24
+	 */
25
+	public function getKey();
26 26
 
27
-    /**
28
-     * @return string
29
-     */
30
-    public function getSalt();
27
+	/**
28
+	 * @return string
29
+	 */
30
+	public function getSalt();
31 31
 }
Please login to merge, or discard this patch.
src/Control/HybridSessionMiddleware.php 1 patch
Indentation   +18 added lines, -18 removed lines patch added patch discarded remove patch
@@ -8,25 +8,25 @@
 block discarded – undo
8 8
 
9 9
 class HybridSessionMiddleware implements HTTPMiddleware
10 10
 {
11
-    public function process(HTTPRequest $request, callable $delegate)
12
-    {
13
-        try {
14
-            // Start session and execute
15
-            $request->getSession()->init($request);
11
+	public function process(HTTPRequest $request, callable $delegate)
12
+	{
13
+		try {
14
+			// Start session and execute
15
+			$request->getSession()->init($request);
16 16
 
17
-            // Generate output
18
-            $response = $delegate($request);
19
-        } finally {
20
-            // Save session data, even if there was an exception
21
-            // Note that save() will start/resume the session if required.
22
-            $request->getSession()->save($request);
17
+			// Generate output
18
+			$response = $delegate($request);
19
+		} finally {
20
+			// Save session data, even if there was an exception
21
+			// Note that save() will start/resume the session if required.
22
+			$request->getSession()->save($request);
23 23
 
24
-            if (HybridSession::is_enabled()) {
25
-                // Close the session
26
-                session_write_close();
27
-            }
28
-        }
24
+			if (HybridSession::is_enabled()) {
25
+				// Close the session
26
+				session_write_close();
27
+			}
28
+		}
29 29
 
30
-        return $response;
31
-    }
30
+		return $response;
31
+	}
32 32
 }
Please login to merge, or discard this patch.
tests/ConfigurationTest.php 1 patch
Indentation   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -9,12 +9,12 @@
 block discarded – undo
9 9
 
10 10
 class ConfigurationTest extends SapphireTest
11 11
 {
12
-    public function testHybridSessionsSessionMiddlewareReplacesCore()
13
-    {
14
-        $this->assertInstanceOf(
15
-            HybridSessionMiddleware::class,
16
-            Injector::inst()->get(SessionMiddleware::class),
17
-            'HybridSession\'s middleware should replace the default SessionMiddleware'
18
-        );
19
-    }
12
+	public function testHybridSessionsSessionMiddlewareReplacesCore()
13
+	{
14
+		$this->assertInstanceOf(
15
+			HybridSessionMiddleware::class,
16
+			Injector::inst()->get(SessionMiddleware::class),
17
+			'HybridSession\'s middleware should replace the default SessionMiddleware'
18
+		);
19
+	}
20 20
 }
Please login to merge, or discard this patch.
tests/AbstractTest.php 1 patch
Indentation   +100 added lines, -100 removed lines patch added patch discarded remove patch
@@ -10,104 +10,104 @@
 block discarded – undo
10 10
 
11 11
 abstract class AbstractTest extends SapphireTest
12 12
 {
13
-    protected $usesDatabase = true;
14
-
15
-    protected function setUp()
16
-    {
17
-        parent::setUp();
18
-
19
-        TestCookieStore::$override_headers_sent = false;
20
-
21
-        Injector::inst()->registerService(
22
-            new TestCookieStore(),
23
-            CookieStore::class
24
-        );
25
-
26
-        DBDatetime::set_mock_now('2010-03-15 12:00:00');
27
-    }
28
-
29
-    protected function tearDown()
30
-    {
31
-        DBDatetime::clear_mock_now();
32
-
33
-        parent::tearDown();
34
-    }
35
-
36
-    abstract protected function getStore();
37
-
38
-    /**
39
-     * Test how this store handles large volumes of data (>1000 characters)
40
-     */
41
-    public function testStoreLargeData()
42
-    {
43
-        $session = uniqid();
44
-        $store = $this->getStore();
45
-
46
-        // Test new session is blank
47
-        $result = $store->read($session);
48
-        $this->assertEmpty($result);
49
-
50
-        // Save data against session
51
-        $data1 = array(
52
-            'Large' => str_repeat('A', 600),
53
-            'Content' => str_repeat('B', 600)
54
-        );
55
-        $store->write($session, serialize($data1));
56
-        $result = $store->read($session);
57
-        $this->assertEquals($data1, unserialize($result));
58
-    }
59
-
60
-    /**
61
-     * Test storage of data
62
-     */
63
-    public function testStoreData()
64
-    {
65
-        $session = uniqid();
66
-        $store = $this->getStore();
67
-
68
-        // Test new session is blank
69
-        $result = $store->read($session);
70
-        $this->assertEmpty($result);
71
-
72
-        // Save data against session
73
-        $data1 = array(
74
-            'Color' => 'red',
75
-            'Animal' => 'elephant'
76
-        );
77
-        $store->write($session, serialize($data1));
78
-        $result = $store->read($session);
79
-        $this->assertEquals($data1, unserialize($result));
80
-
81
-        // Save larger data
82
-        $data2 = array(
83
-            'Color' => 'blue',
84
-            'Animal' => str_repeat('bat', 100)
85
-        );
86
-        $store->write($session, serialize($data2));
87
-        $result = $store->read($session);
88
-        $this->assertEquals($data2, unserialize($result));
89
-    }
90
-
91
-    /**
92
-     * Test expiry of data
93
-     */
94
-    public function testExpiry()
95
-    {
96
-        $session1 = uniqid();
97
-        $store = $this->getStore();
98
-
99
-        // Store data now
100
-        $data1 = array(
101
-            'Food' => 'Pizza'
102
-        );
103
-        $store->write($session1, serialize($data1));
104
-        $result1 = $store->read($session1);
105
-        $this->assertEquals($data1, unserialize($result1));
106
-
107
-        // Go to the future and test that the expiry is accurate
108
-        DBDatetime::set_mock_now('2040-03-16 12:00:00');
109
-        $result2 = $store->read($session1);
110
-
111
-        $this->assertEmpty($result2);
112
-    }
13
+	protected $usesDatabase = true;
14
+
15
+	protected function setUp()
16
+	{
17
+		parent::setUp();
18
+
19
+		TestCookieStore::$override_headers_sent = false;
20
+
21
+		Injector::inst()->registerService(
22
+			new TestCookieStore(),
23
+			CookieStore::class
24
+		);
25
+
26
+		DBDatetime::set_mock_now('2010-03-15 12:00:00');
27
+	}
28
+
29
+	protected function tearDown()
30
+	{
31
+		DBDatetime::clear_mock_now();
32
+
33
+		parent::tearDown();
34
+	}
35
+
36
+	abstract protected function getStore();
37
+
38
+	/**
39
+	 * Test how this store handles large volumes of data (>1000 characters)
40
+	 */
41
+	public function testStoreLargeData()
42
+	{
43
+		$session = uniqid();
44
+		$store = $this->getStore();
45
+
46
+		// Test new session is blank
47
+		$result = $store->read($session);
48
+		$this->assertEmpty($result);
49
+
50
+		// Save data against session
51
+		$data1 = array(
52
+			'Large' => str_repeat('A', 600),
53
+			'Content' => str_repeat('B', 600)
54
+		);
55
+		$store->write($session, serialize($data1));
56
+		$result = $store->read($session);
57
+		$this->assertEquals($data1, unserialize($result));
58
+	}
59
+
60
+	/**
61
+	 * Test storage of data
62
+	 */
63
+	public function testStoreData()
64
+	{
65
+		$session = uniqid();
66
+		$store = $this->getStore();
67
+
68
+		// Test new session is blank
69
+		$result = $store->read($session);
70
+		$this->assertEmpty($result);
71
+
72
+		// Save data against session
73
+		$data1 = array(
74
+			'Color' => 'red',
75
+			'Animal' => 'elephant'
76
+		);
77
+		$store->write($session, serialize($data1));
78
+		$result = $store->read($session);
79
+		$this->assertEquals($data1, unserialize($result));
80
+
81
+		// Save larger data
82
+		$data2 = array(
83
+			'Color' => 'blue',
84
+			'Animal' => str_repeat('bat', 100)
85
+		);
86
+		$store->write($session, serialize($data2));
87
+		$result = $store->read($session);
88
+		$this->assertEquals($data2, unserialize($result));
89
+	}
90
+
91
+	/**
92
+	 * Test expiry of data
93
+	 */
94
+	public function testExpiry()
95
+	{
96
+		$session1 = uniqid();
97
+		$store = $this->getStore();
98
+
99
+		// Store data now
100
+		$data1 = array(
101
+			'Food' => 'Pizza'
102
+		);
103
+		$store->write($session1, serialize($data1));
104
+		$result1 = $store->read($session1);
105
+		$this->assertEquals($data1, unserialize($result1));
106
+
107
+		// Go to the future and test that the expiry is accurate
108
+		DBDatetime::set_mock_now('2040-03-16 12:00:00');
109
+		$result2 = $store->read($session1);
110
+
111
+		$this->assertEmpty($result2);
112
+	}
113 113
 }
Please login to merge, or discard this patch.
src/HybridSession.php 2 patches
Doc Comments   +2 added lines patch added patch discarded remove patch
@@ -25,6 +25,7 @@  discard block
 block discarded – undo
25 25
 
26 26
     /**
27 27
      * @param SessionHandlerInterface[]
28
+     * @param BaseStore[] $handlers
28 29
      *
29 30
      * @return $this
30 31
      */
@@ -38,6 +39,7 @@  discard block
 block discarded – undo
38 39
 
39 40
     /**
40 41
      * @param string
42
+     * @param string $key
41 43
      *
42 44
      * @return $this
43 45
      */
Please login to merge, or discard this patch.
Indentation   +148 added lines, -148 removed lines patch added patch discarded remove patch
@@ -9,152 +9,152 @@
 block discarded – undo
9 9
 class HybridSession extends BaseStore
10 10
 {
11 11
 
12
-    /**
13
-     * List of session handlers
14
-     *
15
-     * @var array
16
-     */
17
-    protected $handlers = [];
18
-
19
-    /**
20
-     * True if this session store has been initialised
21
-     *
22
-     * @var bool
23
-     */
24
-    protected static $enabled = false;
25
-
26
-    /**
27
-     * @param SessionHandlerInterface[]
28
-     *
29
-     * @return $this
30
-     */
31
-    public function setHandlers($handlers)
32
-    {
33
-        $this->handlers = $handlers;
34
-        $this->setKey($this->getKey());
35
-
36
-        return $this;
37
-    }
38
-
39
-    /**
40
-     * @param string
41
-     *
42
-     * @return $this
43
-     */
44
-    public function setKey($key)
45
-    {
46
-        parent::setKey($key);
47
-
48
-        foreach ($this->getHandlers() as $handler) {
49
-            $handler->setKey($key);
50
-        }
51
-
52
-        return $this;
53
-    }
54
-
55
-    /**
56
-     * @return SessionHandlerInterface[]
57
-     */
58
-    public function getHandlers()
59
-    {
60
-        return $this->handlers ?: [];
61
-    }
62
-
63
-    /**
64
-     * @param string $save_path
65
-     * @param string $name
66
-     *
67
-     * @return bool
68
-     */
69
-    public function open($save_path, $name)
70
-    {
71
-        foreach ($this->getHandlers() as $handler) {
72
-            $handler->open($save_path, $name);
73
-        }
74
-
75
-        return true;
76
-    }
77
-
78
-    /**
79
-     * @return bool
80
-     */
81
-    public function close()
82
-    {
83
-        foreach ($this->getHandlers() as $handler) {
84
-            $handler->close();
85
-        }
86
-
87
-        return true;
88
-    }
89
-
90
-    /**
91
-     * @param string $session_id
92
-     *
93
-     * @return string
94
-     */
95
-    public function read($session_id)
96
-    {
97
-        foreach ($this->getHandlers() as $handler) {
98
-            if ($data = $handler->read($session_id)) {
99
-                return $data;
100
-            }
101
-        }
102
-
103
-        return '';
104
-    }
105
-
106
-    public function write($session_id, $session_data)
107
-    {
108
-        foreach ($this->getHandlers() as $handler) {
109
-            if ($handler->write($session_id, $session_data)) {
110
-                return true;
111
-            }
112
-        }
113
-
114
-        return false;
115
-    }
116
-
117
-    public function destroy($session_id)
118
-    {
119
-        foreach ($this->getHandlers() as $handler) {
120
-            $handler->destroy($session_id);
121
-        }
122
-
123
-        return true;
124
-    }
125
-
126
-    public function gc($maxlifetime)
127
-    {
128
-        foreach ($this->getHandlers() as $handler) {
129
-            $handler->gc($maxlifetime);
130
-        }
131
-    }
132
-
133
-    /**
134
-     * Register the session handler as the default
135
-     *
136
-     * @param string $key Desired session key
137
-     */
138
-    public static function init($key = null)
139
-    {
140
-        $instance = Injector::inst()->get(__CLASS__);
141
-
142
-        if (empty($key)) {
143
-            user_error(
144
-                'HybridSession::init() was not given a $key. Disabling cookie-based storage',
145
-                E_USER_WARNING
146
-            );
147
-        } else {
148
-            $instance->setKey($key);
149
-        }
150
-
151
-        session_set_save_handler($instance, true);
152
-
153
-        self::$enabled = true;
154
-    }
155
-
156
-    public static function is_enabled()
157
-    {
158
-        return self::$enabled;
159
-    }
12
+	/**
13
+	 * List of session handlers
14
+	 *
15
+	 * @var array
16
+	 */
17
+	protected $handlers = [];
18
+
19
+	/**
20
+	 * True if this session store has been initialised
21
+	 *
22
+	 * @var bool
23
+	 */
24
+	protected static $enabled = false;
25
+
26
+	/**
27
+	 * @param SessionHandlerInterface[]
28
+	 *
29
+	 * @return $this
30
+	 */
31
+	public function setHandlers($handlers)
32
+	{
33
+		$this->handlers = $handlers;
34
+		$this->setKey($this->getKey());
35
+
36
+		return $this;
37
+	}
38
+
39
+	/**
40
+	 * @param string
41
+	 *
42
+	 * @return $this
43
+	 */
44
+	public function setKey($key)
45
+	{
46
+		parent::setKey($key);
47
+
48
+		foreach ($this->getHandlers() as $handler) {
49
+			$handler->setKey($key);
50
+		}
51
+
52
+		return $this;
53
+	}
54
+
55
+	/**
56
+	 * @return SessionHandlerInterface[]
57
+	 */
58
+	public function getHandlers()
59
+	{
60
+		return $this->handlers ?: [];
61
+	}
62
+
63
+	/**
64
+	 * @param string $save_path
65
+	 * @param string $name
66
+	 *
67
+	 * @return bool
68
+	 */
69
+	public function open($save_path, $name)
70
+	{
71
+		foreach ($this->getHandlers() as $handler) {
72
+			$handler->open($save_path, $name);
73
+		}
74
+
75
+		return true;
76
+	}
77
+
78
+	/**
79
+	 * @return bool
80
+	 */
81
+	public function close()
82
+	{
83
+		foreach ($this->getHandlers() as $handler) {
84
+			$handler->close();
85
+		}
86
+
87
+		return true;
88
+	}
89
+
90
+	/**
91
+	 * @param string $session_id
92
+	 *
93
+	 * @return string
94
+	 */
95
+	public function read($session_id)
96
+	{
97
+		foreach ($this->getHandlers() as $handler) {
98
+			if ($data = $handler->read($session_id)) {
99
+				return $data;
100
+			}
101
+		}
102
+
103
+		return '';
104
+	}
105
+
106
+	public function write($session_id, $session_data)
107
+	{
108
+		foreach ($this->getHandlers() as $handler) {
109
+			if ($handler->write($session_id, $session_data)) {
110
+				return true;
111
+			}
112
+		}
113
+
114
+		return false;
115
+	}
116
+
117
+	public function destroy($session_id)
118
+	{
119
+		foreach ($this->getHandlers() as $handler) {
120
+			$handler->destroy($session_id);
121
+		}
122
+
123
+		return true;
124
+	}
125
+
126
+	public function gc($maxlifetime)
127
+	{
128
+		foreach ($this->getHandlers() as $handler) {
129
+			$handler->gc($maxlifetime);
130
+		}
131
+	}
132
+
133
+	/**
134
+	 * Register the session handler as the default
135
+	 *
136
+	 * @param string $key Desired session key
137
+	 */
138
+	public static function init($key = null)
139
+	{
140
+		$instance = Injector::inst()->get(__CLASS__);
141
+
142
+		if (empty($key)) {
143
+			user_error(
144
+				'HybridSession::init() was not given a $key. Disabling cookie-based storage',
145
+				E_USER_WARNING
146
+			);
147
+		} else {
148
+			$instance->setKey($key);
149
+		}
150
+
151
+		session_set_save_handler($instance, true);
152
+
153
+		self::$enabled = true;
154
+	}
155
+
156
+	public static function is_enabled()
157
+	{
158
+		return self::$enabled;
159
+	}
160 160
 }
Please login to merge, or discard this patch.
tests/HybridSessionTest.php 1 patch
Indentation   +79 added lines, -79 removed lines patch added patch discarded remove patch
@@ -9,83 +9,83 @@
 block discarded – undo
9 9
 
10 10
 class HybridSessionTest extends SapphireTest
11 11
 {
12
-    /**
13
-     * @var BaseStore
14
-     */
15
-    protected $handler;
16
-
17
-    /**
18
-     * @var HybridSession
19
-     */
20
-    protected $instance;
21
-
22
-    protected function setUp()
23
-    {
24
-        parent::setUp();
25
-
26
-        $this->handler = $this->createMock(TestCookieStore::class);
27
-
28
-        $this->instance = new HybridSession();
29
-    }
30
-
31
-    public function testSetHandlersAlsoSetsKeyToEachHandler()
32
-    {
33
-        $this->instance->setKey('foobar');
34
-        $this->handler->expects($this->once())->method('setKey')->with('foobar');
35
-        $this->instance->setHandlers([$this->handler]);
36
-    }
37
-
38
-    public function testOpenDelegatesToAllHandlers()
39
-    {
40
-        $this->handler->expects($this->once())->method('open')->with('foo', 'bar');
41
-        $this->instance->setHandlers([$this->handler]);
42
-        $this->assertTrue($this->instance->open('foo', 'bar'), 'Method returns true after delegation');
43
-    }
44
-
45
-    public function testCloseDelegatesToAllHandlers()
46
-    {
47
-        $this->handler->expects($this->once())->method('close');
48
-        $this->instance->setHandlers([$this->handler]);
49
-        $this->assertTrue($this->instance->close(), 'Method returns true after delegation');
50
-    }
51
-
52
-    public function testReadReturnsEmptyStringWithNoHandlers()
53
-    {
54
-        $this->handler->expects($this->once())->method('read')->with('foosession')->willReturn(false);
55
-        $this->instance->setHandlers([$this->handler]);
56
-        $this->assertSame('', $this->instance->read('foosession'));
57
-    }
58
-
59
-    public function testReadReturnsHandlerDelegateResult()
60
-    {
61
-        $this->handler->expects($this->once())->method('read')->with('foo.session')->willReturn('success!');
62
-        $this->instance->setHandlers([$this->handler]);
63
-        $this->assertSame('success!', $this->instance->read('foo.session'));
64
-    }
65
-
66
-    public function testWriteDelegatesToHandlerAndReturnsTrue()
67
-    {
68
-        $this->handler->expects($this->once())->method('write')->with('foo', 'bar')->willReturn(true);
69
-        $this->instance->setHandlers([$this->handler]);
70
-        $this->assertTrue($this->instance->write('foo', 'bar'));
71
-    }
72
-
73
-    public function testWriteReturnsFalseWithNoHandlers()
74
-    {
75
-        $this->assertFalse($this->instance->write('no', 'handlers'));
76
-    }
77
-
78
-    public function testDestroyDelegatesToHandler()
79
-    {
80
-        $this->handler->expects($this->once())->method('destroy')->with('sessid1234');
81
-        $this->instance->setHandlers([$this->handler]);
82
-        $this->assertTrue($this->instance->destroy('sessid1234'), 'Method returns true after delegation');
83
-    }
84
-
85
-    public function testGcDelegatesToHandlers()
86
-    {
87
-        $this->handler->expects($this->once())->method('gc')->with(12345);
88
-        $this->instance->setHandlers([$this->handler]);
89
-        $this->instance->gc(12345);
90
-    }
12
+	/**
13
+	 * @var BaseStore
14
+	 */
15
+	protected $handler;
16
+
17
+	/**
18
+	 * @var HybridSession
19
+	 */
20
+	protected $instance;
21
+
22
+	protected function setUp()
23
+	{
24
+		parent::setUp();
25
+
26
+		$this->handler = $this->createMock(TestCookieStore::class);
27
+
28
+		$this->instance = new HybridSession();
29
+	}
30
+
31
+	public function testSetHandlersAlsoSetsKeyToEachHandler()
32
+	{
33
+		$this->instance->setKey('foobar');
34
+		$this->handler->expects($this->once())->method('setKey')->with('foobar');
35
+		$this->instance->setHandlers([$this->handler]);
36
+	}
37
+
38
+	public function testOpenDelegatesToAllHandlers()
39
+	{
40
+		$this->handler->expects($this->once())->method('open')->with('foo', 'bar');
41
+		$this->instance->setHandlers([$this->handler]);
42
+		$this->assertTrue($this->instance->open('foo', 'bar'), 'Method returns true after delegation');
43
+	}
44
+
45
+	public function testCloseDelegatesToAllHandlers()
46
+	{
47
+		$this->handler->expects($this->once())->method('close');
48
+		$this->instance->setHandlers([$this->handler]);
49
+		$this->assertTrue($this->instance->close(), 'Method returns true after delegation');
50
+	}
51
+
52
+	public function testReadReturnsEmptyStringWithNoHandlers()
53
+	{
54
+		$this->handler->expects($this->once())->method('read')->with('foosession')->willReturn(false);
55
+		$this->instance->setHandlers([$this->handler]);
56
+		$this->assertSame('', $this->instance->read('foosession'));
57
+	}
58
+
59
+	public function testReadReturnsHandlerDelegateResult()
60
+	{
61
+		$this->handler->expects($this->once())->method('read')->with('foo.session')->willReturn('success!');
62
+		$this->instance->setHandlers([$this->handler]);
63
+		$this->assertSame('success!', $this->instance->read('foo.session'));
64
+	}
65
+
66
+	public function testWriteDelegatesToHandlerAndReturnsTrue()
67
+	{
68
+		$this->handler->expects($this->once())->method('write')->with('foo', 'bar')->willReturn(true);
69
+		$this->instance->setHandlers([$this->handler]);
70
+		$this->assertTrue($this->instance->write('foo', 'bar'));
71
+	}
72
+
73
+	public function testWriteReturnsFalseWithNoHandlers()
74
+	{
75
+		$this->assertFalse($this->instance->write('no', 'handlers'));
76
+	}
77
+
78
+	public function testDestroyDelegatesToHandler()
79
+	{
80
+		$this->handler->expects($this->once())->method('destroy')->with('sessid1234');
81
+		$this->instance->setHandlers([$this->handler]);
82
+		$this->assertTrue($this->instance->destroy('sessid1234'), 'Method returns true after delegation');
83
+	}
84
+
85
+	public function testGcDelegatesToHandlers()
86
+	{
87
+		$this->handler->expects($this->once())->method('gc')->with(12345);
88
+		$this->instance->setHandlers([$this->handler]);
89
+		$this->instance->gc(12345);
90
+	}
91 91
 }
Please login to merge, or discard this patch.