Completed
Push — 15627-fix-session ( a23a32 )
by Alexander
17:43
created

MultiFieldSession::getUseCustomStorage()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
ccs 0
cts 2
cp 0
cc 1
eloc 2
nc 1
nop 0
crap 2
1
<?php
2
/**
3
 * @link http://www.yiiframework.com/
4
 * @copyright Copyright (c) 2008 Yii Software LLC
5
 * @license http://www.yiiframework.com/license/
6
 */
7
8
namespace yii\web;
9
10
/**
11
 * MultiFieldSession is the base class for session storage implementations with multi-field data storage support.
12
 *
13
 * With multi-field data storage, session data can be split between several fields in the storage record.
14
 * Using such a storage allows saving particular session data into separated field, which then can be used
15
 * to manipulate sessions in the way plain PHP does not allow.
16
 *
17
 * For example the ID of the authenticated user can be saved as separated column in the MySQL 'session' table,
18
 * which allows to query all active sessions for a particular user or terminate them at will.
19
 *
20
 * Customizing of the session writing is performed via [[writeCallback]], reading via [[readCallback]].
21
 *
22
 * While extending this class you should use [[composeFields()]] method - while writing the session data into the storage and
23
 * [[extractData()]] - while reading session data from the storage.
24
 *
25
 * @property bool $useCustomStorage Whether to use custom storage. This property is read-only.
26
 *
27
 * @author Paul Klimov <[email protected]>
28
 * @since 2.0.6
29
 */
30
abstract class MultiFieldSession extends Session
31
{
32
    /**
33
     * @var callable a callback that will be called during session data reading.
34
     * The signature of the callback should be as follows:
35
     *
36
     * ```
37
     * function ($fields)
38
     * ```
39
     *
40
     * where `$fields` is the storage field set for read session and `$session` is this session instance.
41
     * If callback returns an array, it will be merged into the session data.
42
     *
43
     * For example:
44
     *
45
     * ```php
46
     * function ($fields) {
47
     *     return [
48
     *         'expireDate' => Yii::$app->formatter->asDate($fields['expire']),
49
     *     ];
50
     * }
51
     * ```
52
     */
53
    public $readCallback;
54
    /**
55
     * @var callable a callback that will be called during session data writing.
56
     * The signature of the callback should be as follows:
57
     *
58
     * ```
59
     * function ($session)
60
     * ```
61
     *
62
     * where `$session` is this session instance, this variable can be used to retrieve session data.
63
     * Callback should return the actual fields set, which should be saved into the session storage.
64
     *
65
     * For example:
66
     *
67
     * ```php
68
     * function ($session) {
69
     *     return [
70
     *         'user_id' => Yii::$app->user->id,
71
     *         'ip' => $_SERVER['REMOTE_ADDR'],
72
     *         'is_trusted' => $session->get('is_trusted', false),
73
     *     ];
74
     * }
75
     * ```
76
     */
77
    public $writeCallback;
78
79
80
    /**
81
     * Returns a value indicating whether to use custom session storage.
82
     * This method overrides the parent implementation and always returns true.
83
     * @return bool whether to use custom storage.
84
     */
85
    public function getUseCustomStorage()
86
    {
87
        return true;
88
    }
89
90
    /**
91
     * Composes storage field set for session writing.
92
     * @param string $id session id
93
     * @param string $data session data
94
     * @return array storage fields
95
     */
96 15
    protected function composeFields($id, $data)
97
    {
98
        $fields = [
99 15
            'data' => $data,
100
        ];
101 15
        if ($this->writeCallback !== null) {
102 3
            $fields = array_merge(
103 3
                $fields,
104 3
                call_user_func($this->writeCallback, $this)
105
            );
106 3
            if (!is_string($fields['data'])) {
107
                $_SESSION = $fields['data'];
108
                $fields['data'] = session_encode();
109
            }
110
        }
111
        // ensure 'id' and 'expire' are never affected by [[writeCallback]]
112 15
        $fields = array_merge($fields, [
113 15
            'id' => $id,
114 15
            'expire' => time() + $this->getTimeout(),
115
        ]);
116 15
        return $fields;
117
    }
118
119
    /**
120
     * Extracts session data from storage field set.
121
     * @param array $fields storage fields.
122
     * @return string session data.
123
     */
124
    protected function extractData($fields)
125
    {
126
        if ($this->readCallback !== null) {
127
            if (!isset($fields['data'])) {
128
                $fields['data'] = '';
129
            }
130
            $extraData = call_user_func($this->readCallback, $fields);
131
            if (!empty($extraData)) {
132
                session_decode($fields['data']);
133
                $_SESSION = array_merge((array) $_SESSION, (array) $extraData);
134
                return session_encode();
135
            }
136
137
            return $fields['data'];
138
        }
139
140
        return isset($fields['data']) ? $fields['data'] : '';
141
    }
142
}
143