1<?php 2/* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */ 3 4/** 5 * LM presentation (left frame) explorer GUI class 6 * 7 * @author Alex Killing <alex.killing@gmx.de> 8 * @version $Id$ 9 * 10 * @ingroup ModulesLearningModule 11 */ 12class ilLMTOCExplorerGUI extends ilLMExplorerGUI 13{ 14 protected $lang; 15 protected $highlight_node; 16 protected $export_all_languages; 17 18 /** 19 * @var ilPageActivationDBRepository 20 */ 21 protected $activation_repo; 22 23 /** 24 * @var array 25 */ 26 protected $complete_tree; 27 28 /** 29 * @var array 30 */ 31 protected $activation_data; 32 33 /** 34 * @var ilObjLearningModule 35 */ 36 protected $lm; 37 38 /** 39 * @var ilSetting 40 */ 41 protected $lm_set; 42 43 /** 44 * @var ilLMPresentationLinker 45 */ 46 protected $linker; 47 48 protected $focus_id; 49 50 /** 51 * @var ilLMPresentationService 52 */ 53 protected $service; 54 55 /** 56 * @var ilLMTracker 57 */ 58 protected $tracker; 59 60 /** 61 * Constructor 62 * 63 * @param object|string $a_parent_obj parent gui object 64 * @param string $a_parent_cmd parent cmd 65 * @param ilLMPresentationService $service 66 * @param string $a_lang language 67 */ 68 public function __construct( 69 $a_parent_obj, 70 $a_parent_cmd, 71 ilLMPresentationService $service, 72 $a_lang = "-", 73 $a_focus_id = 0, 74 $export_all_languages = false 75 ) { 76 global $DIC; 77 78 $this->service = $service; 79 $this->user = $DIC->user(); 80 $this->lm = $service->getLearningModule(); 81 $this->linker = $service->getLinker(); 82 $this->tracker = $service->getTracker(); 83 84 $exp_id = (!$this->getOfflineMode() && $this->lm->getProgressIcons()) 85 ? "ilLMProgressTree" 86 : ""; 87 parent::__construct($a_parent_obj, $a_parent_cmd, $this->lm, $exp_id); 88 $this->lm_set = new ilSetting("lm"); 89 $this->lang = $a_lang; 90 if ($a_focus_id > 0) { 91 $this->setSecondaryHighlightedNodes(array($a_focus_id)); 92 } 93 if ($this->lm->getTOCMode() != "pages") { 94 $this->setTypeWhiteList(array("st", "du")); 95 } 96 $this->focus_id = $a_focus_id; 97 $this->export_all_languages = $export_all_languages; 98 99 $this->activation_repo = new ilPageActivationDBRepository(); 100 101 $this->initTreeData(); 102 } 103 104 /** 105 * Init tree data 106 * @param 107 * @return 108 */ 109 protected function initTreeData() 110 { 111 $nodes = $this->tree->getCompleteTree(); 112 foreach ($nodes as $node) { 113 $this->complete_tree["childs"][$node["parent"]][] = $node; 114 $this->complete_tree["parent"][$node["child"]] = $node["parent"]; 115 $this->complete_tree["nodes"][$node["child"]] = $node; 116 } 117 118 $page_ids = array_column($this->complete_tree["nodes"], "child"); 119 $this->activation_data = $this->activation_repo->get( 120 "lm", 121 $page_ids, 122 $this->lm_set->get("time_scheduled_page_activation"), 123 $this->lang 124 ); 125 $this->initVisibilityData($this->tree->readRootId()); 126 } 127 128 /** 129 * Init visibility data 130 * @param int $node_id 131 */ 132 protected function initVisibilityData($node_id) 133 { 134 $current_node = $this->complete_tree["nodes"][$node_id]; 135 136 if (is_array($this->complete_tree["childs"][$node_id])) { 137 foreach ($this->complete_tree["childs"][$node_id] as $node) { 138 $this->initVisibilityData($node["child"]); 139 } 140 } 141 142 // pages are visible if they are active or activation info should be shown 143 if ($current_node["type"] == "pg") { 144 $this->complete_tree["visibility"][$node_id] = ($this->activation_data[$node_id]["active"] || 145 $this->activation_data[$node_id]["show_info"]); 146 } elseif ($current_node["type"] == "st") { 147 148 // make chapters visible as soon as there is one visible child 149 $this->complete_tree["visibility"][$node_id] = false; 150 if (is_array($this->complete_tree["childs"][$node_id])) { 151 foreach ($this->complete_tree["childs"][$node_id] as $node) { 152 if (isset($this->complete_tree["visibility"][$node["child"]]) && 153 $this->complete_tree["visibility"][$node["child"]]) { 154 $this->complete_tree["visibility"][$node_id] = true; 155 } 156 } 157 } 158 } else { 159 $this->complete_tree["visibility"][$node_id] = true; 160 } 161 } 162 163 /** 164 * Get root node 165 */ 166 public function getRootNode() 167 { 168 $root_id = $this->getTree()->readRootId(); 169 if ($this->focus_id > 0 && $this->getTree()->isInTree($this->focus_id) && 170 ilLMObject::_lookupType($this->focus_id) == "st") { 171 // $root_id = $this->focus_id; 172 } 173 return $this->getTree()->getNodeData($root_id); 174 } 175 176 /** 177 * Set tracker 178 * 179 * @param ilLMTracker $a_val tracker object 180 */ 181 public function setTracker($a_val) 182 { 183 $this->tracker = $a_val; 184 } 185 186 /** 187 * Get tracker 188 * 189 * @return ilLMTracker tracker object 190 */ 191 public function getTracker() 192 { 193 return $this->tracker; 194 } 195 196 /** 197 * Set highlighted node 198 * 199 * @param int $a_val node id 200 */ 201 public function setHighlightNode($a_val) 202 { 203 $this->highlight_node = $a_val; 204 } 205 206 /** 207 * Get highlighted node 208 * 209 * @return int node id 210 */ 211 public function getHighlightNode() 212 { 213 return $this->highlight_node; 214 } 215 216 /** 217 * Is node highlighted? 218 * 219 * @param mixed $a_node node object/array 220 * @return boolean node visible true/false 221 */ 222 public function isNodeHighlighted($a_node) 223 { 224 if ($a_node["child"] == $this->getHighlightNode()) { 225 return true; 226 } 227 return false; 228 } 229 230 /** 231 * Get node content 232 * 233 * @param array $a_node node array 234 * @return string node content 235 */ 236 public function getNodeContent($a_node) 237 { 238 if ($a_node["child"] == $this->getNodeId($this->getRootNode())) { 239 return $this->service->getPresentationStatus()->getLMPresentationTitle(); 240 } 241 242 if ($a_node["type"] == "st") { 243 return ilStructureObject::_getPresentationTitle( 244 $a_node["child"], 245 ilLMOBject::CHAPTER_TITLE, 246 $this->lm->isActiveNumbering(), 247 false, 248 false, 249 $this->lm->getId(), 250 $this->lang, 251 true 252 ); 253 } elseif ($a_node["type"] == "pg") { 254 return ilLMPageObject::_getPresentationTitle( 255 $a_node["child"], 256 $this->lm->getPageHeader(), 257 $this->lm->isActiveNumbering(), 258 $this->lm_set->get("time_scheduled_page_activation"), 259 true, 260 $this->lm->getId(), 261 $this->lang, 262 true 263 ); 264 } elseif ($a_node["child"] == $this->getNodeId($this->getRootNode())) { 265 return $this->lm->getTitle(); 266 } 267 268 return $a_node["title"]; 269 } 270 271 272 /** 273 * Get node icon 274 * 275 * @param array $a_node node array 276 * @return string icon path 277 */ 278 public function getNodeIcon($a_node) 279 { 280 // overwrite chapter icons with lp info? 281 if (!$this->getOfflineMode() && $a_node["type"] == "st") { 282 $icon = $this->checkLPIcon($a_node["child"]); 283 if ($icon != "") { 284 return $icon; 285 } 286 } 287 288 // use progress icons (does not depend on lp mode) 289 if (!$this->getOfflineMode() && $this->lm->getProgressIcons()) { 290 return $this->tracker->getIconForLMObject($a_node, $this->highlight_node); 291 } 292 293 if ($a_node["type"] == "du") { 294 $a_node["type"] = "lm"; 295 } 296 $a_name = "icon_" . $a_node["type"] . ".svg"; 297 if ($a_node["type"] == "pg") { 298 $lm_set = new ilSetting("lm"); 299 $active = ilLMPage::_lookupActive( 300 $a_node["child"], 301 $this->lm->getType(), 302 $lm_set->get("time_scheduled_page_activation") 303 ); 304 305 // is page scheduled? 306 $img_sc = ($lm_set->get("time_scheduled_page_activation") && 307 ilLMPage::_isScheduledActivation($a_node["child"], $this->lm->getType()) && !$active 308 && !$this->getOfflineMode()) 309 ? "_sc" 310 : ""; 311 312 $a_name = "icon_pg" . $img_sc . ".svg"; 313 314 if (!$active && !$this->getOfflineMode()) { 315 $a_name = "icon_pg_d" . $img_sc . ".svg"; 316 } 317 } 318 319 return ilUtil::getImagePath($a_name, false, "output", $this->getOfflineMode()); 320 } 321 322 /** 323 * Is node clickable 324 * 325 * @param array $a_node node array 326 * @return bool clickable? 327 */ 328 public function isNodeClickable($a_node) 329 { 330 $ilUser = $this->user; 331 332 $orig_node_id = $a_node["child"]; 333 334 // if navigation is restricted based on correct answered questions 335 // check if we have preceeding pages including unsanswered/incorrect answered questions 336 if (!$this->getOfflineMode()) { 337 if ($this->lm->getRestrictForwardNavigation()) { 338 if ($this->getTracker()->hasPredIncorrectAnswers($orig_node_id)) { 339 return false; 340 } 341 } 342 } 343 344 if ($a_node["type"] == "st") { 345 if (!$this->getOfflineMode()) { 346 if ($this->lm->getTOCMode() != "pages") { 347 $a_node = $this->getTree()->fetchSuccessorNode($a_node["child"], "pg"); 348 } else { 349 // faster, but needs pages to be in explorer 350 $a_node = $this->getSuccessorNode($a_node["child"], "pg"); 351 } 352 if ($a_node["child"] == 0) { 353 return false; 354 } 355 } else { 356 // get next activated page 357 $found = false; 358 while (!$found) { 359 if ($this->lm->getTOCMode() != "pages") { 360 $a_node = $this->getTree()->fetchSuccessorNode($a_node["child"], "pg"); 361 } else { 362 $a_node = $this->getSuccessorNode($a_node["child"], "pg"); 363 } 364 $active = ilLMPage::_lookupActive( 365 $a_node["child"], 366 $this->lm->getType(), 367 $this->lm_set->get("time_scheduled_page_activation") 368 ); 369 370 if ($a_node["child"] > 0 && !$active) { 371 $found = false; 372 } else { 373 $found = true; 374 } 375 } 376 if ($a_node["child"] <= 0) { 377 return false; 378 } else { 379 $path = $this->getTree()->getPathId($a_node["child"]); 380 if (!in_array($orig_node_id, $path)) { 381 return false; 382 } 383 } 384 } 385 } 386 387 if ($a_node["type"] == "pg") { 388 // check public area mode 389 if ($ilUser->getId() == ANONYMOUS_USER_ID && !ilLMObject::_isPagePublic($a_node["child"], true)) { 390 return false; 391 } 392 } 393 394 return true; 395 } 396 397 398 /** 399 * Get node icon alt text 400 * 401 * @param array $a_node node array 402 * @return string alt text 403 */ 404 public function getNodeIconAlt($a_node) 405 { 406 } 407 408 /** 409 * Get href for node 410 * 411 * @param mixed $a_node node object/array 412 * @return string href attribute 413 */ 414 public function getNodeHref($a_node) 415 { 416 if (!$this->getOfflineMode()) { 417 return $this->linker->getLink("", $a_node["child"]); 418 //return parent::buildLinkTarget($a_node_id, $a_type); 419 } else { 420 if ($a_node["type"] != "pg") { 421 // get next activated page 422 $found = false; 423 while (!$found) { 424 $a_node = $this->getTree()->fetchSuccessorNode($a_node["child"], "pg"); 425 $active = ilLMPage::_lookupActive( 426 $a_node["child"], 427 $this->lm->getType(), 428 $this->lm_set->get("time_scheduled_page_activation") 429 ); 430 431 if ($a_node["child"] > 0 && !$active) { 432 $found = false; 433 } else { 434 $found = true; 435 } 436 } 437 } 438 439 $lang_suffix = ""; 440 if ($this->export_all_languages) { 441 if ($this->lang != "" && $this->lang != "-") { 442 $lang_suffix = "_" . $this->lang; 443 } 444 } 445 446 if ($nid = ilLMPageObject::getExportId($this->lm->getId(), $a_node["child"])) { 447 return "lm_pg_" . $nid . $lang_suffix . ".html"; 448 } 449 return "lm_pg_" . $a_node["child"] . $lang_suffix . ".html"; 450 } 451 } 452 453 /** 454 * Is node visible? 455 * 456 * @param mixed $a_node node object/array 457 * @return boolean node visible true/false 458 */ 459 public function isNodeVisible($a_node) 460 { 461 return (bool) $this->complete_tree["visibility"][$a_node["child"]]; 462 } 463} 464