1<?php 2 3declare(strict_types=1); 4 5use ILIAS\KioskMode\ControlBuilder; 6use ILIAS\KioskMode\LocatorBuilder; 7use ILIAS\KioskMode\TOCBuilder; 8use ILIAS\KioskMode\URLBuilder; 9 10use ILIAS\UI\Factory; 11 12/** 13 * Class LSControlBuilder 14 */ 15class LSControlBuilder implements ControlBuilder 16{ 17 const CMD_START_OBJECT = 'start_legacy_obj'; 18 const CMD_CHECK_CURRENT_ITEM_LP = 'ccilp'; 19 const PARAM_LP_CURRENT_ITEM_OBJID = 'ccilpobjid'; 20 21 /** 22 * @var Component|null 23 */ 24 protected $exit_control; 25 26 /** 27 * @var Component|null 28 */ 29 protected $previous_control; 30 31 /** 32 * @var Component|null 33 */ 34 protected $next_control; 35 36 /** 37 * @var Component|null 38 */ 39 protected $done_control; 40 41 /** 42 * @var Component[] 43 */ 44 protected $controls = []; 45 46 /** 47 * @var Component[] 48 */ 49 protected $toggles = []; 50 51 /** 52 * @var Component[] 53 */ 54 protected $mode_controls = []; 55 56 /** 57 * @var TOCBuilder|null 58 */ 59 protected $toc; 60 61 /** 62 * @var LocatorBuilder|null 63 */ 64 protected $loc; 65 66 /** 67 * @var Factory 68 */ 69 protected $ui_factory; 70 71 /** 72 * @var URLBuilder 73 */ 74 protected $url_builder; 75 76 /** 77 * @var Component|null 78 */ 79 protected $start; 80 81 /** 82 * @var string | null 83 */ 84 protected $additional_js; 85 86 /** 87 * @var LSGlobalSettings 88 */ 89 protected $global_settings; 90 91 public function __construct( 92 Factory $ui_factory, 93 LSURLBuilder $url_builder, 94 ilLanguage $language, 95 LSGlobalSettings $global_settings 96 ) { 97 $this->ui_factory = $ui_factory; 98 $this->url_builder = $url_builder; 99 $this->lng = $language; 100 $this->global_settings = $global_settings; 101 } 102 103 public function getExitControl() 104 { 105 return $this->exit_control; 106 } 107 108 public function getPreviousControl() 109 { 110 return $this->previous_control; 111 } 112 113 public function getNextControl() 114 { 115 return $this->next_control; 116 } 117 118 public function getDoneControl() 119 { 120 return $this->done_control; 121 } 122 123 public function getToggles() 124 { 125 return $this->toggles; 126 } 127 128 public function getModeControls() 129 { 130 return $this->mode_controls; 131 } 132 133 public function getControls() : array 134 { 135 return $this->controls; 136 } 137 138 public function getLocator() 139 { 140 return $this->loc; 141 } 142 143 public function getToc() 144 { 145 return $this->toc; 146 } 147 148 /** 149 * @inheritdoc 150 */ 151 public function exit(string $command) : ControlBuilder 152 { 153 if ($this->exit_control) { 154 throw new \LogicException("Only one exit-control per view...", 1); 155 } 156 $cmd = $this->url_builder->getHref($command); 157 158 $label = 'lso_player_suspend'; 159 if ($command === ilLSPlayer::LSO_CMD_FINISH) { 160 $label = 'lso_player_finish'; 161 } 162 163 $exit_button = $this->ui_factory->button()->shy( 164 $this->lng->txt($label), 165 $cmd 166 ); 167 168 $this->exit_control = $exit_button; 169 return $this; 170 } 171 172 /** 173 * @inheritdoc 174 */ 175 public function next(string $command, int $parameter = null) : ControlBuilder 176 { 177 if ($this->next_control) { 178 throw new \LogicException("Only one next-control per view...", 1); 179 } 180 $label = $this->lng->txt('lso_player_next'); 181 $cmd = $this->url_builder->getHref($command, $parameter); 182 $btn = $this->ui_factory->button()->standard($label, $cmd); 183 if ($command === '') { 184 $btn = $btn->withUnavailableAction(); 185 } 186 $this->next_control = $btn; 187 return $this; 188 } 189 190 /** 191 * @inheritdoc 192 */ 193 public function previous(string $command, int $parameter = null) : ControlBuilder 194 { 195 if ($this->previous_control) { 196 throw new \LogicException("Only one previous-control per view...", 1); 197 } 198 $label = $this->lng->txt('lso_player_previous'); 199 $cmd = $this->url_builder->getHref($command, $parameter); 200 $btn = $this->ui_factory->button()->standard($label, $cmd); 201 if ($command === '') { 202 $btn = $btn->withUnavailableAction(); 203 } 204 $this->previous_control = $btn; 205 return $this; 206 } 207 208 /** 209 * @inheritdoc 210 */ 211 public function done(string $command, int $parameter = null) : ControlBuilder 212 { 213 if ($this->done_control) { 214 throw new \LogicException("Only one done-control per view...", 1); 215 } 216 $label = $this->lng->txt('lso_player_done'); 217 $cmd = $this->url_builder->getHref($command, $parameter); 218 $btn = $this->ui_factory->button()->primary($label, $cmd); 219 $this->done_control = $btn; 220 return $this; 221 } 222 223 /** 224 * @inheritdoc 225 */ 226 public function generic(string $label, string $command, int $parameter = null) : ControlBuilder 227 { 228 $cmd = $this->url_builder->getHref($command, $parameter); 229 $this->controls[] = $this->ui_factory->button()->standard($label, $cmd); 230 return $this; 231 } 232 233 /** 234 * A toggle can be used to switch some behaviour in the view on or of. 235 */ 236 public function toggle(string $label, string $on_command, string $off_command) : ControlBuilder 237 { 238 throw new \Exception("NYI: Toggles", 1); 239 240 $cmd_on = $this->url_builder->getHref($on_command, 0); 241 $cmd_off = $this->url_builder->getHref($off_command, 0); 242 //build toggle and add to $this->toggles 243 //return $this; 244 } 245 246 /** 247 * @inheritdoc 248 */ 249 public function mode(string $command, array $labels) : ControlBuilder 250 { 251 $actions = []; 252 foreach ($labels as $parameter => $label) { 253 $actions[$label] = $this->url_builder->getHref($command, $parameter); 254 } 255 $this->mode_controls[] = $this->ui_factory->viewControl()->mode($actions, ''); 256 return $this; 257 } 258 259 /** 260 * @inheritdoc 261 */ 262 public function locator(string $command) : LocatorBuilder 263 { 264 if ($this->loc) { 265 throw new \LogicException("Only one locator per view...", 1); 266 } 267 $this->loc = new LSLocatorBuilder($command, $this); 268 return $this->loc; 269 } 270 271 /** 272 * @inheritdoc 273 */ 274 public function tableOfContent( 275 string $label, 276 string $command, 277 int $parameter = null, 278 $state = null 279 ) : TOCBuilder { 280 if ($this->toc) { 281 throw new \LogicException("Only one ToC per view...", 1); 282 } 283 $this->toc = new LSTOCBuilder($this, $command, $label, $parameter, $state); 284 return $this->toc; 285 } 286 287 /** 288 * Add a "start"-button as primary. 289 * This is NOT regular behavior, but a special feature for the LegacyView 290 * of LearningSequence's sub-objects that do not implement a KioskModeView. 291 * 292 * The start-control is exclusively used to open an ILIAS-Object in a new windwow/tab. 293 */ 294 public function start(string $label, string $url, int $parameter = null) : ControlBuilder 295 { 296 if ($this->start) { 297 throw new \LogicException("Only one start-control per view...", 1); 298 } 299 300 $this_cmd = $this->url_builder->getHref(self::CMD_START_OBJECT, 0); 301 $lp_cmd = str_replace( 302 '&cmd=view&', 303 '&cmd=' . self::CMD_CHECK_CURRENT_ITEM_LP . '&', 304 $this_cmd 305 ); 306 307 $current_obj_id = $parameter; 308 $lp_cmd .= '&' . self::PARAM_LP_CURRENT_ITEM_OBJID . '=' . $current_obj_id; 309 310 $signal = $this->getStartSignal(); 311 $this->setListenerJS($signal->getId(), $url, $lp_cmd, $this_cmd); 312 313 $this->start = $this->ui_factory->button() 314 ->primary($label, '') 315 ->withOnClick($signal); 316 317 return $this; 318 } 319 320 public function getStartControl() 321 { 322 return $this->start; 323 } 324 325 /** 326 * This is a hack and not supposed to be considered as a common way to inject 327 * JS-Code and bind it to a button. 328 * However, for the time beeing and the lack of a general alternative, 329 * I think it's OK to do this for legacy(!)-objects here... 330 */ 331 protected function getStartSignal() : ILIAS\UI\Component\Signal 332 { 333 $id = uniqid(); 334 $signal = new ILIAS\UI\Implementation\Component\Signal($id); 335 return $signal; 336 } 337 338 339 public function getAdditionalJS() : string 340 { 341 return $this->additional_js; 342 } 343 344 protected function setListenerJS( 345 string $signal_id, 346 string $new_win_url, 347 string $check_lp_url, 348 string $on_lp_change_url 349 ) { 350 $interval = $this->global_settings->getPollingIntervalMilliseconds(); 351 $this->additional_js = 352<<<JS 353function lso_checkLPOfObject() { 354 $.ajax({ 355 url: "$check_lp_url", 356 }).done(function(data) { 357 if(window._lso_current_item_lp === -1) { 358 window._lso_current_item_lp = data; 359 } 360 if (window._lso_current_item_lp !== data) { 361 location.replace('$on_lp_change_url'); 362 } 363 }); 364} 365 366$(document).on('{$signal_id}', function() { 367 var il_ls_win = window.open('$new_win_url'); 368}); 369window._lso_current_item_lp = -1; 370lso_checkLPOfObject(); 371window.setInterval(lso_checkLPOfObject, $interval); 372JS; 373 } 374} 375