Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
19.30% covered (danger)
19.30%
11 / 57
18.75% covered (danger)
18.75%
3 / 16
CRAP
0.00% covered (danger)
0.00%
0 / 1
SessionData
19.30% covered (danger)
19.30%
11 / 57
18.75% covered (danger)
18.75%
3 / 16
678.85
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getSession
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
20
 writeData
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 setGroup
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
42
 set
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
12
 get
80.00% covered (warning)
80.00%
4 / 5
0.00% covered (danger)
0.00%
0 / 1
3.07
 getEntity
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
 setEntityClass
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 remove
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 clearGroup
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 clear
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 restart
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 has
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 isEmpty
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 jsonSerialize
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 convertValueToScalar
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace BO\Slim\Middleware\Session;
4
5use Psr\Http\Message\ServerRequestInterface as Request;
6
7class SessionData implements SessionInterface
8{
9    /**
10     * @var array
11     */
12    protected $data;
13
14    /**
15     * @var boolean
16     */
17    private $isLocked = false;
18
19
20    protected $entityClass = null;
21
22    /**
23     * __construct is not allowed, use
24     * - {@see SessionData::getSessionFromName}
25     * instead
26     */
27    public function __construct($data = null)
28    {
29        $this->data = $data;
30    }
31
32    /**
33     *
34     * @SuppressWarnings(Superglobals)
35     * @SuppressWarnings(Unused)
36     *
37     * @return self
38     */
39    public static function getSession(Request $request)
40    {
41        if (headers_sent() === false && session_status() !== PHP_SESSION_ACTIVE) {
42            session_start();
43            if (!count($_SESSION)) {
44                $_SESSION['status'] = 'start';
45            };
46            $session = $_SESSION;
47        } else {
48            throw  new \BO\Slim\Exception\SessionFailed("Headers sent or a session is already active");
49        }
50
51        $instance = new self();
52        $instance->data = $session;
53        return $instance;
54    }
55
56    public function writeData()
57    {
58        session_write_close();
59        $this->isLocked = true;
60    }
61
62    #[\Override]
63    public function setGroup(array $group, $clear)
64    {
65        foreach ($group as $index => $items) {
66            if ($clear) {
67                $this->clearGroup($index);
68            }
69            if (is_array($items) && 0 < count($items)) {
70                foreach ($items as $key => $value) {
71                    $this->set($key, $value, $index);
72                }
73            }
74        }
75    }
76
77    /**
78     *
79     * @SuppressWarnings(Superglobals)
80     *
81     * @return array
82     */
83    #[\Override]
84    public function set($key, $value, $groupIndex = null)
85    {
86        if (null === $groupIndex) {
87            $this->data[$key] = self::convertValueToScalar($value);
88        } else {
89            $this->data[$groupIndex][$key] = self::convertValueToScalar($value);
90        }
91        if ($this->isLocked) {
92            throw new \BO\Slim\Exception\SessionLocked();
93        }
94        $_SESSION = $this->data;
95    }
96
97    #[\Override]
98    public function get($key, $groupIndex = null, $default = null)
99    {
100        if (! $this->has($key, $groupIndex)) {
101            return self::convertValueToScalar($default);
102        } elseif (null === $groupIndex) {
103            return $this->data[$key];
104        } else {
105            return $this->data[$groupIndex][$key];
106        }
107    }
108
109    #[\Override]
110    public function getEntity()
111    {
112        if (null === $this->entityClass) {
113            throw new \Exception("Entity-Class not set");
114        }
115        $sessionContent = clone $this->entityClass;
116        $sessionContent->content = $this->data;
117        return $sessionContent;
118    }
119
120    public function setEntityClass($entityClass)
121    {
122        $this->entityClass = $entityClass;
123        return $this;
124    }
125
126    #[\Override]
127    public function remove($key, $groupIndex = null)
128    {
129        if (null === $groupIndex) {
130            unset($this->data[$key]);
131        } else {
132            unset($this->data[$groupIndex][$key]);
133        }
134    }
135
136    /**
137     *
138     * @SuppressWarnings(Superglobals)
139     *
140     * @return self
141     */
142    #[\Override]
143    public function clearGroup($groupIndex = null)
144    {
145        if (null !== $groupIndex) {
146            $this->data[$groupIndex] = [];
147            $_SESSION = $this->data;
148        }
149    }
150
151    /**
152     *
153     * @SuppressWarnings(Superglobals)
154     *
155     * @return self
156     */
157    #[\Override]
158    public function clear()
159    {
160        if (session_status() === PHP_SESSION_ACTIVE) {
161            setcookie(session_name(), '', time() - 3600, '/');
162            $_SESSION = array();
163            session_destroy();
164        }
165    }
166
167    /**
168     *
169     * @SuppressWarnings(Superglobals)
170     *
171     * @return self
172     */
173    public function restart()
174    {
175        if (session_status() === PHP_SESSION_ACTIVE) {
176            session_regenerate_id(true);
177            $_SESSION = array();
178            $this->data = $_SESSION;
179        }
180    }
181
182    #[\Override]
183    public function has($key, $groupIndex = null)
184    {
185        if (null === $groupIndex) {
186            return array_key_exists($key, $this->data);
187        } else {
188            if (array_key_exists($groupIndex, $this->data)) {
189                return array_key_exists($key, $this->data[$groupIndex]);
190            }
191        }
192    }
193
194    #[\Override]
195    public function isEmpty()
196    {
197        return empty($this->data);
198    }
199
200    // TODO: Review the use of `mixed` return type.
201    // This method delegates to getSession()->jsonSerialize(), which may return various types.
202    // Consider adding stricter return typing if getSession() can be more precisely typed.
203    #[\Override]
204    public function jsonSerialize(): mixed
205    {
206        return json_encode($this->data);
207    }
208
209    private static function convertValueToScalar($value)
210    {
211        return json_decode(json_encode($value), true);
212    }
213}