Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
21 / 21
100.00% covered (success)
100.00%
11 / 11
CRAP
100.00% covered (success)
100.00%
1 / 1
AbstractSession
100.00% covered (success)
100.00%
21 / 21
100.00% covered (success)
100.00%
11 / 11
17
100.00% covered (success)
100.00%
1 / 1
 kill
n/a
0 / 0
n/a
0 / 0
0
 setTimedValue
n/a
0 / 0
n/a
0 / 0
0
 setRequestValue
n/a
0 / 0
n/a
0 / 0
0
 count
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getIterator
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 toArray
n/a
0 / 0
n/a
0 / 0
0
 jsonSerialize
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 checkRequestValue
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
3
 checkRequestValues
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 checkExpirationValue
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 checkExpirationValues
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 __get
n/a
0 / 0
n/a
0 / 0
0
 __set
n/a
0 / 0
n/a
0 / 0
0
 __isset
n/a
0 / 0
n/a
0 / 0
0
 __unset
n/a
0 / 0
n/a
0 / 0
0
 offsetSet
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 offsetGet
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 offsetExists
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 offsetUnset
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2declare(strict_types=1);
3/**
4 * Pop PHP Framework (https://www.popphp.org/)
5 *
6 * @link       https://github.com/popphp/popphp-framework
7 * @author     Nick Sagona, III <nick@popphp.org>
8 * @copyright  Copyright (c) 2009-2026 Nick Sagona, III
9 * @license    https://www.popphp.org/license     New BSD License
10 */
11
12/**
13 * @namespace
14 */
15namespace Pop\Session;
16
17use ArrayAccess;
18use ArrayIterator;
19use Countable;
20use IteratorAggregate;
21use JsonSerializable;
22
23/**
24 * Abstract session class
25 *
26 * @category   Pop
27 * @package    Pop\Session
28 * @author     Nick Sagona, III <nick@popphp.org>
29 * @copyright  Copyright (c) 2009-2026 Nick Sagona, III
30 * @license    https://www.popphp.org/license     New BSD License
31 * @version    5.0.0
32 */
33abstract class AbstractSession implements SessionInterface, ArrayAccess, Countable, IteratorAggregate, JsonSerializable
34{
35
36    /**
37     * Destroy the session
38     *
39     * @return void
40     */
41    abstract public function kill(): void;
42
43    /**
44     * Set a time-based value
45     *
46     * @param  string $key
47     * @param  mixed  $value
48     * @param  int    $expire
49     * @return AbstractSession
50     */
51    abstract public function setTimedValue(string $key, mixed $value, int $expire = 300): AbstractSession;
52
53    /**
54     * Set a request-based value
55     *
56     * @param  string $key
57     * @param  mixed  $value
58     * @param  int    $hops
59     * @return AbstractSession
60     */
61    abstract public function setRequestValue(string $key, mixed $value, int $hops = 1): AbstractSession;
62
63    /**
64     * Method to get the count of data in the session
65     *
66     * @return int
67     */
68    public function count(): int
69    {
70
71        return count($this->toArray());
72    }
73
74    /**
75     * Method to iterate over the session
76     *
77     * @return ArrayIterator
78     */
79    public function getIterator(): ArrayIterator
80    {
81        return new ArrayIterator($this->toArray());
82    }
83
84    /**
85     * Get the session values as an array
86     *
87     * @return array
88     */
89    abstract public function toArray(): array;
90
91    /**
92     * Get the session values for JSON serialization
93     *
94     * @return array
95     */
96    public function jsonSerialize(): array
97    {
98        return $this->toArray();
99    }
100
101    /**
102     * Check a single request-based value against its hop limit, removing it once the limit is exceeded
103     *
104     * @param  string $key
105     * @param  array  $data
106     * @param  array  $bookkeeping
107     * @return void
108     */
109    protected function checkRequestValue(string $key, array &$data, array &$bookkeeping): void
110    {
111        if (isset($bookkeeping['requests'][$key])) {
112            $bookkeeping['requests'][$key]['current']++;
113            $current = $bookkeeping['requests'][$key]['current'];
114            $limit   = $bookkeeping['requests'][$key]['limit'];
115            if ($current > $limit) {
116                unset($data[$key]);
117                unset($bookkeeping['requests'][$key]);
118            }
119        }
120    }
121
122    /**
123     * Check all request-based values against their hop limits
124     *
125     * @param  array $data
126     * @param  array $bookkeeping
127     * @return void
128     */
129    protected function checkRequestValues(array &$data, array &$bookkeeping): void
130    {
131        foreach (array_keys($bookkeeping['requests'] ?? []) as $key) {
132            $this->checkRequestValue($key, $data, $bookkeeping);
133        }
134    }
135
136    /**
137     * Check a single time-based value against its expiration, removing it once expired
138     *
139     * @param  string $key
140     * @param  array  $data
141     * @param  array  $bookkeeping
142     * @return void
143     */
144    protected function checkExpirationValue(string $key, array &$data, array &$bookkeeping): void
145    {
146        if (isset($bookkeeping['expirations'][$key]) && (time() > $bookkeeping['expirations'][$key])) {
147            unset($data[$key]);
148            unset($bookkeeping['expirations'][$key]);
149        }
150    }
151
152    /**
153     * Check all time-based values against their expirations
154     *
155     * @param  array $data
156     * @param  array $bookkeeping
157     * @return void
158     */
159    protected function checkExpirationValues(array &$data, array &$bookkeeping): void
160    {
161        foreach (array_keys($bookkeeping['expirations'] ?? []) as $key) {
162            $this->checkExpirationValue($key, $data, $bookkeeping);
163        }
164    }
165
166    /**
167     * Magic get method to return the value of values[$name].
168     *
169     * @param  string $name
170     * @return mixed
171     */
172    abstract public function __get(string $name): mixed;
173
174    /**
175     * Magic set method to set values[$name].
176     *
177     * @param  string $name
178     * @param  mixed $value
179     * @return void
180     */
181    abstract public function __set(string $name, mixed $value): void;
182
183    /**
184     * Return the isset value of values[$name].
185     *
186     * @param  string $name
187     * @return bool
188     */
189    abstract public function __isset(string $name): bool;
190
191    /**
192     * Unset values[$name].
193     *
194     * @param  string $name
195     * @return void
196     */
197    abstract public function __unset(string $name): void;
198
199    /**
200     * ArrayAccess offsetSet
201     *
202     * @param  mixed $offset
203     * @param  mixed $value
204     * @return void
205     */
206    public function offsetSet(mixed $offset, mixed $value): void
207    {
208        $this->__set($offset, $value);
209    }
210
211    /**
212     * ArrayAccess offsetGet
213     *
214     * @param  mixed $offset
215     * @return mixed
216     */
217    public function offsetGet(mixed $offset): mixed
218    {
219        return $this->__get($offset);
220    }
221
222    /**
223     * ArrayAccess offsetExists
224     *
225     * @param  mixed $offset
226     * @return bool
227     */
228    public function offsetExists(mixed $offset): bool
229    {
230        return $this->__isset($offset);
231    }
232
233    /**
234     * ArrayAccess offsetUnset
235     *
236     * @param  mixed $offset
237     * @return void
238     */
239    public function offsetUnset(mixed $offset): void
240    {
241        $this->__unset($offset);
242    }
243
244}