ILIAS  release_7 Revision v7.30-3-g800a261c036
class.ilLSStateDB.php
Go to the documentation of this file.
1<?php
2
3declare(strict_types=1);
4
11{
12 const TABLE_NAME = 'lso_states';
13
14 const CURRENT_ITEM_ID = "current_item";
15 const STATES = "states";
16 const FIRST_ACCESS = "first_access";
17 const LAST_ACCESS = "last_access";
18
22 protected $db;
23
24 public function __construct(ilDBInterface $db)
25 {
26 $this->db = $db;
27 }
28
32 public function getStatesFor(int $lso_ref_id, array $usr_ids = []) : array
33 {
34 $data = $this->select($lso_ref_id, $usr_ids);
35 $ret = [];
36 foreach ($usr_ids as $usr_id) {
37 $ret[$usr_id] = [];
38 if (array_key_exists($usr_id, $data)) {
39 $ret[$usr_id] = $data[$usr_id][self::STATES];
40 }
41 }
42
43 return $ret;
44 }
45
49 public function getCurrentItemsFor(int $lso_ref_id, array $usr_ids = []) : array
50 {
51 $data = $this->select($lso_ref_id, $usr_ids);
52 $ret = [];
53 foreach ($usr_ids as $usr_id) {
54 $ret[$usr_id] = -1;
55 if (array_key_exists($usr_id, $data)) {
56 $ret[$usr_id] = $data[$usr_id][self::CURRENT_ITEM_ID];
57 }
58 }
59
60 return $ret;
61 }
62
63 public function getFirstAccessFor(int $lso_ref_id, array $usr_ids = []) : array
64 {
65 $data = $this->select($lso_ref_id, $usr_ids);
66 $ret = [];
67 foreach ($usr_ids as $usr_id) {
68 $ret[$usr_id] = -1;
69 if (array_key_exists($usr_id, $data)) {
70 $ret[$usr_id] = $data[$usr_id][self::FIRST_ACCESS];
71 }
72 }
73
74 return $ret;
75 }
76
77 public function getLastAccessFor(int $lso_ref_id, array $usr_ids = []) : array
78 {
79 $data = $this->select($lso_ref_id, $usr_ids);
80 $ret = [];
81 foreach ($usr_ids as $usr_id) {
82 $ret[$usr_id] = -1;
83 if (array_key_exists($usr_id, $data)) {
84 $ret[$usr_id] = $data[$usr_id][self::LAST_ACCESS];
85 }
86 }
87
88 return $ret;
89 }
90
95 public function updateState(
96 int $lso_ref_id,
97 int $usr_id,
98 int $ref_id,
99 ILIAS\KioskMode\State $state,
100 int $current_item = null
101 ) {
102 $insert_first = $this->entryExistsFor($lso_ref_id, $usr_id) === false;
103 $states = $this->getStatesFor($lso_ref_id, [$usr_id]);
104 $states = $states[$usr_id];
105 $states[$ref_id] = $state;
106 $serialized = $this->serializeStates($states);
107 if (is_null($current_item)) {
108 $current_item = $ref_id;
109 }
110
111 $ilAtomQuery = $this->db->buildAtomQuery();
112 $ilAtomQuery->addTableLock(static::TABLE_NAME);
113 $ilAtomQuery->addQueryCallable(
114 function (ilDBInterface $db) use ($insert_first, $lso_ref_id, $usr_id, $current_item, $serialized) {
115 if ($insert_first) {
116 $this->insert($lso_ref_id, $usr_id);
117 }
118 $this->update($db, $lso_ref_id, $usr_id, $current_item, $serialized);
119 }
120 );
121
122 $ilAtomQuery->run();
123 }
124
125 protected function entryExistsFor(int $lso_ref_id, int $usr_id) : bool
126 {
127 return count($this->select($lso_ref_id, [$usr_id])) > 0;
128 }
129
130 protected function insert(int $lso_ref_id, int $usr_id)
131 {
132 $first_access = date("d.m.Y H:i:s");
133 $values = array(
134 "lso_ref_id" => array("integer", $lso_ref_id),
135 "usr_id" => array("integer", $usr_id),
136 "first_access" => array("text", $first_access)
137 );
138
139 $this->db->insert(static::TABLE_NAME, $values);
140 }
141
142 protected function update(
144 int $lso_ref_id,
145 int $usr_id,
146 int $current_item,
147 string $serialized
148 ) {
149 $last_access = date("d.m.Y H:i:s");
150 $where = array(
151 "lso_ref_id" => array("integer", $lso_ref_id),
152 "usr_id" => array("integer", $usr_id)
153 );
154 $values = array(
155 "current_item" => array("integer", $current_item),
156 "states" => array("text", $serialized),
157 "last_access" => array("text", $last_access)
158 );
159
160 $db->update(static::TABLE_NAME, $values, $where);
161 }
162
167 public function deleteFor(int $lso_ref_id, array $usr_ids = [])
168 {
169 $query =
170 "DELETE FROM " . static::TABLE_NAME . PHP_EOL
171 . "WHERE lso_ref_id = " . $this->db->quote($lso_ref_id, "integer") . PHP_EOL
172 ;
173
174 if (count($usr_ids) > 0) {
175 $query .= "AND usr_id IN (" . implode(',', $usr_ids) . ")";
176 }
177
178 $this->db->manipulate($query);
179 }
180
181 public function deleteForItem(int $lso_ref_id, int $item_ref_id)
182 {
183 $all_states = $this->select($lso_ref_id);
184 if (count($all_states) === 0) {
185 return;
186 }
187
188 $ilAtomQuery = $this->db->buildAtomQuery();
189 $ilAtomQuery->addTableLock(static::TABLE_NAME);
190 $ilAtomQuery->addQueryCallable(
191 function (ilDBInterface $db) use ($lso_ref_id, $all_states, $item_ref_id) {
192 foreach ($all_states as $usr_id => $state_entry) {
193 $current_item = $state_entry['current_item'];
194 $states = $state_entry['states'];
195
196 if ($current_item === $item_ref_id) {
197 $current_item = -1;
198 }
199
200 if (array_key_exists($item_ref_id, $states)) {
201 unset($states[$item_ref_id]);
202 }
203 $serialized = $this->serializeStates($states);
204 $this->update($db, $lso_ref_id, $usr_id, $current_item, $serialized);
205 }
206 }
207 );
208
209 $ilAtomQuery->run();
210 }
211
212
216 protected function buildStates(string $serialized) : array
217 {
218 $states = [];
219 $data = json_decode($serialized, true);
220 foreach ($data as $ref_id => $kvpair) {
221 $states[$ref_id] = new ILIAS\KioskMode\State();
222 if (is_array($kvpair)) {
223 foreach ($kvpair as $key => $value) {
224 $states[$ref_id] = $states[$ref_id]->withValueFor($key, $value);
225 }
226 }
227 }
228
229 return $states;
230 }
231
235 protected function serializeStates(array $states)
236 {
237 $data = [];
238 foreach ($states as $ref_id => $state) {
239 $data[$ref_id] = json_decode($state->serialize());
240 }
241
242 return json_encode($data);
243 }
244
245 protected function select(int $lso_ref_id, array $usr_ids = [])
246 {
247 $query =
248 "SELECT usr_id, current_item, states, first_access, last_access" . PHP_EOL
249 . "FROM " . static::TABLE_NAME . PHP_EOL
250 . "WHERE lso_ref_id = " . $this->db->quote($lso_ref_id, "integer") . PHP_EOL
251 ;
252
253 if (count($usr_ids) > 0) {
254 $query .= "AND usr_id IN (" . implode(',', $usr_ids) . ")";
255 }
256
257 $result = $this->db->query($query);
258
259 $ret = [];
260 while ($row = $this->db->fetchAssoc($result)) {
261 $ret[$row['usr_id']] = [
262 self::CURRENT_ITEM_ID => (int) $row[self::CURRENT_ITEM_ID],
263 self::STATES => $this->buildStates($row[self::STATES]),
264 self::FIRST_ACCESS => $row[self::FIRST_ACCESS],
265 self::LAST_ACCESS => $row[self::LAST_ACCESS]
266 ];
267 }
268
269 return $ret;
270 }
271}
$result
An exception for terminatinating execution or to throw for unit testing.
Keeps the state of a view in a simple stringly type key-value store.
Definition: State.php:10
Persistence for View-States.
serializeStates(array $states)
insert(int $lso_ref_id, int $usr_id)
select(int $lso_ref_id, array $usr_ids=[])
deleteFor(int $lso_ref_id, array $usr_ids=[])
buildStates(string $serialized)
getFirstAccessFor(int $lso_ref_id, array $usr_ids=[])
__construct(ilDBInterface $db)
update(ilDBInterface $db, int $lso_ref_id, int $usr_id, int $current_item, string $serialized)
deleteForItem(int $lso_ref_id, int $item_ref_id)
getCurrentItemsFor(int $lso_ref_id, array $usr_ids=[])
getLastAccessFor(int $lso_ref_id, array $usr_ids=[])
entryExistsFor(int $lso_ref_id, int $usr_id)
getStatesFor(int $lso_ref_id, array $usr_ids=[])
updateState(int $lso_ref_id, int $usr_id, int $ref_id, ILIAS\KioskMode\State $state, int $current_item=null)
update a single State (for the item with ref_id); if $current_item is not set, assume that $ref_id is...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Class ChatMainBarProvider \MainMenu\Provider.
$ret
Definition: parser.php:6
$query
$data
Definition: storeScorm.php:23