2 /****************************************************************/
4 /****************************************************************/
5 /* Copyright (c) 2002-2010 */
6 /* Inclusive Design Institute */
9 /* This program is free software. You can redistribute it and/or*/
10 /* modify it under the terms of the GNU General Public License */
11 /* as published by the Free Software Foundation. */
12 /****************************************************************/
42 var $tree_collapse_icon, $tree_expand_icon, $tree_vertline_icon, $tree_horizontal_icon,
43 $tree_split_icon, $tree_disabled_icon, $tree_end_icon, $tree_space_icon;
46 function ContentManager(&$db, $course_id) {
50 $this->course_id = intval($course_id);
52 // Look for tree icons for displaying content navigation from theme image folder,
53 // if the icon is not there, look up in atutor root image folder
54 $this->tree_collapse_icon = find_image($rtl.'tree/tree_collapse.gif', '');
55 $this->tree_expand_icon = find_image($rtl.'tree/tree_expand.gif', '');
56 $this->tree_vertline_icon = find_image($rtl.'tree/tree_vertline.gif', '');
57 $this->tree_horizontal_icon = find_image($rtl.'tree/tree_horizontal.gif', '');
58 $this->tree_split_icon = find_image($rtl.'tree/tree_split.gif', '');
59 $this->tree_disabled_icon = find_image($rtl.'tree/tree_disabled.gif', '');
60 $this->tree_end_icon = find_image($rtl.'tree/tree_end.gif', '');
61 $this->tree_space_icon = find_image($rtl.'tree/tree_space.gif', '');
64 function initContent( ) {
65 if (!($this->course_id > 0)) {
68 $sql = "SELECT content_id, content_parent_id, ordering, title, UNIX_TIMESTAMP(release_date) AS u_release_date, content_type
69 FROM ".TABLE_PREFIX."content
70 WHERE course_id=$this->course_id
71 ORDER BY content_parent_id, ordering";
72 $result = mysql_query($sql, $this->db);
74 /* x could be the ordering or even the content_id */
75 /* don't really need the ordering anyway. */
76 /* $_menu[content_parent_id][x] = array('content_id', 'ordering', 'title') */
79 /* number of content sections */
83 $_menu_info = array();
85 while ($row = mysql_fetch_assoc($result)) {
87 $_menu[$row['content_parent_id']][] = array('content_id'=> $row['content_id'],
88 'ordering' => $row['ordering'],
89 'title' => htmlspecialchars($row['title']),
90 'content_type' => $row['content_type']);
92 $_menu_info[$row['content_id']] = array('content_parent_id' => $row['content_parent_id'],
93 'title' => htmlspecialchars($row['title']),
94 'ordering' => $row['ordering'],
95 'u_release_date' => $row['u_release_date'],
96 'content_type' => $row['content_type']);
99 * add test content asscioations
100 * find associations per content page, and add it as a sublink.
103 $test_rs = $this->getContentTestsAssoc($row['content_id']);
104 while ($test_row = mysql_fetch_assoc($test_rs)){
105 $_menu[$row['content_id']][] = array( 'test_id' => $test_row['test_id'],
106 'title' => htmlspecialchars($test_row['title']),
107 'content_type' => CONTENT_TYPE_CONTENT);
109 /* End of add test content asscioations */
111 if ($row['content_parent_id'] == 0) {
112 $max_depth[$row['content_id']] = 1;
114 $max_depth[$row['content_id']] = $max_depth[$row['content_parent_id']]+1;
118 $this->_menu = $_menu;
120 $this->_menu_info = $_menu_info;
122 $this->num_sections = $num_sections;
124 if (count($max_depth) > 1) {
125 $this->max_depth = max($max_depth);
127 $this->max_depth = 0;
130 // generate array of all the content ids in the same order that they appear in "content navigation"
131 $this->_menu_in_order[] = $next_content_id = $this->getNextContentID(0);
132 while ($next_content_id > 0)
134 $next_content_id = $this->getNextContentID($next_content_id);
136 if (in_array($next_content_id, $this->_menu_in_order)) break;
137 else $this->_menu_in_order[] = $next_content_id;
140 $this->content_length = count($_menu[0]);
143 // This function is called by initContent to construct $this->_menu_in_order, an array to
144 // holds all the content ids in the same order that they appear in "content navigation"
145 function getNextContentID($content_id, $order=0) {
146 // return first root content when $content_id is not given
148 return $this->_menu[0][0]['content_id'];
151 $myParent = $this->_menu_info[$content_id]['content_parent_id'];
152 $myOrder = $this->_menu_info[$content_id]['ordering'];
154 // calculate $myOrder, add in the number of tests in front of this content page
155 if (is_array($this->_menu[$myParent])) {
157 foreach ($this->_menu[$myParent] as $menuContent) {
158 if ($menuContent['content_id'] == $content_id) break;
159 if (isset($menuContent['test_id'])) $num_of_tests++;
162 $myOrder += $num_of_tests;
163 // end of calculating $myOrder
165 /* if this content has children, then take the first one. */
166 if ( isset($this->_menu[$content_id]) && is_array($this->_menu[$content_id]) && ($order==0) ) {
168 // if the child is a test, keep searching for the content id
169 foreach ($this->_menu[$content_id] as $menuID => $menuContent)
171 if (!empty($menuContent['test_id'])) continue;
174 $nextMenu = $this->_menu[$content_id][$menuID]['content_id'];
179 // all children are tests
180 if (!isset($nextMenu))
182 if (isset($this->_menu[$myParent][$myOrder]['content_id'])) {
184 return $this->_menu[$myParent][$myOrder]['content_id'];
187 $nextMenu = $this->getNextContentID($myParent, 1);
193 if (isset($this->_menu[$myParent][$myOrder]) && $this->_menu[$myParent][$myOrder] != '') {
195 return $this->_menu[$myParent][$myOrder]['content_id'];
197 /* No more siblings */
198 if ($myParent != 0) {
199 return $this->getNextContentID($myParent, 1);
205 function getContent($parent_id=-1, $length=-1) {
206 if ($parent_id == -1) {
207 $my_menu_copy = $this->_menu;
209 $my_menu_copy[0] = array_slice($my_menu_copy[0], 0, $length);
211 return $my_menu_copy;
213 return $this->_menu[$parent_id];
217 function &getContentPath($content_id) {
220 $path[] = array('content_id' => $content_id, 'title' => $this->_menu_info[$content_id]['title']);
222 $this->getContentPathRecursive($content_id, $path);
224 $path = array_reverse($path);
229 function getContentPathRecursive($content_id, &$path) {
230 $parent_id = $this->_menu_info[$content_id]['content_parent_id'];
232 if ($parent_id > 0) {
233 $path[] = array('content_id' => $parent_id, 'title' => $this->_menu_info[$parent_id]['title']);
234 $this->getContentPathRecursive($parent_id, $path);
238 function addContent($course_id, $content_parent_id, $ordering, $title, $text, $keywords,
239 $related, $formatting, $release_date, $head = '', $use_customized_head = 0,
240 $test_message = '', $allow_test_export = 1, $content_type = CONTENT_TYPE_CONTENT) {
242 if (!authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN) && ($_SESSION['course_id'] != -1)) {
246 // shift the new neighbouring content down
247 $sql = "UPDATE ".TABLE_PREFIX."content SET ordering=ordering+1
248 WHERE ordering>=$ordering
249 AND content_parent_id=$content_parent_id
250 AND course_id=$_SESSION[course_id]";
251 $result = mysql_query($sql, $this->db);
253 /* main topics all have minor_num = 0 */
254 $sql = "INSERT INTO ".TABLE_PREFIX."content
279 $use_customized_head,
288 $err = mysql_query($sql, $this->db);
290 /* insert the related content */
291 $sql = "SELECT LAST_INSERT_ID() AS insert_id";
292 $result = mysql_query($sql, $this->db);
293 $row = mysql_fetch_assoc($result);
294 $cid = $row['insert_id'];
297 if (is_array($related)) {
298 foreach ($related as $x => $related_content_id) {
299 $related_content_id = intval($related_content_id);
301 if ($related_content_id != 0) {
305 $sql .= '('.$cid.', '.$related_content_id.')';
306 $sql .= ', ('.$related_content_id.', '.$cid.')';
311 $sql = 'INSERT INTO '.TABLE_PREFIX.'related_content VALUES '.$sql;
312 $result = mysql_query($sql, $this->db);
319 function editContent($content_id, $title, $text, $keywords,$related, $formatting,
320 $release_date, $head, $use_customized_head, $test_message,
321 $allow_test_export, $content_type) {
322 if (!authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN)) {
326 /* update the title, text of the newly moved (or not) content */
327 $sql = "UPDATE ".TABLE_PREFIX."content
328 SET title='$title', head='$head', use_customized_head=$use_customized_head,
329 text='$text', keywords='$keywords', formatting=$formatting,
330 revision=revision+1, last_modified=NOW(), release_date='$release_date',
331 test_message='$test_message', allow_test_export=$allow_test_export,
332 content_type=$content_type
333 WHERE content_id=$content_id AND course_id=$_SESSION[course_id]";
334 $result = mysql_query($sql, $this->db);
336 /* update the related content */
337 $result = mysql_query("DELETE FROM ".TABLE_PREFIX."related_content WHERE content_id=$content_id OR related_content_id=$content_id", $this->db);
339 if (is_array($related)) {
340 foreach ($related as $x => $related_content_id) {
341 $related_content_id = intval($related_content_id);
343 if ($related_content_id != 0) {
347 $sql .= '('.$content_id.', '.$related_content_id.')';
348 $sql .= ', ('.$related_content_id.', '.$content_id.')';
353 /* delete the old related content */
354 $result = mysql_query("DELETE FROM ".TABLE_PREFIX."related_content WHERE content_id=$content_id OR related_content_id=$content_id", $this->db);
356 /* insert the new, and the old related content again */
357 $sql = 'INSERT INTO '.TABLE_PREFIX.'related_content VALUES '.$sql;
358 $result = mysql_query($sql, $this->db);
363 function moveContent($content_id, $new_content_parent_id, $new_content_ordering) {
366 if (!authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN)) {
370 /* first get the content to make sure it exists */
371 $sql = "SELECT ordering, content_parent_id FROM ".TABLE_PREFIX."content WHERE content_id=$content_id AND course_id=$_SESSION[course_id]";
372 $result = mysql_query($sql, $this->db);
373 if (!($row = mysql_fetch_assoc($result)) ) {
376 $old_ordering = $row['ordering'];
377 $old_content_parent_id = $row['content_parent_id'];
379 $sql = "SELECT max(ordering) max_ordering FROM ".TABLE_PREFIX."content WHERE content_parent_id=$old_content_parent_id AND course_id=$_SESSION[course_id]";
380 $result = mysql_query($sql, $this->db);
381 $row = mysql_fetch_assoc($result);
382 $max_ordering = $row['max_ordering'];
384 if ($content_id == $new_content_parent_id) {
385 $msg->addError("NO_SELF_AS_PARENT");
389 if ($old_content_parent_id == $new_content_parent_id && $old_ordering == $new_content_ordering) {
390 $msg->addError("SAME_LOCATION");
394 $content_path = $this->getContentPath($new_content_parent_id);
395 foreach ($content_path as $parent){
396 if ($parent['content_id'] == $content_id) {
397 $msg->addError("NO_CHILD_AS_PARENT");
402 // if the new_content_ordering is greater than the maximum ordering of the parent content,
403 // set the $new_content_ordering to the maximum ordering. This happens when move the content
404 // to the last element under the same parent content.
405 if ($old_content_parent_id == $new_content_parent_id && $new_content_ordering > $max_ordering)
406 $new_content_ordering = $max_ordering;
408 if (($old_content_parent_id != $new_content_parent_id) || ($old_ordering != $new_content_ordering)) {
409 // remove the gap left by the moved content
410 $sql = "UPDATE ".TABLE_PREFIX."content
411 SET ordering=ordering-1
412 WHERE ordering>$old_ordering
413 AND content_parent_id=$old_content_parent_id
414 AND content_id<>$content_id
415 AND course_id=$_SESSION[course_id]";
416 $result = mysql_query($sql, $this->db);
418 // shift the new neighbouring content down
419 $sql = "UPDATE ".TABLE_PREFIX."content
420 SET ordering=ordering+1
421 WHERE ordering>=$new_content_ordering
422 AND content_parent_id=$new_content_parent_id
423 AND content_id<>$content_id
424 AND course_id=$_SESSION[course_id]";
425 $result = mysql_query($sql, $this->db);
427 $sql = "UPDATE ".TABLE_PREFIX."content
428 SET content_parent_id=$new_content_parent_id, ordering=$new_content_ordering
429 WHERE content_id=$content_id AND course_id=$_SESSION[course_id]";
430 $result = mysql_query($sql, $this->db);
434 function deleteContent($content_id) {
435 if (!authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN)) {
439 /* check if exists */
440 $sql = "SELECT ordering, content_parent_id FROM ".TABLE_PREFIX."content WHERE content_id=$content_id AND course_id=$_SESSION[course_id]";
441 $result = mysql_query($sql, $this->db);
442 if (!($row = @mysql_fetch_assoc($result)) ) {
445 $ordering = $row['ordering'];
446 $content_parent_id = $row['content_parent_id'];
448 /* check if this content has sub content */
449 $children = $this->_menu[$content_id];
451 if (is_array($children) && (count($children)>0) ) {
452 /* delete its children recursively first*/
453 foreach ($children as $x => $info) {
454 $this->deleteContentRecursive($info['content_id']);
458 /* delete this content page */
459 $sql = "DELETE FROM ".TABLE_PREFIX."content WHERE content_id=$content_id AND course_id=$_SESSION[course_id]";
460 $result = mysql_query($sql, $this->db);
462 /* delete this content from member tracking page */
463 $sql = "DELETE FROM ".TABLE_PREFIX."member_track WHERE content_id=$content_id AND course_id=$_SESSION[course_id]";
464 $result = mysql_query($sql, $this->db);
466 $sql = "DELETE FROM ".TABLE_PREFIX."related_content WHERE content_id=$content_id OR related_content_id=$content_id";
467 $result = mysql_query($sql, $this->db);
469 /* delete the content tests association */
470 $sql = "DELETE FROM ".TABLE_PREFIX."content_tests_assoc WHERE content_id=$content_id";
471 $result = mysql_query($sql, $this->db);
473 /* delete the content forum association */
474 $sql = "DELETE FROM ".TABLE_PREFIX."content_forums_assoc WHERE content_id=$content_id";
475 $result = mysql_query($sql, $this->db);
477 /* Delete all AccessForAll contents */
478 require_once(AT_INCLUDE_PATH.'../mods/_core/imsafa/classes/A4a.class.php');
479 $a4a = new A4a($content_id);
482 /* re-order the rest of the content */
483 $sql = "UPDATE ".TABLE_PREFIX."content SET ordering=ordering-1 WHERE ordering>=$ordering AND content_parent_id=$content_parent_id AND course_id=$_SESSION[course_id]";
484 $result = mysql_query($sql, $this->db);
485 /* end moving block */
487 /* remove the "resume" to this page, b/c it was deleted */
488 $sql = "UPDATE ".TABLE_PREFIX."course_enrollment SET last_cid=0 WHERE course_id=$_SESSION[course_id] AND last_cid=$content_id";
489 $result = mysql_query($sql, $this->db);
495 /* private. call from deleteContent only. */
496 function deleteContentRecursive($content_id) {
497 /* check if this content has sub content */
498 $children = $this->_menu[$content_id];
500 if (is_array($children) && (count($children)>0) ) {
501 /* delete its children recursively first*/
502 foreach ($children as $x => $info) {
503 $this->deleteContent($info['content_id']);
507 /* delete this content page */
508 $sql = "DELETE FROM ".TABLE_PREFIX."content WHERE content_id=$content_id AND course_id=$_SESSION[course_id]";
509 $result = mysql_query($sql, $this->db);
511 /* delete this content from member tracking page */
512 $sql = "DELETE FROM ".TABLE_PREFIX."member_track WHERE content_id=$content_id";
513 $result = mysql_query($sql, $this->db);
515 $sql = "DELETE FROM ".TABLE_PREFIX."related_content WHERE content_id=$content_id OR related_content_id=$content_id";
516 $result = mysql_query($sql, $this->db);
518 /* delete the content tests association */
519 $sql = "DELETE FROM ".TABLE_PREFIX."content_tests_assoc WHERE content_id=$content_id";
520 $result = mysql_query($sql, $this->db);
523 function getContentPage($content_id) {
524 $sql = "SELECT *, DATE_FORMAT(release_date, '%Y-%m-%d %H:%i:00') AS release_date, release_date+0 AS r_date, NOW()+0 AS n_date FROM ".TABLE_PREFIX."content
525 WHERE content_id=$content_id";
526 $result = mysql_query($sql, $this->db);
531 /* @See editor/edit_content.php include/html/dropdowns/related_topics.inc.php include/lib/editor_tabs_functions.inc.php */
532 function getRelatedContent($content_id, $all=false) {
533 if ($content_id == 0) {
536 if ($content_id == '') {
539 $related_content = array();
542 $sql = "SELECT * FROM ".TABLE_PREFIX."related_content WHERE content_id=$content_id OR related_content_id=$content_id";
544 $sql = "SELECT * FROM ".TABLE_PREFIX."related_content WHERE content_id=$content_id";
546 $result = mysql_query($sql, $this->db);
548 while ($row = mysql_fetch_assoc($result)) {
549 if ($row['related_content_id'] != $content_id) {
550 $related_content[] = $row['related_content_id'];
552 $related_content[] = $row['content_id'];
556 return $related_content;
560 * Return a list of tests associated with the selected content
561 * @param int the content id that all tests are associated with it.
562 * @return array list of tests
566 function & getContentTestsAssoc($content_id){
567 $sql = "SELECT ct.test_id, t.title FROM (SELECT * FROM ".TABLE_PREFIX."content_tests_assoc WHERE content_id=$content_id) AS ct LEFT JOIN ".TABLE_PREFIX."tests t ON ct.test_id=t.test_id";
568 $result = mysql_query($sql, $this->db);
572 /*TODO***************BOLOGNA***************REMOVE ME**********/
573 function & getContentForumsAssoc($content_id){
574 $sql = "SELECT cf.forum_id, f.title FROM (SELECT * FROM ".TABLE_PREFIX."content_forums_assoc WHERE content_id=$content_id) AS cf LEFT JOIN ".TABLE_PREFIX."forums f ON cf.forum_id=f.forum_id";
575 $result = mysql_query($sql, $this->db);
579 function & cleanOutput($value) {
580 return stripslashes(htmlspecialchars($value));
584 /* @See include/html/editor_tabs/properties.inc.php */
586 function getNumSections() {
587 return $this->num_sections;
591 function getMaxDepth() {
592 return $this->max_depth;
596 function getContentLength() {
597 return $this->content_length;
600 /* @See include/html/dropdowns/local_menu.inc.php */
601 function getLocationPositions($parent_id, $content_id) {
602 $siblings = $this->getContent($parent_id);
603 for ($i=0;$i<count($siblings); $i++){
604 if ($siblings[$i]['content_id'] == $content_id) {
611 /* Access: Private */
612 function getNumbering($content_id) {
613 $path = $this->getContentPath($content_id);
616 foreach ($path as $page) {
617 $num = $this->getLocationPositions($parent, $page['content_id']) +1;
618 $parent = $page['content_id'];
619 $numbering .= $num.'.';
621 $numbering = substr($numbering, 0, -1);
626 function getPreviousContent($content_id) {
627 if (is_array($this->_menu_in_order))
629 foreach ($this->_menu_in_order as $content_location => $this_content_id)
631 if ($this_content_id == $content_id) break;
634 for ($i=$content_location-1; $i >= 0; $i--)
636 $content_type = $this->_menu_info[$this->_menu_in_order[$i]]['content_type'];
638 if ($content_type == CONTENT_TYPE_CONTENT || $content_type == CONTENT_TYPE_WEBLINK)
639 return array('content_id' => $this->_menu_in_order[$i],
640 'ordering' => $this->_menu_info[$this->_menu_in_order[$i]]['ordering'],
641 'title' => $this->_menu_info[$this->_menu_in_order[$i]]['title']);
647 function getNextContent($content_id) {
648 if (is_array($this->_menu_in_order))
650 foreach ($this->_menu_in_order as $content_location => $this_content_id)
652 if ($this_content_id == $content_id) break;
655 for ($i=$content_location+1; $i < count($this->_menu_in_order); $i++)
657 $content_type = $this->_menu_info[$this->_menu_in_order[$i]]['content_type'];
659 if ($content_type == CONTENT_TYPE_CONTENT || $content_type == CONTENT_TYPE_WEBLINK)
660 return(array('content_id' => $this->_menu_in_order[$i],
661 'ordering' => $this->_menu_info[$this->_menu_in_order[$i]]['ordering'],
662 'title' => $this->_menu_info[$this->_menu_in_order[$i]]['title']));
668 /* @See include/header.inc.php */
669 function generateSequenceCrumbs($cid) {
672 $sequence_links = array();
674 $first = $this->getNextContent(0); // get first
675 if ($_SESSION['prefs']['PREF_NUMBERING'] && $first) {
676 $first['title'] = $this->getNumbering($first['content_id']).' '.$first['title'];
679 $first['url'] = $_base_path.url_rewrite('content.php?cid='.$first['content_id']);
680 $sequence_links['first'] = $first;
683 if (!$cid && $_SESSION['s_cid']) {
684 $resume['title'] = $this->_menu_info[$_SESSION['s_cid']]['title'];
686 if ($_SESSION['prefs']['PREF_NUMBERING']) {
687 $resume['title'] = $this->getNumbering($_SESSION['s_cid']).' ' . $resume['title'];
690 $resume['url'] = $_base_path.url_rewrite('content.php?cid='.$_SESSION['s_cid']);
692 $sequence_links['resume'] = $resume;
695 $previous = $this->getPreviousContent($cid);
697 $next = $this->getNextContent($cid ? $cid : 0);
699 if ($_SESSION['prefs']['PREF_NUMBERING']) {
700 $previous['title'] = $this->getNumbering($previous['content_id']).' '.$previous['title'];
701 $next['title'] = $this->getNumbering($next['content_id']).' '.$next['title'];
704 $next['url'] = $_base_path.url_rewrite('content.php?cid='.$next['content_id']);
705 if (isset($previous['content_id'])) {
706 $previous['url'] = $_base_path.url_rewrite('content.php?cid='.$previous['content_id']);
709 if (isset($previous['content_id'])) {
710 $sequence_links['previous'] = $previous;
712 $previous['url'] = $_base_path . url_rewrite('index.php');
713 $previous['title'] = _AT('course_home');
714 $sequence_links['previous'] = $previous;
716 if (!empty($next['content_id'])) {
717 $sequence_links['next'] = $next;
721 return $sequence_links;
724 /** Generate javascript to hide all root content folders, except the one with current content page
726 * @return print out javascript function initContentMenu()
728 function getInitMenuJS(){
731 echo "\n".'ATutor.course.contentMenu.initContentMenu = function() {'."\n";
733 $sql = "SELECT content_id
734 FROM ".TABLE_PREFIX."content
735 WHERE course_id=$this->course_id
736 AND content_type = ".CONTENT_TYPE_FOLDER;
737 $result = mysql_query($sql, $this->db);
739 // collapse all root content folders
740 while ($row = mysql_fetch_assoc($result)) {
741 echo 'if (ATutor.getcookie("c'.$_SESSION['course_id'].'_'.$row['content_id'].'") == "1") {'."\n".
742 ' ATutor.course.contentMenu.expandContentFolder('.$row['content_id'].');'."\n".
744 ' ATutor.course.contentMenu.collapseContentFolder('.$row['content_id'].');'."\n".
748 // expand the content folder that has current content
749 if (isset($_SESSION['s_cid']) && $_SESSION['s_cid'] > 0) {
750 $current_content_path = $this->getContentPath($_SESSION['s_cid']);
752 for ($i=0; $i < count($current_content_path)-1; $i++) {
753 echo ' ATutor.course.contentMenu.expandContentFolder('.$current_content_path[$i]['content_id'].');'."\n";
754 ' ATutor.setcookie("c'.$_SESSION['course_id'].'_'.$current_content_path[$i]['content_id'].'", "1", 1);'."\n";
756 } else { // expand the first folder at user's first visit
757 // find the first content folder
758 $sql = "SELECT content_id
759 FROM ".TABLE_PREFIX."content c1
760 WHERE course_id=".$this->course_id."
761 AND content_parent_id=0
762 AND content_type=".CONTENT_TYPE_FOLDER."
763 AND exists (SELECT * FROM ".TABLE_PREFIX."content c2
764 WHERE c2.content_parent_id = c1.content_id)
767 $result = mysql_query($sql, $this->db);
769 // print out javascript to expand the first content folder
770 if (mysql_num_rows($result)) {
771 $row = mysql_fetch_assoc($result);
772 echo ' ATutor.course.contentMenu.expandContentFolder('.$row['content_id'].');'."\n";
775 echo '}'."\n"; // end of javascript function initContentMenu()
778 /* @See include/html/dropdowns/menu_menu.inc.php */
779 function printMainMenu( ) {
780 if (!($this->course_id > 0)) {
791 $ignore_state = true;
795 // DO NOT change id value "editable_table", which is used in ATutorContentMenu.js
796 // for the initialization of the inline edit fields
797 echo '<div id="editable_table">';
799 if (authenticate(AT_PRIV_ADMIN,AT_PRIV_RETURN) && !is_mobile_device())
802 <div class="menuedit">
803 <a href="'.$_base_path.'mods/_core/editor/edit_content_folder.php">
804 <img id="img_create_top_folder" src="'.$_base_path.'images/folder_new.gif" alt="'._AT("add_top_folder").'" title="'._AT("add_top_folder").'" style="border:0;height:1.2em" />
806 '<a href="'.$_base_path.'mods/_core/editor/edit_content.php">
807 <img id="img_create_top_content" src="'.$_base_path.'images/page_add.gif" alt="'._AT("add_top_page").'" title="'._AT("add_top_page").'" style="border:0;height:1.2em" />
809 '<a href="javascript:void(0)" onclick="javascript:ATutor.course.contentMenu.switchEditMode();">
810 <img id="img_switch_edit_mode" src="'.$_base_path.'images/medit.gif" alt="'._AT("enter_edit_mode").'" title="'._AT("enter_edit_mode").'" style="border:0;height:1.2em" />
814 $this->printMenu($parent_id, $depth, $path, $children, $truncate, $ignore_state);
817 // javascript for inline editor
818 echo '<script type="text/javascript">
819 var ATutor = ATutor || {};
820 ATutor.course = ATutor.course || {};
821 ATutor.course.contentMenu = ATutor.course.contentMenu || {};
823 ATutor.course.text_enter_edit_mode = "'._AT("enter_edit_mode").'";
824 ATutor.course.text_exit_edit_mode = "'._AT("exit_edit_mode").'";
825 ATutor.base_path = "'.$_base_path.'";
826 ATutor.course.text_expand = "'._AT("expand").'";
827 ATutor.course.text_collapse = "'._AT("collapse").'";
830 // get the javascript to initialize the expand/collapse of the content folders
831 $this->getInitMenuJS();
832 echo '</script>'."\n";
834 // Include the javascript that defines functions for side menu "content navigation" operation
835 // Note that this javascript calls on js function ATutor.course.contentMenu.initContentMenu()
836 // that is generated from php function $this->getInitMenuJS(). So, must call the php function
837 // before including this js script.
838 echo '<script src="'.AT_BASE_HREF.'jscripts/ATutorContentMenu.js" type="text/javascript"></script>'."\n";
841 /* @See tools/sitemap/index.php */
842 function printSiteMapMenu() {
848 $ignore_state = true;
851 $this->printMenu($parent_id, $depth, $path, $children, $truncate, $ignore_state, 'sitemap');
855 function printTOCMenu($cid, $top_num) {
858 $path = $top_num.'.';
861 $ignore_state = false;
864 $this->printMenu($parent_id, $depth, $path, $children, $truncate, $ignore_state);
867 /* @See index.php include/html/dropdowns/local_menu.inc.php */
868 function printSubMenu($cid, $top_num) {
871 $path = $top_num.'.';
874 $ignore_state = false;
877 $this->printMenu($parent_id, $depth, $path, $children, $truncate, $ignore_state);
880 /* @See include/html/menu_menu.inc.php */
881 /* Access: PRIVATE */
882 function printMenu($parent_id, $depth, $path, $children, $truncate, $ignore_state, $from = '') {
883 global $cid, $_my_uri, $_base_path, $rtl, $substr, $strlen;
886 if (!isset($temp_path)) {
888 $temp_path = $this->getContentPath($cid);
890 $temp_path = $this->getContentPath($_SESSION['s_cid']);
894 $highlighted = array();
895 if (is_array($temp_path)) {
896 foreach ($temp_path as $temp_path_item) {
897 $_SESSION['menu'][$temp_path_item['content_id']] = 1;
898 $highlighted[$temp_path_item['content_id']] = true;
904 $this->start = false;
907 if ( isset($this->_menu[$parent_id]) && is_array($this->_menu[$parent_id]) ) {
908 $top_level = $this->_menu[$parent_id];
910 $num_items = count($top_level);
912 echo '<div id="folder'.$parent_id.$from.'">'."\n";
914 foreach ($top_level as $garbage => $content) {
916 //tests do not have content id
917 $content['content_id'] = isset($content['content_id']) ? $content['content_id'] : '';
918 $content['parent_content_id'] = $parent_id;
920 if (!$ignore_state) {
921 $link .= '<a name="menu'.$content['content_id'].'"></a>';
926 if ( (($_SESSION['s_cid'] != $content['content_id']) || ($_SESSION['s_cid'] != $cid)) && ($content['content_type'] == CONTENT_TYPE_CONTENT || $content['content_type'] == CONTENT_TYPE_WEBLINK))
927 { // non-current content nodes with content type "CONTENT_TYPE_CONTENT"
928 if (isset($highlighted[$content['content_id']])) {
933 //content test extension @harris
934 //if this is a test link.
935 if (isset($content['test_id'])){
936 $title_n_alt = $content['title'];
937 $in_link = 'mods/_standard/tests/test_intro.php?tid='.$content['test_id'].SEP.'in_cid='.$content['parent_content_id'];
938 $img_link = ' <img src="'.$_base_path.'images/check.gif" title="'.$title_n_alt.'" alt="'.$title_n_alt.'" />';
940 $in_link = 'content.php?cid='.$content['content_id'];
944 $full_title = $content['title'];
945 $link .= $img_link . ' <a href="'.$_base_path.htmlentities_utf8(url_rewrite($in_link)).'" title="';
946 $base_title_length = 29;
947 if ($_SESSION['prefs']['PREF_NUMBERING']) {
948 $base_title_length = 24;
951 $link .= $content['title'].'">';
953 if ($truncate && ($strlen($content['title']) > ($base_title_length-$depth*4)) ) {
954 $content['title'] = htmlspecialchars(rtrim($substr(htmlspecialchars_decode($content['title']), 0, ($base_title_length-$depth*4)-4))).'...';
957 if (isset($content['test_id'])) {
958 $link .= $content['title'];
960 $link .= '<span class="inlineEdits" id="menu-'.$content['content_id'].'" title="'.$full_title.'">';
961 if($_SESSION['prefs']['PREF_NUMBERING']){
962 $link .= $path.$counter;
964 $link .= ' '.$content['title'].'</span>';
969 $link .= '</strong>';
972 // instructors have privilege to delete content
973 if (authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN) && !isset($content['test_id']) && !is_mobile_device()) {
974 $link .= '<a href="'.$_base_path.'mods/_core/editor/delete_content.php?cid='.$content['content_id'].'"><img src="'.AT_BASE_HREF.'images/x.gif" alt="'._AT("delete_content").'" title="'._AT("delete_content").'" class="del-content-icon" /></a>';
978 { // current content page & nodes with content type "CONTENT_TYPE_FOLDER"
979 $base_title_length = 33;
980 if ($_SESSION['prefs']['PREF_NUMBERING']) {
981 $base_title_length = 26;
984 if (isset($highlighted[$content['content_id']])) {
989 if ($content['content_type'] == CONTENT_TYPE_CONTENT || $content['content_type'] == CONTENT_TYPE_WEBLINK)
990 { // current content page
991 $full_title = $content['title'];
992 $link .= '<a href="'.$_my_uri.'"><img src="'.$_base_path.'images/clr.gif" alt="'._AT('you_are_here').': ';
993 if($_SESSION['prefs']['PREF_NUMBERING']){
994 $link .= $path.$counter;
996 $link .= $content['title'].'" height="1" width="1" border="0" /></a><strong class="current-content" title="'.$content['title'].'">'."\n";
997 if ($truncate && ($strlen($content['title']) > ($base_title_length-$depth*4)) ) {
998 $content['title'] = htmlspecialchars(rtrim($substr(htmlspecialchars_decode($content['title']), 0, ($base_title_length-$depth*4)-4))).'...';
1000 $link .= '<a name="menu'.$content['content_id'].'"></a><span class="inlineEdits" id="menu-'.$content['content_id'].'" title="'.$full_title.'">';
1001 if($_SESSION['prefs']['PREF_NUMBERING']){
1002 $link .= $path.$counter;
1004 $link .= $content['title'].'</span></strong>';
1006 // instructors have privilege to delete content
1007 if (authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN) && !is_mobile_device()) {
1008 $link .= '<a href="'.$_base_path.'mods/_core/editor/delete_content.php?cid='.$content['content_id'].'"><img src="'.AT_BASE_HREF.'images/x.gif" alt="'._AT("delete_content").'" title="'._AT("delete_content").'" class="del-content-icon" /></a>';
1012 { // nodes with content type "CONTENT_TYPE_FOLDER"
1013 $full_title = $content['title'];
1014 if (authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN) && !is_mobile_device()) {
1015 $link .= '<a href="'.$_base_path."mods/_core/editor/edit_content_folder.php?cid=".$content['content_id'].'" title="'.$full_title. _AT('click_edit').'">'."\n";
1018 $link .= '<span style="cursor:pointer" onclick="javascript: ATutor.course.toggleFolder(\''.$content['content_id'].$from.'\', \''._AT('expand').'\', \''._AT('collapse').'\', '.$this->course_id.'); ">'."\n";
1021 if ($truncate && ($strlen($content['title']) > ($base_title_length-$depth*4)) ) {
1022 $content['title'] = htmlspecialchars(rtrim($substr(htmlspecialchars_decode($content['title']), 0, ($base_title_length-$depth*4)-4))).'...';
1024 if (isset($content['test_id']))
1025 $link .= $content['title'];
1027 $link .= '<span class="inlineEdits" id="menu-'.$content['content_id'].'" title="'.$full_title.'">';
1028 if($_SESSION['prefs']['PREF_NUMBERING']){
1029 $link .= $path.$counter;
1031 $link .= ' '.$content['title'].'</span>';
1033 if (authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN) && !is_mobile_device()) {
1034 $link .= '</a>'."\n";
1037 $link .= '</span>'."\n";
1040 // instructors have privilege to delete content
1041 if (authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN) && !is_mobile_device()) {
1042 $link .= '<a href="'.$_base_path.'mods/_core/editor/delete_content.php?cid='.$content['content_id'].'"><img src="'.AT_BASE_HREF.'images/x.gif" alt="'._AT("delete_content").'" title="'._AT("delete_content").'" class="del-content-icon" /></a>';
1047 $link .= '</strong>';
1051 if ($ignore_state) {
1057 if ( isset($this->_menu[$content['content_id']]) && is_array($this->_menu[$content['content_id']]) ) {
1059 for ($i=0; $i<$depth; $i++) {
1060 if ($children[$i] == 1) {
1061 echo '<img src="'.AT_BASE_HREF.$this->tree_vertline_icon.'" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
1063 echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
1067 if (($counter == $num_items) && ($depth > 0)) {
1068 echo '<img src="'.AT_BASE_HREF.$this->tree_end_icon.'" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
1069 $children[$depth] = 0;
1070 } else if ($counter == $num_items) {
1071 echo '<img src="'.AT_BASE_HREF.$this->tree_end_icon.'" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
1072 $children[$depth] = 0;
1074 echo '<img src="'.AT_BASE_HREF.$this->tree_split_icon.'" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
1075 $children[$depth] = 1;
1078 if ($_SESSION['s_cid'] == $content['content_id']) {
1079 if (is_array($this->_menu[$content['content_id']])) {
1080 $_SESSION['menu'][$content['content_id']] = 1;
1084 if (isset($_SESSION['menu'][$content['content_id']]) && $_SESSION['menu'][$content['content_id']] == 1) {
1086 echo '<a href="javascript:void(0)" onclick="javascript: ATutor.course.toggleFolder(\''.$content['content_id'].$from.'\', \''._AT('expand').'\', \''._AT('collapse').'\', '.$this->course_id.'); "><img src="'.AT_BASE_HREF.$this->tree_collapse_icon.'" id="tree_icon'.$content['content_id'].$from.'" alt="'._AT('collapse').'" border="0" width="16" height="16" title="'._AT('collapse').'" class="img-size-tree" /></a>'."\n";
1089 echo '<a href="'.$_my_uri.'collapse='.$content['content_id'].'">'."\n";
1090 echo '<img src="'.AT_BASE_HREF.$this->tree_collapse_icon.'" id="tree_icon'.$content['content_id'].$from.'" alt="'._AT('collapse').'" border="0" width="16" height="16" title="'._AT('collapse').' '.$content['title'].'" class="img-size-tree" onclick="javascript: ATutor.course.toggleFolder(\''.$content['content_id'].$from.'\', \''._AT('expand').'\', \''._AT('collapse').'\', '.$this->course_id.'); " />'."\n";
1095 echo '<a href="javascript:void(0)" onclick="javascript: ATutor.course.toggleFolder(\''.$content['content_id'].$from.'\', \''._AT('expand').'\', \''._AT('collapse').'\', '.$this->course_id.'); "><img src="'.AT_BASE_HREF.$this->tree_collapse_icon.'" id="tree_icon'.$content['content_id'].$from.'" alt="'._AT('collapse').'" border="0" width="16" height="16" title="'._AT('collapse').'" class="img-size-tree" /></a>'."\n";
1098 echo '<a href="'.$_my_uri.'expand='.$content['content_id'].'">'."\n";
1099 echo '<img src="'.AT_BASE_HREF.$this->tree_expand_icon.'" id="tree_icon'.$content['content_id'].$from.'" alt="'._AT('expand').'" border="0" width="16" height="16" title="'._AT('expand').' '.$content['title'].'" class="img-size-tree" onclick="javascript: ATutor.course.toggleFolder(\''.$content['content_id'].$from.'\', \''._AT('expand').'\', \''._AT('collapse').'\', '.$this->course_id.'); " />';
1105 /* doesn't have children */
1106 if ($counter == $num_items) {
1107 for ($i=0; $i<$depth; $i++) {
1108 if ($children[$i] == 1) {
1109 echo '<img src="'.AT_BASE_HREF.$this->tree_vertline_icon.'" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
1111 echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
1114 echo '<img src="'.AT_BASE_HREF.$this->tree_end_icon.'" alt="" border="0" class="img-size-tree" />'."\n";
1116 for ($i=0; $i<$depth; $i++) {
1117 if ($children[$i] == 1) {
1118 echo '<img src="'.AT_BASE_HREF.$this->tree_vertline_icon.'" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
1120 echo '<img src="'.AT_BASE_HREF.$this->tree_space_icon.'" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
1123 echo '<img src="'.AT_BASE_HREF.$this->tree_split_icon.'" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
1125 echo '<img src="'.AT_BASE_HREF.$this->tree_horizontal_icon.'" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
1131 echo "\n<br /></span>\n\n";
1133 if ( $ignore_state || (isset($_SESSION['menu'][$content['content_id']]) && $_SESSION['menu'][$content['content_id']] == 1)) {
1137 $this->printMenu($content['content_id'],
1156 /* @See include/html/editor_tabs/properties.inc.php
1157 @See editor/arrange_content.php
1159 $print_type: "movable" or "related_content"
1161 function printActionMenu($menu, $parent_id, $depth, $path, $children, $print_type = 'movable') {
1163 global $cid, $_my_uri, $_base_path, $rtl;
1167 $top_level = $menu[$parent_id];
1169 if ( is_array($top_level) ) {
1171 $num_items = count($top_level);
1172 foreach ($top_level as $current_num => $content) {
1173 if (isset($content['test_id'])){
1177 $link = $buttons = '';
1181 if ($print_type == 'movable')
1183 if ($content['content_id'] == $_POST['moved_cid']) {
1184 $radio_selected = ' checked="checked" ';
1187 $radio_selected = '';
1190 $buttons = '<td>'."\n".
1192 ' <input type="image" name="move['.$parent_id.'_'.$content['ordering'].']" src="'.$_base_path.'images/before.gif" alt="'._AT('before_topic', $content['title']).'" title="'._AT('before_topic', $content['title']).'" style="height:1.5em; width:1.9em;" />'."\n";
1194 if ($current_num + 1 == count($top_level))
1195 $buttons .= ' <input type="image" name="move['.$parent_id.'_'.($content['ordering']+1).']" src="'.$_base_path.'images/after.gif" alt="'._AT('after_topic', $content['title']).'" title="'._AT('after_topic', $content['title']).'" style="height:1.5em; width:1.9em;" />'."\n";
1197 $buttons .= ' </small>'."\n".
1201 if ($content['content_type'] == CONTENT_TYPE_FOLDER)
1202 $buttons .= '<input type="image" name="move['.$content['content_id'].'_1]" src="'.$_base_path.'images/child_of.gif" style="height:1.25em; width:1.7em;" alt="'._AT('child_of', $content['title']).'" title="'._AT('child_of', $content['title']).'" />';
1204 $buttons .= ' ';
1206 $buttons .= '</td>'."\n".
1207 '<td><input name="moved_cid" value="'.$content['content_id'].'" type="radio" id="r'.$content['content_id'].'" '.$radio_selected .'/></td>'."\n";
1210 $buttons .= '<td>'."\n";
1211 if ($print_type == "related_content")
1213 if ($content['content_type'] == CONTENT_TYPE_CONTENT || $content['content_type'] == CONTENT_TYPE_WEBLINK)
1215 $link .= '<input type="checkbox" name="related[]" value="'.$content['content_id'].'" id="r'.$content['content_id'].'" ';
1216 if (isset($_POST['related']) && in_array($content['content_id'], $_POST['related'])) {
1217 $link .= ' checked="checked"';
1219 $link .= ' />'."\n";
1223 if ($content['content_type'] == CONTENT_TYPE_FOLDER)
1225 $link .= '<img src="'.$_base_path.'images/folder.gif" />';
1227 $link .= ' <label for="r'.$content['content_id'].'">'.$content['title'].'</label>'."\n";
1229 if ( is_array($menu[$content['content_id']]) && !empty($menu[$content['content_id']]) ) {
1232 for ($i=0; $i<$depth; $i++) {
1233 if ($children[$i] == 1) {
1236 if ($end && ($i==0)) {
1237 echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />';
1239 echo '<img src="'.AT_BASE_HREF.$this->tree_vertline_icon.'" alt="" border="0" width="16" height="16" />';
1242 echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />';
1246 if (($counter == $num_items) && ($depth > 0)) {
1247 echo '<img src="'.AT_BASE_HREF.$this->tree_end_icon.'" alt="" border="0" width="16" height="16" />';
1248 $children[$depth] = 0;
1251 if (($num_items == $counter) && ($parent_id == 0)) {
1252 echo '<img src="'.AT_BASE_HREF.$this->tree_end_icon.'" alt="" border="0" width="16" height="16" />';
1255 echo '<img src="'.AT_BASE_HREF.$this->tree_split_icon.'" alt="" border="0" width="16" height="16" />';
1257 $children[$depth] = 1;
1260 if ($_SESSION['s_cid'] == $content['content_id']) {
1261 if (is_array($menu[$content['content_id']])) {
1262 $_SESSION['menu'][$content['content_id']] = 1;
1266 if ($_SESSION['menu'][$content['content_id']] == 1) {
1267 echo '<img src="'.AT_BASE_HREF.$this->tree_disabled_icon.'" alt="'._AT('toggle_disabled').'" border="0" width="16" height="16" title="'._AT('toggle_disabled').'" />';
1270 echo '<img src="'.AT_BASE_HREF.$this->tree_disabled_icon.'" alt="'._AT('toggle_disabled').'" border="0" width="16" height="16" title="'._AT('toggle_disabled').'" />';
1274 /* doesn't have children */
1275 if ($counter == $num_items) {
1278 for ($i=0; $i<$depth; $i++) {
1279 if ($children[$i] == 1) {
1280 if ($end && ($i == 0)) {
1281 echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />';
1283 echo '<img src="'.AT_BASE_HREF.$this->tree_vertline_icon.'" alt="" border="0" width="16" height="16" />';
1286 echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />';
1292 echo '<img src="'.AT_BASE_HREF.$this->tree_end_icon.'" alt="" border="0" />';
1297 for ($i=0; $i<$depth; $i++) {
1298 if ($children[$i] == 1) {
1299 if ($end && !$print) {
1301 echo '<img src="'.AT_BASE_HREF.$this->tree_space_icon.'" alt="" border="0" width="16" height="16" />';
1303 echo '<img src="'.AT_BASE_HREF.$this->tree_vertline_icon.'" alt="" border="0" width="16" height="16" />';
1306 echo '<img src="'.AT_BASE_HREF.$this->tree_space_icon.'" alt="" border="0" width="16" height="16" />';
1314 echo '<img src="'.AT_BASE_HREF.$this->tree_split_icon.'" alt="" border="0" width="16" height="16" />';
1316 echo '<img src="'.AT_BASE_HREF.$this->tree_horizontal_icon.'" alt="" border="0" width="16" height="16" />';
1320 if($_SESSION['prefs']['PREF_NUMBERING']){
1321 echo $path.$counter;
1326 echo '</small></td>'."\n".'</tr>'."\n";
1328 $this->printActionMenu($menu,
1329 $content['content_id'],
1341 /* returns the timestamp of release if this page has not yet been released, or is under a page that has not been released, true otherwise */
1342 /* finds the max(timestamp) of all parents and returns that, true if less than now */
1343 /* Access: public */
1344 function isReleased($cid) {
1345 if ($this->_menu_info[$cid]['content_parent_id'] == 0) {
1346 // this $cid has no parent, so we check its release date directly
1347 if ($this->_menu_info[$cid]['u_release_date'] <= time()) {
1348 // yup! it's released
1351 // nope! not released
1352 return $this->_menu_info[$cid]['u_release_date'];
1355 // this is a sub page, need to check ALL its parents
1356 $parent = $this->isReleased($this->_menu_info[$cid]['content_parent_id']); // recursion
1358 if ($parent !== TRUE && $parent > $this->_menu_info[$cid]['u_release_date']) {
1360 } else if ($this->_menu_info[$cid]['u_release_date'] <= time()) {
1363 return $this->_menu_info[$cid]['u_release_date'];
1367 /* Returns the first test_id if this page has pre-test(s) to be passed,
1368 * The pre-tests associated with the parent folders has higher priority to be taken.
1369 * or is under a page that has pre-test(s) to be passed,
1370 * 0 if has no pre-test(s) to be passed
1371 * -1 if one of the pre-test(s) has expired, the content should not be displayed in this case
1374 function getPretest($cid) {
1375 // Prepare all the parent folders to this cid since the pre-tests
1376 // associated with the parent folders has higher priority to be taken.
1377 $this_content_path = $this->getContentPath($cid);
1379 foreach ($this_content_path as $this_content) {
1380 $this_pre_test_id = $this->getOnePretest($this_content['content_id']);
1382 if ($this_pre_test_id > 0 || $this_pre_test_id == -1){
1383 return $this_pre_test_id;
1392 /* returns the first test_id if this content has pre-test(s) to be passed,
1393 * 0 if has no pre-test(s) to be passed
1394 * -1 if one of the pre-test(s) has expired, the content should not be displayed in this case
1397 function getOnePretest($cid) {
1399 include_once(AT_INCLUDE_PATH.'../mods/_standard/tests/lib/test_result_functions.inc.php');
1401 $sql = "SELECT *, UNIX_TIMESTAMP(t.start_date) AS start_date, UNIX_TIMESTAMP(t.end_date) AS end_date
1402 FROM ".TABLE_PREFIX."tests t, ".TABLE_PREFIX."content_prerequisites cp
1403 WHERE cp.content_id=".$cid."
1404 AND cp.type = '".CONTENT_PRE_TEST."'
1405 AND cp.item_id=t.test_id";
1406 $result= mysql_query($sql, $db);
1408 while ($row = mysql_fetch_assoc($result))
1410 // check to make sure we can access this test
1411 if (!$row['guests'] && ($_SESSION['enroll'] == AT_ENROLL_NO || $_SESSION['enroll'] == AT_ENROLL_ALUMNUS)) {
1412 $msg->addInfo('NOT_ENROLLED');
1415 if (!$row['guests'] && !authenticate_test($row['test_id'])) {
1416 $msg->addInfo(array('PRETEST_NO_PRIV',$row['title']));
1419 // if the test is not release, not allow student to view the content
1420 if ($row['start_date'] > time() || $row['end_date'] < time()) {
1421 $msg->addInfo(array('PRETEST_EXPIRED',$row['title']));
1425 $sql = "SELECT tr.result_id, count(*) num_of_questions, sum(ta.score) score, sum(tqa.weight) total_weight
1426 FROM ".TABLE_PREFIX."tests_results tr, ".TABLE_PREFIX."tests_answers ta, ".TABLE_PREFIX."tests_questions_assoc tqa
1427 WHERE tr.test_id = ".$row['test_id']."
1428 AND tr.member_id = ".$_SESSION['member_id']."
1429 AND tr.result_id = ta.result_id
1430 AND tr.test_id = tqa.test_id
1431 AND ta.question_id = tqa.question_id
1432 GROUP BY tr.result_id";
1433 $result_score = mysql_query($sql, $db);
1435 $num_of_attempts = 0;
1436 while ($row_score = mysql_fetch_assoc($result_score))
1438 // skip the test when:
1439 // 1. no pass score is defined. this is a survey.
1440 // 2. the student has passed the test
1441 // 3. the test has no question
1442 if (($row['passscore'] == 0 && $row['passpercent'] == 0) ||
1443 $row_score['num_of_questions'] == 0 ||
1444 ($row['passscore']<>0 && $row_score['score']>=$row['passscore']) ||
1445 ($row['passpercent']<>0 && ($row_score['score']/$row_score['total_weight']*100)>=$row['passpercent']))
1451 if ($row['num_takes'] != AT_TESTS_TAKE_UNLIMITED && $num_of_attempts >= $row['num_takes'])
1453 $msg->addInfo(array('PRETEST_FAILED',$row['title']));
1456 return $row['test_id'];
1462 * Return true if this content page allows export, else false.
1463 * @param int content id
1464 * @return true if 'allow_test_export'==1 || is instructor || oauth export into Transformable
1466 function allowTestExport($content_id){
1467 if (isset($_SESSION['is_admin']) || (isset($_REQUEST['m']) && isset($_REQUEST['c']))) {
1470 $sql = "SELECT allow_test_export FROM ".TABLE_PREFIX."content WHERE content_id=$content_id";
1471 $result = mysql_query($sql, $this->db);
1472 if ($row = mysql_fetch_assoc($result)){
1473 if ($row['allow_test_export'] == 1){
1482 * This function returns an array of content tools' shortcuts
1484 * @param: $content_row: an array of the current content information
1485 * @return: an array of all the tool shortcuts that apply to the current content or content folder
1487 public static function getToolShortcuts($content_row)
1489 global $_base_href, $contentManager;
1491 $shortcuts = array();
1492 if (( ($content_row['r_date'] <= $content_row['n_date'])
1493 && ((!$content_row['content_parent_id'] && ($_SESSION['packaging'] == 'top'))
1494 || ($_SESSION['packaging'] == 'all'))
1495 ) || authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN)) {
1496 $shortcuts[] = array('title' => _AT('export_content'), 'url' => $_base_href . 'mods/_core/imscp/ims_export.php?cid='.$content_row['content_id'], 'icon' => $_base_href . 'images/download.png');
1499 if (authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN)) {
1500 if ($content_row['content_type'] == CONTENT_TYPE_CONTENT || $content_row['content_type'] == CONTENT_TYPE_WEBLINK) {
1501 $shortcuts[] = array(
1502 'title' => _AT('edit_this_page'),
1503 'url' => $_base_href . 'mods/_core/editor/edit_content.php?cid='.$content_row['content_id'],
1504 'icon' => $_base_href . 'images/medit.gif');
1506 $shortcuts[] = array(
1507 'title' => _AT('add_sibling_folder'),
1508 'url' => $_base_href.'mods/_core/editor/edit_content_folder.php?pid='.$contentManager->_menu_info[$content_row['content_id']]['content_parent_id'],
1509 'icon' => $_base_href . 'images/folder_new_sibling.gif');
1511 if ($content_row['content_type'] == CONTENT_TYPE_FOLDER) {
1512 $shortcuts[] = array(
1513 'title' => _AT('add_sub_folder'),
1514 'url' => $_base_href . 'mods/_core/editor/edit_content_folder.php?pid='.$content_row['content_id'],
1515 'icon' => $_base_href . 'images/folder_new_sub.gif');
1518 $shortcuts[] = array(
1519 'title' => _AT('add_sibling_page'),
1520 'url' => $_base_href.'mods/_core/editor/edit_content.php?pid='.$contentManager->_menu_info[$content_row['content_id']]['content_parent_id'],
1521 'icon' => $_base_href . 'images/page_add_sibling.gif');
1523 if ($content_row['content_type'] == CONTENT_TYPE_CONTENT || $content_row['content_type'] == CONTENT_TYPE_WEBLINK) {
1524 $shortcuts[] = array(
1525 'title' => _AT('delete_this_page'),
1526 'url' => $_base_href . 'mods/_core/editor/delete_content.php?cid='.$content_row['content_id'],
1527 'icon' => $_base_href . 'images/page_delete.gif');
1529 else if ($content_row['content_type'] == CONTENT_TYPE_FOLDER) {
1530 $shortcuts[] = array(
1531 'title' => _AT('add_sub_page'),
1532 'url' => $_base_href . 'mods/_core/editor/edit_content.php?pid='.$content_row['content_id'],
1533 'icon' => $_base_href . 'images/page_add_sub.gif');
1534 $shortcuts[] = array(
1535 'title' => _AT('delete_this_folder'),
1536 'url' => $_base_href . 'mods/_core/editor/delete_content.php?cid='.$content_row['content_id'],
1537 'icon' => $_base_href . 'images/page_delete.gif');