ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.ilLSPlayer.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
28
33{
34 public const PARAM_LSO_COMMAND = 'lsocmd';
35 public const PARAM_LSO_PARAMETER = 'lsov';
36
37 public const LSO_CMD_NEXT = 'lsonext'; //with param directions
38 public const LSO_CMD_GOTO = 'lsogoto'; //with param ref_id
39 public const LSO_CMD_SUSPEND = 'lsosuspend';
40 public const LSO_CMD_FINISH = 'lsofinish';
41
42 public const GS_DATA_LS_KIOSK_MODE = 'ls_kiosk_mode';
43 public const GS_DATA_LS_CONTENT = 'ls_content';
44 public const GS_DATA_LS_MAINBARCONTROLS = 'ls_mainbar_controls';
45 public const GS_DATA_LS_METABARCONTROLS = 'ls_metabar_controls';
46
47 public function __construct(
48 protected ilLSLearnerItemsQueries $ls_items,
49 protected LSControlBuilder $control_builder,
50 protected LSUrlBuilder $url_builder,
51 protected ilLSCurriculumBuilder $curriculum_builder,
52 protected ilLSViewFactory $view_factory,
53 protected ilKioskPageRenderer $page_renderer,
54 protected Factory $ui_factory,
55 protected ScreenContext $current_context,
56 protected Refinery\Factory $refinery
57 ) {
58 }
59
60 public function play(RequestWrapper $get): ?string
61 {
62 $items = $this->ls_items->getItems();
63
64 if (count($items) === 0) {
65 return null;
66 }
67
68 $current_item = $this->getNextAvailableItem($items, $this->getCurrentItem($items));
69 if ($current_item === null) {
70 return null;
71 }
72
73 $view = $this->view_factory->getViewFor($current_item);
74 $state = $this->ls_items->getStateFor($current_item, $view);
75 $state = $this->updateViewState($state, $view, $get);
76 //reload items after update viewState
77 $items = $this->ls_items->getItems();
78
79 $current_item_ref_id = $current_item->getRefId();
80 //now, digest parameter:
81 $command = null;
82 if ($get->has(self::PARAM_LSO_COMMAND)) {
83 $command = $get->retrieve(self::PARAM_LSO_COMMAND, $this->refinery->kindlyTo()->string());
84 }
85 $param = null;
86 if ($get->has(self::PARAM_LSO_PARAMETER)) {
87 $param = $get->retrieve(self::PARAM_LSO_PARAMETER, $this->refinery->kindlyTo()->int());
88 }
89
90 switch ($command) {
93 $this->ls_items->storeState($state, $current_item_ref_id, $current_item_ref_id);
94 return 'EXIT::' . $command;
96 $next_item = $this->getNextItem($items, $current_item, $param);
97 if ($next_item->getAvailability() !== Step::AVAILABLE) {
98 $next_item = $current_item;
99 }
100 break;
102 list(, $next_item) = $this->findItemByRefId($items, $param);
103 break;
104 default: //view-internal / unknown command
105 $next_item = $current_item;
106 }
107 //write State to DB
108 $this->ls_items->storeState($state, $current_item_ref_id, $next_item->getRefId());
109
110 //get proper view
111 if ($next_item != $current_item) {
112 $view = $this->view_factory->getViewFor($next_item);
113 $state = $this->ls_items->getStateFor($next_item, $view);
114 }
115
116 //content
117 $obj_title = $next_item->getTitle();
118 $icon = $this->ui_factory->symbol()->icon()->standard(
119 $next_item->getType(),
120 $next_item->getType(),
121 'medium'
122 );
123
124 $content = $this->renderComponentView($state, $view);
125
126 $panel = $this->ui_factory->panel()->standard(
127 '',
128 $content
129 );
130 $content = [$panel];
131
132 $items = $this->ls_items->getItems(); //reload items after renderComponentView content
133
134 //get position
135 list($item_position, $item) = $this->findItemByRefId($items, $next_item->getRefId());
136
137 //have the view build controls
138 $control_builder = $this->control_builder;
139 $view->buildControls($state, $control_builder);
140
141 //amend controls not set by the view
142 $control_builder = $this->buildDefaultControls($control_builder, $item, $item_position, $items);
143
144 $rendered_body = $this->page_renderer->render(
145 $control_builder,
146 $obj_title,
147 $icon,
148 $content
149 );
150
151 $metabar_controls = [
152 'exit' => $control_builder->getExitControl()
153 ];
154
155 $curriculum_slate = $this->page_renderer->buildCurriculumSlate(
156 $this->curriculum_builder
157 ->getLearnerCurriculum(true)
158 ->withActive($item_position)
159 );
160 $mainbar_controls = [
161 'curriculum' => $curriculum_slate
162 ];
163
164 $toc = $control_builder->getToc();
165 if ($toc) {
166 $toc_slate = $this->page_renderer->buildToCSlate($toc, $icon);
167 $mainbar_controls['toc'] = $toc_slate;
168 }
169
170 $cc = $this->current_context;
171 $cc->addAdditionalData(self::GS_DATA_LS_KIOSK_MODE, true);
172 $cc->addAdditionalData(self::GS_DATA_LS_METABARCONTROLS, $metabar_controls);
173 $cc->addAdditionalData(self::GS_DATA_LS_MAINBARCONTROLS, $mainbar_controls);
174 $cc->addAdditionalData(self::GS_DATA_LS_CONTENT, $rendered_body);
175
176 return null;
177 }
178
182 protected function getCurrentItem(array $items): LSLearnerItem
183 {
184 $current_item = $items[0];
185 $current_item_ref_id = $this->ls_items->getCurrentItemRefId();
186 if ($current_item_ref_id !== 0) {
187 $valid_ref_ids = array_map(
188 fn($item) => $item->getRefId(),
189 array_values($this->ls_items->getItems())
190 );
191 if (in_array($current_item_ref_id, $valid_ref_ids)) {
192 list(, $current_item) = $this->findItemByRefId($items, $current_item_ref_id);
193 }
194 }
195 return $current_item;
196 }
197
198 protected function getNextAvailableItem(
199 array $items,
200 LSLearnerItem $current_item
201 ): ?LSLearnerItem {
202 if ($current_item->getAvailability() === Step::AVAILABLE) {
203 return $current_item;
204 }
205
206 $new_next_item = null;
207 $idx = array_search($current_item, $items);
208
209 for ($i = $idx - 1; $i >= 0; $i--) {
210 if ($items[$i]->getAvailability() === Step::AVAILABLE) {
211 $new_next_item = $items[$i];
212 continue;
213 }
214 }
215 if ($new_next_item === null) {
216 for ($i = $idx + 1; $i < count($items); $i++) {
217 if ($items[$i]->getAvailability() === Step::AVAILABLE) {
218 $new_next_item = $items[$i];
219 continue;
220 }
221 }
222 }
223 return $new_next_item;
224 }
225
226 protected function updateViewState(
227 ILIAS\KioskMode\State $state,
228 ILIAS\KioskMode\View $view,
229 RequestWrapper $get
230 ): ILIAS\KioskMode\State {
231 if ($get->has(self::PARAM_LSO_COMMAND) && $get->has(self::PARAM_LSO_PARAMETER)) {
232 $command = $get->retrieve(self::PARAM_LSO_COMMAND, $this->refinery->kindlyTo()->string());
233 $param = $get->retrieve(self::PARAM_LSO_PARAMETER, $this->refinery->kindlyTo()->int());
234 $state = $view->updateGet($state, $command, $param);
235 }
236 return $state;
237 }
238
242 protected function getNextItem(array $items, LSLearnerItem $current_item, int $direction): LSLearnerItem
243 {
244 list($position) = $this->findItemByRefId($items, $current_item->getRefId());
245 $next = $position + $direction;
246 if ($next >= 0 && $next < count($items)) {
247 return $items[$next];
248 }
249 return $current_item;
250 }
251
255 protected function findItemByRefId(array $items, int $ref_id): array
256 {
257 foreach ($items as $index => $item) {
258 if ($item->getRefId() === $ref_id) {
259 return [$index, $item];
260 }
261 }
262 throw new \Exception("This is not a valid item.", 1);
263 }
264
265 protected function buildDefaultControls(
266 LSControlBuilder $control_builder,
267 LSLearnerItem $item,
268 int $item_position,
269 array $items
270 ): ControlBuilder {
271 $is_first = $item_position === 0;
272 $is_last = $item_position === count($items) - 1;
273
274 if (!$control_builder->getExitControl()) {
275 $cmd = self::LSO_CMD_SUSPEND;
276 if ($is_last) {
277 $cmd = self::LSO_CMD_FINISH;
278 }
279 $control_builder = $control_builder->exit($cmd);
280 }
281
282 if (!$control_builder->getPreviousControl()) {
283 $direction_prev = -1;
284 $cmd = ''; //disables control
285
286 if (!$is_first) {
287 $available = $this->getNextItem($items, $item, $direction_prev)
288 ->getAvailability() === Step::AVAILABLE;
289
290 if ($available) {
291 $cmd = self::LSO_CMD_NEXT;
292 }
293 }
294
295 $control_builder = $control_builder
296 ->previous($cmd, $direction_prev);
297 }
298
299 if (!$control_builder->getNextControl()) {
300 $direction_next = 1;
301 $cmd = '';
302 if (!$is_last) {
303 $available = $this->getNextItem($items, $item, $direction_next)
304 ->getAvailability() === Step::AVAILABLE;
305
306 if ($available) {
307 $cmd = self::LSO_CMD_NEXT;
308 }
309 }
310
311 $control_builder = $control_builder
312 ->next($cmd, $direction_next);
313 }
314
315 return $control_builder;
316 }
317
318 protected function renderComponentView($state, ILIAS\KioskMode\View $view): Component
319 {
320 return $view->render(
321 $state,
322 $this->ui_factory,
323 $this->url_builder,
324 []
325 );
326 }
327
329 {
330 $item = $this->getCurrentItem($this->ls_items->getItems());
331 return $item->getLearningProgressStatus();
332 }
333}
Builds a Color from either hex- or rgb values.
Definition: Factory.php:31
Builds data types.
Definition: Factory.php:36
previous(string $command, ?int $parameter=null)
A previous control allows the user to go back to the previous item in the object.
exit(string $command)
An exit control allows the user to gracefully leave the object providing the kiosk mode.
next(string $command, ?int $parameter=null)
A next control allows the user to progress to the next item in the object.
getRefId()
Definition: LSItem.php:93
Add learning progress and availability information to the LSItem.
Builds the overview (curriculum) of a LearningSequence.
This combines calls to ProgressDB and StateDB to handle learner-items in the context of a specific LS...
Implementation of KioskMode Player.
findItemByRefId(array $items, int $ref_id)
const PARAM_LSO_COMMAND
renderComponentView($state, ILIAS\KioskMode\View $view)
__construct(protected ilLSLearnerItemsQueries $ls_items, protected LSControlBuilder $control_builder, protected LSUrlBuilder $url_builder, protected ilLSCurriculumBuilder $curriculum_builder, protected ilLSViewFactory $view_factory, protected ilKioskPageRenderer $page_renderer, protected Factory $ui_factory, protected ScreenContext $current_context, protected Refinery\Factory $refinery)
const LSO_CMD_SUSPEND
play(RequestWrapper $get)
const GS_DATA_LS_KIOSK_MODE
getNextItem(array $items, LSLearnerItem $current_item, int $direction)
$direction is either -1 or 1;
const GS_DATA_LS_MAINBARCONTROLS
const LSO_CMD_FINISH
getCurrentItemLearningProgress()
const PARAM_LSO_PARAMETER
updateViewState(ILIAS\KioskMode\State $state, ILIAS\KioskMode\View $view, RequestWrapper $get)
buildDefaultControls(LSControlBuilder $control_builder, LSLearnerItem $item, int $item_position, array $items)
getCurrentItem(array $items)
const GS_DATA_LS_METABARCONTROLS
getNextAvailableItem(array $items, LSLearnerItem $current_item)
const GS_DATA_LS_CONTENT
Interface RequestWrapper.
retrieve(string $key, Transformation $transformation)
Build controls for the view.
A component is the most general form of an entity in the UI.
Definition: Component.php:28
This describes a Workflow Step.
Definition: Step.php:30
$ref_id
Definition: ltiauth.php:66
has(string $class_name)
Interface Observer \BackgroundTasks Contains several chained tasks and infos about them.
if(!file_exists('../ilias.ini.php'))
$param
Definition: xapitoken.php:46