public function toSelect($returnClassedHTML = false, $includeSkillGaps = false, $showQuestions = false, $iterator = false, $lessons = false, $courses = false)
 {
     if (!$iterator) {
         $iterator = new EfrontNodeFilterIterator(new RecursiveIteratorIterator(new RecursiveArrayIterator($this->tree), RecursiveIteratorIterator::SELF_FIRST));
     }
     if ($lessons === false) {
         //If a lessons list is not specified, get all active lessons
         if ($showQuestions) {
             $result = eF_getTableData("lessons l JOIN questions q ON q.lessons_ID = l.id", "l.id, l.name, count(q.id) as questions", "q.type <> 'raw_text' AND l.archive = 0 AND l.active=1", "", "l.name");
         } else {
             $result = eF_getTableData("lessons", "*", "archive = 0 && active=1");
             //Get all lessons at once, thus avoiding looping queries
         }
         foreach ($result as $value) {
             $value['name'] = str_replace("'", "&#039;", $value['name']);
             $lessons[$value['id']] = new EfrontLesson($value);
             //Create an array of EfrontLesson objects
         }
     }
     $directionsQuestions = array();
     $directionsLessons = array();
     foreach ($lessons as $id => $lesson) {
         if (!$lesson->lesson['active']) {
             //Remove inactive lessons
             unset($lessons[$id]);
         } elseif (!$lesson->lesson['course_only']) {
             //Lessons in courses will be handled by the course's display method, so remove them from the list
             $directions_ID = $lesson->lesson['directions_ID'];
             $directionsLessons[$directions_ID][] = $id;
             //Create an intermediate array that maps lessons to directions
             if ($showQuestions) {
                 if (isset($directionsQuestions[$directions_ID])) {
                     $directionsQuestions[$directions_ID] += $lesson->lesson['questions'];
                 } else {
                     $directionsQuestions[$directions_ID] = $lesson->lesson['questions'];
                 }
             }
         }
     }
     if ($courses === false) {
         //If a courses list is not specified, get all active courses
         if ($showQuestions) {
             $resultQuestions = eF_getTableData("courses c JOIN lessons_to_courses lc ON lc.courses_ID = c.id JOIN questions q ON q.lessons_ID = lc.lessons_ID", "c.id, count(q.id) as questions", "q.type <> 'raw_text' AND c.archive = 0 AND c.active=1", "", "c.name");
             $coursesQuestions = array();
             foreach ($resultQuestions as $resultQs) {
                 $coursesQuestions[$resultQs['id']] = $resultQs['questions'];
             }
         }
         $result = eF_getTableData("courses", "*", "archive = 0 AND active=1");
         //Get all courses at once, thus avoiding looping queries
         foreach ($result as $value) {
             $value['name'] = str_replace("'", "&#039;", $value['name']);
             $value['questions'] = $coursesQuestions[$value['id']] != "" ? $coursesQuestions[$value['id']] : 0;
             // 0 + to cast empty values to 0
             $courses[$value['id']] = new EfrontCourse($value);
             //Create an array of EfrontCourse objects
         }
     }
     $directionsCourses = array();
     foreach ($courses as $id => $course) {
         if (!$course->course['active']) {
             //Remove inactive courses
             unset($courses[$id]);
         } else {
             $directions_ID = $course->course['directions_ID'];
             $directionsCourses[$directions_ID][] = $id;
             //Create an intermediate array that maps courses to directions
             if ($showQuestions) {
                 if (isset($directionsQuestions[$directions_ID])) {
                     $directionsQuestions[$directions_ID] += $course->course['questions'];
                 } else {
                     $directionsQuestions[$directions_ID] = $course->course['questions'];
                 }
             }
         }
     }
     //We need to calculate which directions will be displayed. We will keep only directions that have lessons or courses and their parents. In order to do so, we traverse the directions tree and set the 'hasNodes' attribute to the nodes that will be kept
     foreach ($iterator as $key => $value) {
         if (isset($directionsLessons[$value['id']]) || isset($directionsCourses[$value['id']])) {
             $count = $iterator->getDepth();
             $value['hasNodes'] = true;
             isset($directionsLessons[$value['id']]) ? $value['lessons'] = $directionsLessons[$value['id']] : null;
             //Assign lessons ids to the direction
             isset($directionsCourses[$value['id']]) ? $value['courses'] = $directionsCourses[$value['id']] : null;
             //Assign courses ids to the direction
             while ($count) {
                 $node = $iterator->getSubIterator($count--);
                 $node['hasNodes'] = true;
                 //Mark "keep" all the parents of the node
             }
         }
     }
     $iterator = new EfrontNodeFilterIterator($iterator, array('hasNodes' => true));
     //Filter in only tree nodes that have the 'hasNodes' attribute
     $iterator->rewind();
     $current = $iterator->current();
     // pr($current);
     $current_level_father = 0;
     $treeArray = array();
     if ($includeSkillGaps) {
         $treeArray['lesson_0'] = _SKILLGAPTESTS;
     }
     $offset = "";
     while ($iterator->valid()) {
         $children = array();
         //The $children array is used so that when collapsing a direction, all its children disappear as well
         foreach (new EfrontNodeFilterIterator(new ArrayIterator($this->getNodeChildren($current), RecursiveIteratorIterator::SELF_FIRST)) as $key => $value) {
             $children[] = $key;
         }
         if ($offset != "") {
             $treeArray['direction_' . $current['id']] = str_replace("'", "&#039;", $offset . " " . $current['name']);
         } else {
             $treeArray['direction_' . $current['id']] = str_replace("'", "&#039;", $current['name']);
         }
         if (sizeof($current['lessons']) > 0) {
             foreach ($current->offsetGet('lessons') as $lessonId) {
                 $treeArray['lesson_' . $current['id'] . '_' . $lessonId] = str_replace("'", "&#039;", $offset . "- " . $lessons[$lessonId]->lesson['name']);
             }
         }
         if (sizeof($current['courses']) > 0) {
             foreach ($current->offsetGet('courses') as $courseId) {
                 $coursesArray = $courses[$courseId]->toSelect();
                 $first = 1;
                 foreach ($coursesArray as $courseId => $courseName) {
                     // The first result is the name of the course - the rest lesson names
                     // We need this distinction to have different keys (starting with course_ or lesson_ correctly
                     if ($first) {
                         $treeArray['course_' . $current['id'] . '_' . $courseId . "_" . $courseId] = str_replace("'", "&#039;", $offset . "-" . $courseName);
                         $first = 0;
                     } else {
                         $treeArray['lesson_' . $current['id'] . '_' . $courseId . "_" . $courseId] = str_replace("'", "&#039;", $offset . "-" . $courseName);
                     }
                 }
             }
         }
         $iterator->next();
         $current = $iterator->current();
         // $current
         if ($current['parent_direction_ID'] != $current_level_father) {
             $offset .= "-";
             $current_level_father = $current['parent_direction_ID'];
         }
     }
     if ($returnClassedHTML) {
         $htmlString = '<select id= "educational_criteria_row" name ="educational_criteria_row" onchange="createQuestionsSelect(this)" mySelectedIndex = "0">';
         if ($showQuestions) {
             $result = eF_getTableData("questions", "lessons_ID, count(lessons_ID) as quests", "type <> 'raw_text'", "", "lessons_ID");
             $lessonQuestions = array();
             foreach ($result as $lesson) {
                 if ($lesson['quests'] > 0) {
                     $lessonQuestions[$lesson['lessons_ID']] = $lesson['quests'];
                 }
             }
         }
         foreach ($treeArray as $key => $value) {
             $extras = " ";
             $htmlString .= '<option';
             if (strpos($key, "direction_") === 0) {
                 $directions_ID = strrchr($key, "_");
                 $htmlString .= ' value = "direction' . $directions_ID . '" style="background-color:maroon; color:white"';
                 $course_ID = substr($directions_ID, 1);
                 if ($showQuestions) {
                     $questions = $directionsQuestions[$directions_ID];
                     if ($questions) {
                         $extras = ' (' . $questions . ')';
                     } else {
                         $extras = ' (0)';
                     }
                 }
             } else {
                 if (strpos($key, "course_") === 0) {
                     $course_ID = strrchr($key, "_");
                     $htmlString .= ' value = "course' . $course_ID . '" style="background-color:green; color:white"';
                     $course_ID = substr($course_ID, 1);
                     if ($showQuestions) {
                         $questions = $courses[$course_ID]->course['questions'];
                         if ($questions) {
                             $extras = ' (' . $questions . ')';
                         } else {
                             $extras = ' (0)';
                         }
                     }
                 } else {
                     $htmlString .= ' value = "lesson' . strrchr($key, "_") . '" ';
                     if ($showQuestions) {
                         $lessonId = substr(strrchr($key, "_"), 1);
                         if ($showQuestions) {
                             if ($lessonQuestions[$lessonId]) {
                                 $extras .= "(" . $lessonQuestions[$lessonId] . ")";
                             } else {
                                 $extras .= "(0)";
                             }
                         }
                     }
                 }
             }
             $htmlString .= ">" . $value . $extras . "</option>";
         }
         $htmlString .= "</select>";
         // If no lessons or anything is found, then an empty select or array should be returned
         return $htmlString;
     }
     return $treeArray;
 }
 /**
  * Create HTML representation of the content tree
  *
  * This function is used to create an HTML representation of the content tree
  * The representation is based on javascript library drag_drop_folder_tree.js
  * If an iterator is not specified, then the tree displayed corrresponds to the default
  * tree (excluding inactive units). Otherwise, the specified iterator is used.
  * $treeId should be specified in case there will be more than one trees on the same page.
  * $options specifies the appearance and behaviour of the tree. Possible options are:
  * <br/>- edit   (true/false)
  * <br/>- delete (true/false)
  * <br/>- activate (true/false)
  * <br/>- drag (true/false)
  * <br/>- noclick (true/false)
  * <br/>- selectedNode (node id)
  * <br/>- truncateNames (maximum length)
  * <br/>- expand (true/false)
  * <br/>- tree_root (true/false) (whether to display a root node)
  * <br/>- show_hide (true/false) (whether to display the show/hide header)
  * <br/>- onclick (function)
  * <br/>- custom (any custom code to be put next to each unit name)
  * <br/>Example:
  * <code>
  * echo $content -> toHTML();                               //Display tree with all defaults
  * $iterator = new EfrontNodeFilterIterator(new RecursiveIteratorIterator(new RecursiveArrayIterator($content -> tree), RecursiveIteratorIterator :: SELF_FIRST), array('ctg_type' => 'theory'));
  * echo $content -> toHTML($iterator);                      //Display tree with only theory nodes
  * echo $content -> toHTML($iterator, 'theory_tree')        //Display tree with only theory nodes, having id 'theory_tree'
  * echo $content -> toHTML($iterator, 'theory_tree', array('edit' => 1, 'delete' => 1))     //Display tree with only theory nodes, having id 'theory_tree', and which is editable and deleteable
  * </code>
  *
  * @param RecursiveIteratorIterator $iterator The content tree iterator
  * @param string $treeId The HTML id that will be assigned to the tree. It MUST start with 'dhtml_'
  * @param array $options Behaviour options for the tree
  * @param array $scormState An array that lists special parameters for depicting SCO state (applicable to scorm 2004 content only)
  * @return string The HTML code
  * @since 3.5.0
  * @access public
  */
 public function toHTML($iterator = false, $treeId = false, $options = array(), $scormState = array())
 {
     !isset($options['hideFeedback']) ? $options['hideFeedback'] = false : null;
     !isset($options['onclick']) ? $options['onclick'] = false : null;
     !isset($options['custom']) ? $options['custom'] = false : null;
     !isset($options['tree_root']) ? $options['tree_root'] = false : null;
     isset($options['selectedNode']) or $options['selectedNode'] = '';
     //Decide whether the tree is draggable
     isset($options['drag']) && $options['drag'] ? $nodrag = 'false' : ($nodrag = 'true');
     //Should the tree expand
     isset($options['expand']) && $options['expand'] ? $expand = $options['expand'] : null;
     //Show the expand all/collapse all link
     !isset($options['show_hide']) || $options['show_hide'] ? $showHide = true : ($showHide = false);
     if (!$iterator) {
         $iterator = new EfrontNodeFilterIterator(new RecursiveIteratorIterator(new RecursiveArrayIterator($this->tree), RecursiveIteratorIterator::SELF_FIRST), array('active' => 1));
         //Default iterator excludes non-active units
     }
     if (!$treeId) {
         $treeId = 'dhtml_tree';
     }
     $iterator->rewind();
     $current = $iterator->current();
     $depth = $iterator->getDepth();
     $initDepth = $depth;
     $treeString = '';
     $count = 0;
     //Counts the total number of nodes, used to signify whether the tree has content
     if (!$current && !$options['tree_root']) {
         //Completely empty tree
         $treeString .= '<span class = "emptyCategory">' . _NOCONTENTFOUND . "</span>";
     }
     while ($iterator->valid()) {
         $iterator->next();
         //$current['ctg_type'] == 'tests' ? $contentType = 'tests' : $contentType = 'content';
         if ($current['ctg_type'] == "tests" || $current['ctg_type'] == "feedback") {
             $contentType = $current['ctg_type'];
         } else {
             $contentType = 'content';
         }
         $scorm2004 = in_array($current['scorm_version'], EfrontContentTree::$scorm2004Versions);
         $linkClass = array();
         $liClass = array();
         $tooltip = array();
         $fullName = htmlspecialchars($current['name']);
         //Full name will be needed for the link title, which is never truncated
         //Decide whether the unit name will be truncated
         $unitName = htmlspecialchars($current['name']);
         if (isset($options['truncateNames']) && mb_strlen($current['name']) > $options['truncateNames']) {
             $unitName = mb_substr(htmlspecialchars($current['name']), 0, $options['truncateNames']) . '...';
         }
         //Create the activate/deactivate link
         //isset($options['activate'])      && $options['activate']                                                                             ? $activateLink    = '<a href = "'.basename($_SERVER['PHP_SELF']).'?ctg='.$contentType.'&op=unit_order&activate_unit='.$current['id'].'"><img style = "vertical-align:middle" src = "images/16x16/trafficlight_green.png" title = "'._ACTIVATE.'" alt = "'._ACTIVATE.'" border = "0" /></a>'  : $activateLink = '';
         $activateLink = '';
         if (isset($options['activate']) && $options['activate']) {
             if ($current['active']) {
                 $image = 'trafficlight_green.png';
                 $title = _DEACTIVATE;
             } else {
                 $image = 'trafficlight_red.png';
                 $title = _ACTIVATE;
             }
             $activateLink = '<a href = "javascript:void(0)" onclick = "JSTreeObj.activateUnit(null, $(\'node' . $current['id'] . '\').down().next().next())"><img class = "handle" src = "images/16x16/' . $image . '" title = "' . $title . '" alt = "' . $title . '" /></a>';
         }
         //Create the edit link
         $editLink = '';
         if (isset($options['edit']) && $options['edit'] && !$current['linked_to']) {
             $editLink = '<a href = "' . basename($_SERVER['PHP_SELF']) . '?ctg=' . $contentType . '&edit=' . $current['id'] . '"><img class = "handle" src = "images/16x16/edit.png" title = "' . _EDIT . '" alt = "' . _EDIT . '" /></a>';
         }
         //Create the delete link
         $deleteLink = '';
         if (isset($options['delete']) && $options['delete']) {
             $deleteLink = '<a href = "javascript:void(0)" onclick = "JSTreeObj.deleteUnit(null, $(\'node' . $current['id'] . '\').down().next().next())"><img src = "images/16x16/error_delete.png" title = "' . _DELETE . '" alt = "' . _DELETE . '" class = "handle"/></a>';
         }
         //Create the target link
         $targetLink = basename($_SERVER['PHP_SELF']) . '?view_unit=' . $current['id'];
         //Set the selected node
         if (isset($options['selectedNode']) && $options['selectedNode'] == $current['id']) {
             $linkClass[] = 'drag_tree_current';
         }
         //Set the display style according to whether the unit has data
         if ($current['data'] == '' && $current['ctg_type'] == 'scorm' && $scorm2004) {
             $linkClass[] = 'treeHeader';
         } else {
             if ($current['data'] == '' && $current['ctg_type'] != 'tests' && $current['ctg_type'] != 'feedback') {
                 $linkClass[] = 'treeNoContent';
                 $fullName .= ' (' . _EMPTYUNIT . ')';
                 $targetLink = 'javascript:void(0)';
             }
         }
         //Set the display style according to whether the unit is inactive
         if ($current['active'] == 0) {
             $linkClass[] = 'inactiveLink';
         }
         if ($current['ctg_type'] == "feedback" && $options['hideFeedback'] == true) {
             $linkClass[] = 'inactiveLink';
             $targetLink = 'javascript:void(0)';
         }
         $showTools = true;
         if (G_VERSIONTYPE != 'community') {
             #cpp#ifndef COMMUNITY
             if (G_VERSIONTYPE != 'standard') {
                 #cpp#ifndef STANDARD
                 //SCORM 2004: Handles SCORM requirements on navigation
                 $startLink = '';
                 $display = '';
                 if ($scorm2004) {
                     if ($_SESSION['package_ID'] == $current['package_ID']) {
                         $targetLink = basename($_SERVER['PHP_SELF']) . '?ctg=content&navigation=choice&target=' . $current['id'] . '&package_ID=' . $current['package_ID'];
                         $options['onclick'] = false;
                         if ($scormState['choice'][$current['id']] == 'disabled') {
                             $linkClass[] = 'inactiveLink';
                             $options['onclick'] = "return false";
                         } else {
                             if ($scormState['choice'][$current['id']] == 'hidden') {
                                 $display = 'display:none';
                             }
                         }
                         if ($current['package_ID'] != $current['id']) {
                             $showTools = false;
                             //We don't want edit/delete tools for package children
                         }
                     } else {
                         if ($current['package_ID'] == $current['id']) {
                             $targetLink = basename($_SERVER['PHP_SELF']) . '?ctg=content&package_ID=' . $current['package_ID'];
                         } else {
                             $display = 'display:none';
                         }
                     }
                 }
             }
             #cpp#endif
         }
         #cpp#endif
         if (isset($options['noclick']) && $options['noclick']) {
             $targetLink = 'javascript:void(0)';
         }
         if (!$options['onclick'] && $targetLink == 'javascript:void(0)') {
             $linkClass[] = 'treeUnclickable';
         }
         //Set the class name, based on the unit status
         if ($current['ctg_type'] == 'scorm') {
             $ctgType = 'theory';
         } else {
             if ($current['ctg_type'] == 'scorm_test') {
                 $ctgType = 'tests';
             } else {
                 $ctgType = $current['ctg_type'];
             }
         }
         if (isset($current['incomplete']) && $current['incomplete']) {
             $liClass[] = $ctgType . '_incomplete';
             $tooltip[] = '(' . _TESTSTARTEDAT . ': ' . formatTimestamp($current['incomplete'], 'time') . ')';
         } else {
             if (isset($current['failed']) && $current['failed']) {
                 $liClass[] = $ctgType . '_failed';
             } else {
                 if (isset($current['seen']) && $current['seen'] || isset($current['completed']) && $current['completed']) {
                     $liClass[] = $ctgType . '_passed';
                 } else {
                     $liClass[] = $ctgType;
                 }
             }
         }
         /*
         
                    if ((isset($current['seen']) && $current['seen']) ||(isset($current['completed']) && $current['completed']) || (isset($current['passed']) && $current['passed'])) {
         				$liClass[] = $ctgType.'_passed';
         
                    } else if (isset($current['incomplete']) && $current['incomplete'] && !$current['failed']) {
         				$liClass[] = $ctgType.'_incomplete';
         				$tooltip[] = '('._TESTSTARTEDAT.': '.formatTimestamp($current['incomplete'], 'time').')';
         
                    } else if (isset($current['failed']) && $current['failed']) {
         				$liClass[] = $ctgType.'_failed';
         
                    } else {
                        $liClass[] = $ctgType;
         			}
         */
         if ($options['onclick']) {
             $onclick = $options['onclick'];
         } else {
             if (in_array('treeUnclickable', $linkClass)) {
                 $onclick = 'return false';
             } else {
                 $onclick = '';
             }
         }
         //$toolsString = '<span class = "toolsDiv" style = "position:absolute">'.$activateLink.$editLink.$deleteLink.'</span>';
         $toolsString = '<span>' . $activateLink . $startLink . $editLink . $deleteLink . $options['custom'][$current['id']] . '</span>';
         if (!$showTools) {
             unset($toolsString);
         }
         $treeString .= '
             <li style = "white-space:nowrap;' . $display . '" class = "' . implode(" ", $liClass) . '" id = "node' . $current['id'] . '" noDrag = "' . $nodrag . '" noRename = "true" noDelete = "true">
                 <a onclick = "' . $onclick . '" class = "' . (!$current['active'] ? 'treeinactive' : '') . ' treeLink ' . implode(" ", $linkClass) . '" href = "' . $targetLink . '" title = "' . $fullName . ' ' . implode(" ", $tooltip) . '">' . $unitName . " </a>&nbsp;" . $toolsString;
         $iterator->getDepth() > $depth ? $treeString .= '<ul>' : ($treeString .= '</li>');
         for ($i = $depth; $i > $iterator->getDepth() && $i > $initDepth; $i--) {
             $treeString .= '</ul></li>';
         }
         $current = $iterator->current();
         $depth = $iterator->getDepth();
         $count++;
     }
     $str = '';
     if ($showHide) {
         $str .= '
             <div id = "expand_collapse_div' . $treeId . '" ' . (isset($expand) ? 'expand = "' . $expand . '"' : null) . '>
                 <b><a href = "javascript:void(0)" onclick = "treeObj.setTreeId(\'' . $treeId . '\');treeObj.collapseAll();">' . _HIDEALL . '</a></b> /
                 <b><a href = "javascript:void(0)" onclick = "treeObj.setTreeId(\'' . $treeId . '\');treeObj.expandAll();"  >' . _SHOWALL . '</a></b><br/>
             </div>';
     }
     $str .= '
         <table>
             <tr><td>
                 <ul id = "' . $treeId . '" class = "dhtmlgoodies_tree" selectedNode = "' . $options['selectedNode'] . '">';
     if ($options['tree_root']) {
         $str .= '
                 <li class = "theory" id = "0" noDrag = "false">
                     <a class = "treeactive treeLink" style = "white-space:nowrap;" href = "javascript:void(0)" title = "' . _TREEROOT . '">' . _TREEROOT . "</a>&nbsp;";
     }
     $str .= $treeString . '
                 </ul>
             </td></tr>
         </table>';
     return $str;
 }
Exemple #3
0
 public function getPreviousSiblingNode($queryNode)
 {
     $iterator = new EfrontNodeFilterIterator(new RecursiveIteratorIterator(new RecursiveArrayIterator($this->tree), RecursiveIteratorIterator::SELF_FIRST));
     //Create iterators for the tree
     $iterator->rewind();
     //Initialize iterator
     while ($iterator->valid() && $iterator->key() != $queryNode['parent_content_ID']) {
         //Advance iterator until we reach the designated node
         $iterator->next();
     }
     if ($iterator->valid()) {
         $iterator = new EfrontNodeFilterIterator(new IteratorIterator(new ArrayIterator($iterator->current())));
         $iterator->rewind();
         //Initialize iterator
         while ($iterator->valid() && $iterator->key() != $queryNode['id']) {
             //Advance iterator until we reach the designated node
             $previousNode = $iterator->current();
             $iterator->next();
         }
         if ($iterator->valid()) {
             if (!isset($previousNode)) {
                 //The designated node was apparently the first one, so return false
                 return false;
             } else {
                 if (!$queryNode) {
                     $this->currentNodeId = $previousNode['id'];
                     //If a $queryNode was not specified, we must set the internal pointer to the previous node we just found
                 }
                 //$previousNode = $this -> filterOutChildren(new RecursiveArrayIterator($previousNode));     //Cut off node's children
                 return $previousNode;
             }
         }
     } else {
         throw new EfrontTreeException(_NODEDOESNOTEXIST . ': ' . $queryNode['id'], EfrontTreeException::NODE_NOT_EXISTS);
     }
 }