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 function ContentManager(&$db, $course_id) {
44 $this->course_id = intval($course_id);
47 function initContent( ) {
48 if (!($this->course_id > 0)) {
51 $sql = "SELECT content_id, content_parent_id, ordering, title, UNIX_TIMESTAMP(release_date) AS u_release_date, content_type
52 FROM ".TABLE_PREFIX."content
53 WHERE course_id=$this->course_id
54 ORDER BY content_parent_id, ordering";
55 $result = mysql_query($sql, $this->db);
57 /* x could be the ordering or even the content_id */
58 /* don't really need the ordering anyway. */
59 /* $_menu[content_parent_id][x] = array('content_id', 'ordering', 'title') */
62 /* number of content sections */
66 $_menu_info = array();
68 while ($row = mysql_fetch_assoc($result)) {
70 $_menu[$row['content_parent_id']][] = array('content_id'=> $row['content_id'],
71 'ordering' => $row['ordering'],
72 'title' => htmlspecialchars($row['title']),
73 'content_type' => $row['content_type']);
75 $_menu_info[$row['content_id']] = array('content_parent_id' => $row['content_parent_id'],
76 'title' => htmlspecialchars($row['title']),
77 'ordering' => $row['ordering'],
78 'u_release_date' => $row['u_release_date'],
79 'content_type' => $row['content_type']);
82 * add test content asscioations
83 * find associations per content page, and add it as a sublink.
86 $test_rs = $this->getContentTestsAssoc($row['content_id']);
87 while ($test_row = mysql_fetch_assoc($test_rs)){
88 $_menu[$row['content_id']][] = array( 'test_id' => $test_row['test_id'],
89 'title' => htmlspecialchars($test_row['title']),
90 'content_type' => CONTENT_TYPE_CONTENT);
92 /* End of add test content asscioations */
94 if ($row['content_parent_id'] == 0) {
95 $max_depth[$row['content_id']] = 1;
97 $max_depth[$row['content_id']] = $max_depth[$row['content_parent_id']]+1;
101 $this->_menu = $_menu;
103 $this->_menu_info = $_menu_info;
105 $this->num_sections = $num_sections;
107 if (count($max_depth) > 1) {
108 $this->max_depth = max($max_depth);
110 $this->max_depth = 0;
113 // generate array of all the content ids in the same order that they appear in "content navigation"
114 $this->_menu_in_order[] = $next_content_id = $this->getNextContentID(0);
115 while ($next_content_id > 0)
117 $next_content_id = $this->getNextContentID($next_content_id);
119 if (in_array($next_content_id, $this->_menu_in_order)) break;
120 else $this->_menu_in_order[] = $next_content_id;
123 $this->content_length = count($_menu[0]);
126 // This function is called by initContent to construct $this->_menu_in_order, an array to
127 // holds all the content ids in the same order that they appear in "content navigation"
128 function getNextContentID($content_id, $order=0) {
129 // return first root content when $content_id is not given
131 return $this->_menu[0][0]['content_id'];
134 $myParent = $this->_menu_info[$content_id]['content_parent_id'];
135 $myOrder = $this->_menu_info[$content_id]['ordering'];
137 // calculate $myOrder, add in the number of tests in front of this content page
138 if (is_array($this->_menu[$myParent])) {
140 foreach ($this->_menu[$myParent] as $menuContent) {
141 if ($menuContent['content_id'] == $content_id) break;
142 if (isset($menuContent['test_id'])) $num_of_tests++;
145 $myOrder += $num_of_tests;
146 // end of calculating $myOrder
148 /* if this content has children, then take the first one. */
149 if ( isset($this->_menu[$content_id]) && is_array($this->_menu[$content_id]) && ($order==0) ) {
151 // if the child is a test, keep searching for the content id
152 foreach ($this->_menu[$content_id] as $menuID => $menuContent)
154 if (!empty($menuContent['test_id'])) continue;
157 $nextMenu = $this->_menu[$content_id][$menuID]['content_id'];
162 // all children are tests
163 if (!isset($nextMenu))
165 if (isset($this->_menu[$myParent][$myOrder]['content_id'])) {
167 return $this->_menu[$myParent][$myOrder]['content_id'];
170 $nextMenu = $this->getNextContentID($myParent, 1);
176 if (isset($this->_menu[$myParent][$myOrder]) && $this->_menu[$myParent][$myOrder] != '') {
178 return $this->_menu[$myParent][$myOrder]['content_id'];
180 /* No more siblings */
181 if ($myParent != 0) {
182 return $this->getNextContentID($myParent, 1);
188 function getContent($parent_id=-1, $length=-1) {
189 if ($parent_id == -1) {
190 $my_menu_copy = $this->_menu;
192 $my_menu_copy[0] = array_slice($my_menu_copy[0], 0, $length);
194 return $my_menu_copy;
196 return $this->_menu[$parent_id];
200 function &getContentPath($content_id) {
203 $path[] = array('content_id' => $content_id, 'title' => $this->_menu_info[$content_id]['title']);
205 $this->getContentPathRecursive($content_id, $path);
207 $path = array_reverse($path);
212 function getContentPathRecursive($content_id, &$path) {
213 $parent_id = $this->_menu_info[$content_id]['content_parent_id'];
215 if ($parent_id > 0) {
216 $path[] = array('content_id' => $parent_id, 'title' => $this->_menu_info[$parent_id]['title']);
217 $this->getContentPathRecursive($parent_id, $path);
221 function addContent($course_id, $content_parent_id, $ordering, $title, $text, $keywords,
222 $related, $formatting, $release_date, $head = '', $use_customized_head = 0,
223 $test_message = '', $allow_test_export = 1, $content_type = CONTENT_TYPE_CONTENT) {
225 if (!authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN) && ($_SESSION['course_id'] != -1)) {
229 // shift the new neighbouring content down
230 $sql = "UPDATE ".TABLE_PREFIX."content SET ordering=ordering+1
231 WHERE ordering>=$ordering
232 AND content_parent_id=$content_parent_id
233 AND course_id=$_SESSION[course_id]";
234 $result = mysql_query($sql, $this->db);
236 /* main topics all have minor_num = 0 */
237 $sql = "INSERT INTO ".TABLE_PREFIX."content
262 $use_customized_head,
271 $err = mysql_query($sql, $this->db);
273 /* insert the related content */
274 $sql = "SELECT LAST_INSERT_ID() AS insert_id";
275 $result = mysql_query($sql, $this->db);
276 $row = mysql_fetch_assoc($result);
277 $cid = $row['insert_id'];
280 if (is_array($related)) {
281 foreach ($related as $x => $related_content_id) {
282 $related_content_id = intval($related_content_id);
284 if ($related_content_id != 0) {
288 $sql .= '('.$cid.', '.$related_content_id.')';
289 $sql .= ', ('.$related_content_id.', '.$cid.')';
294 $sql = 'INSERT INTO '.TABLE_PREFIX.'related_content VALUES '.$sql;
295 $result = mysql_query($sql, $this->db);
302 function editContent($content_id, $title, $text, $keywords,$related, $formatting,
303 $release_date, $head, $use_customized_head, $test_message,
304 $allow_test_export) {
305 if (!authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN)) {
309 /* update the title, text of the newly moved (or not) content */
310 $sql = "UPDATE ".TABLE_PREFIX."content
311 SET title='$title', head='$head', use_customized_head=$use_customized_head,
312 text='$text', keywords='$keywords', formatting=$formatting,
313 revision=revision+1, last_modified=NOW(), release_date='$release_date',
314 test_message='$test_message', allow_test_export=$allow_test_export
315 WHERE content_id=$content_id AND course_id=$_SESSION[course_id]";
316 $result = mysql_query($sql, $this->db);
318 /* update the related content */
319 $result = mysql_query("DELETE FROM ".TABLE_PREFIX."related_content WHERE content_id=$content_id OR related_content_id=$content_id", $this->db);
321 if (is_array($related)) {
322 foreach ($related as $x => $related_content_id) {
323 $related_content_id = intval($related_content_id);
325 if ($related_content_id != 0) {
329 $sql .= '('.$content_id.', '.$related_content_id.')';
330 $sql .= ', ('.$related_content_id.', '.$content_id.')';
335 /* delete the old related content */
336 $result = mysql_query("DELETE FROM ".TABLE_PREFIX."related_content WHERE content_id=$content_id OR related_content_id=$content_id", $this->db);
338 /* insert the new, and the old related content again */
339 $sql = 'INSERT INTO '.TABLE_PREFIX.'related_content VALUES '.$sql;
340 $result = mysql_query($sql, $this->db);
345 function moveContent($content_id, $new_content_parent_id, $new_content_ordering) {
348 if (!authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN)) {
352 /* first get the content to make sure it exists */
353 $sql = "SELECT ordering, content_parent_id FROM ".TABLE_PREFIX."content WHERE content_id=$content_id AND course_id=$_SESSION[course_id]";
354 $result = mysql_query($sql, $this->db);
355 if (!($row = mysql_fetch_assoc($result)) ) {
358 $old_ordering = $row['ordering'];
359 $old_content_parent_id = $row['content_parent_id'];
361 $sql = "SELECT max(ordering) max_ordering FROM ".TABLE_PREFIX."content WHERE content_parent_id=$old_content_parent_id AND course_id=$_SESSION[course_id]";
362 $result = mysql_query($sql, $this->db);
363 $row = mysql_fetch_assoc($result);
364 $max_ordering = $row['max_ordering'];
366 if ($content_id == $new_content_parent_id) {
367 $msg->addError("NO_SELF_AS_PARENT");
371 if ($old_content_parent_id == $new_content_parent_id && $old_ordering == $new_content_ordering) {
372 $msg->addError("SAME_LOCATION");
376 $content_path = $this->getContentPath($new_content_parent_id);
377 foreach ($content_path as $parent){
378 if ($parent['content_id'] == $content_id) {
379 $msg->addError("NO_CHILD_AS_PARENT");
384 // if the new_content_ordering is greater than the maximum ordering of the parent content,
385 // set the $new_content_ordering to the maximum ordering. This happens when move the content
386 // to the last element under the same parent content.
387 if ($old_content_parent_id == $new_content_parent_id && $new_content_ordering > $max_ordering)
388 $new_content_ordering = $max_ordering;
390 if (($old_content_parent_id != $new_content_parent_id) || ($old_ordering != $new_content_ordering)) {
391 // remove the gap left by the moved content
392 $sql = "UPDATE ".TABLE_PREFIX."content
393 SET ordering=ordering-1
394 WHERE ordering>$old_ordering
395 AND content_parent_id=$old_content_parent_id
396 AND content_id<>$content_id
397 AND course_id=$_SESSION[course_id]";
398 $result = mysql_query($sql, $this->db);
400 // shift the new neighbouring content down
401 $sql = "UPDATE ".TABLE_PREFIX."content
402 SET ordering=ordering+1
403 WHERE ordering>=$new_content_ordering
404 AND content_parent_id=$new_content_parent_id
405 AND content_id<>$content_id
406 AND course_id=$_SESSION[course_id]";
407 $result = mysql_query($sql, $this->db);
409 $sql = "UPDATE ".TABLE_PREFIX."content
410 SET content_parent_id=$new_content_parent_id, ordering=$new_content_ordering
411 WHERE content_id=$content_id AND course_id=$_SESSION[course_id]";
412 $result = mysql_query($sql, $this->db);
416 function deleteContent($content_id) {
417 if (!authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN)) {
421 /* check if exists */
422 $sql = "SELECT ordering, content_parent_id FROM ".TABLE_PREFIX."content WHERE content_id=$content_id AND course_id=$_SESSION[course_id]";
423 $result = mysql_query($sql, $this->db);
424 if (!($row = @mysql_fetch_assoc($result)) ) {
427 $ordering = $row['ordering'];
428 $content_parent_id = $row['content_parent_id'];
430 /* check if this content has sub content */
431 $children = $this->_menu[$content_id];
433 if (is_array($children) && (count($children)>0) ) {
434 /* delete its children recursively first*/
435 foreach ($children as $x => $info) {
436 $this->deleteContentRecursive($info['content_id']);
440 /* delete this content page */
441 $sql = "DELETE FROM ".TABLE_PREFIX."content WHERE content_id=$content_id AND course_id=$_SESSION[course_id]";
442 $result = mysql_query($sql, $this->db);
444 /* delete this content from member tracking page */
445 $sql = "DELETE FROM ".TABLE_PREFIX."member_track WHERE content_id=$content_id AND course_id=$_SESSION[course_id]";
446 $result = mysql_query($sql, $this->db);
448 $sql = "DELETE FROM ".TABLE_PREFIX."related_content WHERE content_id=$content_id OR related_content_id=$content_id";
449 $result = mysql_query($sql, $this->db);
451 /* delete the content tests association */
452 $sql = "DELETE FROM ".TABLE_PREFIX."content_tests_assoc WHERE content_id=$content_id";
453 $result = mysql_query($sql, $this->db);
455 /* delete the content forum association */
456 $sql = "DELETE FROM ".TABLE_PREFIX."content_forums_assoc WHERE content_id=$content_id";
457 $result = mysql_query($sql, $this->db);
459 /* Delete all AccessForAll contents */
460 require_once(AT_INCLUDE_PATH.'../mods/_core/imsafa/classes/A4a.class.php');
461 $a4a = new A4a($content_id);
464 /* re-order the rest of the content */
465 $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]";
466 $result = mysql_query($sql, $this->db);
467 /* end moving block */
469 /* remove the "resume" to this page, b/c it was deleted */
470 $sql = "UPDATE ".TABLE_PREFIX."course_enrollment SET last_cid=0 WHERE course_id=$_SESSION[course_id] AND last_cid=$content_id";
471 $result = mysql_query($sql, $this->db);
477 /* private. call from deleteContent only. */
478 function deleteContentRecursive($content_id) {
479 /* check if this content has sub content */
480 $children = $this->_menu[$content_id];
482 if (is_array($children) && (count($children)>0) ) {
483 /* delete its children recursively first*/
484 foreach ($children as $x => $info) {
485 $this->deleteContent($info['content_id']);
489 /* delete this content page */
490 $sql = "DELETE FROM ".TABLE_PREFIX."content WHERE content_id=$content_id AND course_id=$_SESSION[course_id]";
491 $result = mysql_query($sql, $this->db);
493 /* delete this content from member tracking page */
494 $sql = "DELETE FROM ".TABLE_PREFIX."member_track WHERE content_id=$content_id";
495 $result = mysql_query($sql, $this->db);
497 $sql = "DELETE FROM ".TABLE_PREFIX."related_content WHERE content_id=$content_id OR related_content_id=$content_id";
498 $result = mysql_query($sql, $this->db);
500 /* delete the content tests association */
501 $sql = "DELETE FROM ".TABLE_PREFIX."content_tests_assoc WHERE content_id=$content_id";
502 $result = mysql_query($sql, $this->db);
505 function getContentPage($content_id) {
506 $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
507 WHERE content_id=$content_id";
508 $result = mysql_query($sql, $this->db);
513 /* @See editor/edit_content.php include/html/dropdowns/related_topics.inc.php include/lib/editor_tabs_functions.inc.php */
514 function getRelatedContent($content_id, $all=false) {
515 if ($content_id == 0) {
518 if ($content_id == '') {
521 $related_content = array();
524 $sql = "SELECT * FROM ".TABLE_PREFIX."related_content WHERE content_id=$content_id OR related_content_id=$content_id";
526 $sql = "SELECT * FROM ".TABLE_PREFIX."related_content WHERE content_id=$content_id";
528 $result = mysql_query($sql, $this->db);
530 while ($row = mysql_fetch_assoc($result)) {
531 if ($row['related_content_id'] != $content_id) {
532 $related_content[] = $row['related_content_id'];
534 $related_content[] = $row['content_id'];
538 return $related_content;
542 * Return a list of tests associated with the selected content
543 * @param int the content id that all tests are associated with it.
544 * @return array list of tests
548 function & getContentTestsAssoc($content_id){
549 $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";
550 $result = mysql_query($sql, $this->db);
554 /*TODO***************BOLOGNA***************REMOVE ME**********/
555 function & getContentForumsAssoc($content_id){
556 $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";
557 $result = mysql_query($sql, $this->db);
561 function & cleanOutput($value) {
562 return stripslashes(htmlspecialchars($value));
566 /* @See include/html/editor_tabs/properties.inc.php */
568 function getNumSections() {
569 return $this->num_sections;
573 function getMaxDepth() {
574 return $this->max_depth;
578 function getContentLength() {
579 return $this->content_length;
582 /* @See include/html/dropdowns/local_menu.inc.php */
583 function getLocationPositions($parent_id, $content_id) {
584 $siblings = $this->getContent($parent_id);
585 for ($i=0;$i<count($siblings); $i++){
586 if ($siblings[$i]['content_id'] == $content_id) {
593 /* Access: Private */
594 function getNumbering($content_id) {
595 $path = $this->getContentPath($content_id);
598 foreach ($path as $page) {
599 $num = $this->getLocationPositions($parent, $page['content_id']) +1;
600 $parent = $page['content_id'];
601 $numbering .= $num.'.';
603 $numbering = substr($numbering, 0, -1);
608 function getPreviousContent($content_id) {
609 if (is_array($this->_menu_in_order))
611 foreach ($this->_menu_in_order as $content_location => $this_content_id)
613 if ($this_content_id == $content_id) break;
616 for ($i=$content_location-1; $i >= 0; $i--)
618 $content_type = $this->_menu_info[$this->_menu_in_order[$i]]['content_type'];
620 if ($content_type == CONTENT_TYPE_CONTENT || $content_type == CONTENT_TYPE_WEBLINK)
621 return array('content_id' => $this->_menu_in_order[$i],
622 'ordering' => $this->_menu_info[$this->_menu_in_order[$i]]['ordering'],
623 'title' => $this->_menu_info[$this->_menu_in_order[$i]]['title']);
629 function getNextContent($content_id) {
630 if (is_array($this->_menu_in_order))
632 foreach ($this->_menu_in_order as $content_location => $this_content_id)
634 if ($this_content_id == $content_id) break;
637 for ($i=$content_location+1; $i < count($this->_menu_in_order); $i++)
639 $content_type = $this->_menu_info[$this->_menu_in_order[$i]]['content_type'];
641 if ($content_type == CONTENT_TYPE_CONTENT || $content_type == CONTENT_TYPE_WEBLINK)
642 return(array('content_id' => $this->_menu_in_order[$i],
643 'ordering' => $this->_menu_info[$this->_menu_in_order[$i]]['ordering'],
644 'title' => $this->_menu_info[$this->_menu_in_order[$i]]['title']));
650 /* @See include/header.inc.php */
651 function generateSequenceCrumbs($cid) {
654 $sequence_links = array();
656 $first = $this->getNextContent(0); // get first
657 if ($_SESSION['prefs']['PREF_NUMBERING'] && $first) {
658 $first['title'] = $this->getNumbering($first['content_id']).' '.$first['title'];
661 $first['url'] = $_base_path.url_rewrite('content.php?cid='.$first['content_id']);
662 $sequence_links['first'] = $first;
665 if (!$cid && $_SESSION['s_cid']) {
666 $resume['title'] = $this->_menu_info[$_SESSION['s_cid']]['title'];
668 if ($_SESSION['prefs']['PREF_NUMBERING']) {
669 $resume['title'] = $this->getNumbering($_SESSION['s_cid']).' ' . $resume['title'];
672 $resume['url'] = $_base_path.url_rewrite('content.php?cid='.$_SESSION['s_cid']);
674 $sequence_links['resume'] = $resume;
677 $previous = $this->getPreviousContent($cid);
679 $next = $this->getNextContent($cid ? $cid : 0);
681 if ($_SESSION['prefs']['PREF_NUMBERING']) {
682 $previous['title'] = $this->getNumbering($previous['content_id']).' '.$previous['title'];
683 $next['title'] = $this->getNumbering($next['content_id']).' '.$next['title'];
686 $next['url'] = $_base_path.url_rewrite('content.php?cid='.$next['content_id']);
687 if (isset($previous['content_id'])) {
688 $previous['url'] = $_base_path.url_rewrite('content.php?cid='.$previous['content_id']);
691 if (isset($previous['content_id'])) {
692 $sequence_links['previous'] = $previous;
694 $previous['url'] = $_base_path . url_rewrite('index.php');
695 $previous['title'] = _AT('home');
696 $sequence_links['previous'] = $previous;
698 if (!empty($next['content_id'])) {
699 $sequence_links['next'] = $next;
703 return $sequence_links;
706 /** Generate javascript to hide all root content folders, except the one with current content page
708 * @return print out javascript function initContentMenu()
714 function initContentMenu() {
715 tree_collapse_icon = "'.$_base_path.'images/tree/tree_collapse.gif";
716 tree_expand_icon = "'.$_base_path.'images/tree/tree_expand.gif";
720 $sql = "SELECT content_id
721 FROM ".TABLE_PREFIX."content
722 WHERE course_id=$this->course_id
723 AND content_type = ".CONTENT_TYPE_FOLDER;
724 $result = mysql_query($sql, $this->db);
726 // collapse all root content folders
727 while ($row = mysql_fetch_assoc($result)) {
729 if (ATutor.getcookie("c'.$_SESSION['course_id'].'_'.$row['content_id'].'") == "1")
731 jQuery("#folder"+'.$row['content_id'].').show();
732 jQuery("#tree_icon"+'.$row['content_id'].').attr("src", tree_collapse_icon);
733 jQuery("#tree_icon"+'.$row['content_id'].').attr("alt", "'._AT("collapse").'");
734 jQuery("#tree_icon"+'.$row['content_id'].').attr("title", "'._AT("collapse").'");
738 jQuery("#folder"+'.$row['content_id'].').hide();
739 jQuery("#tree_icon"+'.$row['content_id'].').attr("src", tree_expand_icon);
740 jQuery("#tree_icon"+'.$row['content_id'].').attr("alt", "'._AT("expand").'");
741 jQuery("#tree_icon"+'.$row['content_id'].').attr("title", "'._AT("expand").'");
746 // expand the content folder that has current content
747 if (isset($_SESSION['s_cid']) && $_SESSION['s_cid'] > 0) {
748 $current_content_path = $this->getContentPath($_SESSION['s_cid']);
750 for ($i=0; $i < count($current_content_path)-1; $i++)
752 jQuery("#folder"+'.$current_content_path[$i]['content_id'].').show();
753 jQuery("#tree_icon"+'.$current_content_path[$i]['content_id'].').attr("src", tree_collapse_icon);
754 jQuery("#tree_icon"+'.$current_content_path[$i]['content_id'].').attr("alt", "'._AT("collapse").'");
755 ATutor.setcookie("c'.$_SESSION['course_id'].'_'.$current_content_path[$i]['content_id'].'", "1", 1);
758 echo '}'; // end of javascript function initContentMenu()
761 /* @See include/html/dropdowns/menu_menu.inc.php */
762 function printMainMenu( ) {
763 if (!($this->course_id > 0)) {
774 $ignore_state = true;
778 // if change the location of this line, change function switchEditMode(), else condition accordingly
779 echo '<div id="editable_table">';
781 if (authenticate(AT_PRIV_ADMIN,AT_PRIV_RETURN) && !is_mobile_device())
784 <div class="menuedit">
785 <a href="'.$_base_path.'mods/_core/editor/edit_content_folder.php">
786 <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" />
788 '<a href="'.$_base_path.'mods/_core/editor/edit_content.php">
789 <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" />
791 '<a href="javascript:void(0)" onclick="javascript:switchEditMode();">
792 <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" />
796 $this->printMenu($parent_id, $depth, $path, $children, $truncate, $ignore_state);
798 // javascript for inline editor
800 <script type="text/javascript">
802 // only expand the content folder that has the current content page
806 function switchEditMode() {
807 title_edit = "'._AT("enter_edit_mode").'";
808 img_edit = "'.$_base_path.'images/medit.gif";
810 title_view = "'._AT("exit_edit_mode").'";
811 img_view = "'.$_base_path.'images/mlock.gif";
813 if (jQuery("#img_switch_edit_mode").attr("src") == img_edit)
815 jQuery("#img_switch_edit_mode").attr("src", img_view);
816 jQuery("#img_switch_edit_mode").attr("alt", title_view);
817 jQuery("#img_switch_edit_mode").attr("title", title_view);
821 { // refresh the content navigation to exit the edit mode
822 jQuery.post("'. $_base_path. 'mods/_core/content/refresh_content_nav.php", {},
823 function(data) {jQuery("#editable_table").replaceWith(data); initContentMenu();});
827 function inlineEditsSetup() {
828 jQuery("#editable_table").find(".inlineEdits").each(function() {
829 jQuery(this).text(jQuery(this).attr("title"));
832 var tableEdit = fluid.inlineEdits("#editable_table", {
834 text : ".inlineEdits",
835 editables : "span:has(span.inlineEdits)"
838 applyEditPadding: false,
841 afterFinishEdit : function (newValue, oldValue, editNode, viewNode) {
842 if (newValue != oldValue)
844 rtn = jQuery.post("'. $_base_path. 'mods/_core/content/menu_inline_editor_submit.php", { "field":viewNode.id, "value":newValue },
845 function(data) {}, "json");
851 jQuery(".fl-inlineEdit-edit").css("width", "80px")
861 /* @See tools/sitemap/index.php */
862 function printSiteMapMenu() {
868 $ignore_state = true;
871 $this->printMenu($parent_id, $depth, $path, $children, $truncate, $ignore_state, 'sitemap');
875 function printTOCMenu($cid, $top_num) {
878 $path = $top_num.'.';
881 $ignore_state = false;
884 $this->printMenu($parent_id, $depth, $path, $children, $truncate, $ignore_state);
887 /* @See index.php include/html/dropdowns/local_menu.inc.php */
888 function printSubMenu($cid, $top_num) {
891 $path = $top_num.'.';
894 $ignore_state = false;
897 $this->printMenu($parent_id, $depth, $path, $children, $truncate, $ignore_state);
900 /* @See include/html/menu_menu.inc.php */
901 /* Access: PRIVATE */
902 function printMenu($parent_id, $depth, $path, $children, $truncate, $ignore_state, $from = '') {
903 global $cid, $_my_uri, $_base_path, $rtl, $substr, $strlen;
906 if (!isset($temp_path)) {
908 $temp_path = $this->getContentPath($cid);
910 $temp_path = $this->getContentPath($_SESSION['s_cid']);
914 $highlighted = array();
915 if (is_array($temp_path)) {
916 foreach ($temp_path as $temp_path_item) {
917 $_SESSION['menu'][$temp_path_item['content_id']] = 1;
918 $highlighted[$temp_path_item['content_id']] = true;
924 $this->start = false;
927 if ( isset($this->_menu[$parent_id]) && is_array($this->_menu[$parent_id]) ) {
928 $top_level = $this->_menu[$parent_id];
930 $num_items = count($top_level);
932 echo '<div id="folder'.$parent_id.$from.'">'."\n";
934 foreach ($top_level as $garbage => $content) {
936 //tests do not have content id
937 $content['content_id'] = isset($content['content_id']) ? $content['content_id'] : '';
939 if (!$ignore_state) {
940 $link .= '<a name="menu'.$content['content_id'].'"></a>';
945 if ( (($_SESSION['s_cid'] != $content['content_id']) || ($_SESSION['s_cid'] != $cid)) && ($content['content_type'] == CONTENT_TYPE_CONTENT || $content['content_type'] == CONTENT_TYPE_WEBLINK))
946 { // non-current content nodes with content type "CONTENT_TYPE_CONTENT"
947 if (isset($highlighted[$content['content_id']])) {
952 //content test extension @harris
953 //if this is a test link.
954 if (isset($content['test_id'])){
955 $title_n_alt = $content['title'];
956 $in_link = 'mods/_standard/tests/test_intro.php?tid='.$content['test_id'];
957 $img_link = ' <img src="'.$_base_path.'images/check.gif" title="'.$title_n_alt.'" alt="'.$title_n_alt.'" />';
959 $in_link = 'content.php?cid='.$content['content_id'];
963 $full_title = $content['title'];
964 $link .= $img_link . ' <a href="'.$_base_path.url_rewrite($in_link).'" title="';
965 $base_title_length = 29;
966 if ($_SESSION['prefs']['PREF_NUMBERING']) {
967 $base_title_length = 24;
970 $link .= $content['title'].'">';
972 if ($truncate && ($strlen($content['title']) > ($base_title_length-$depth*4)) ) {
973 $content['title'] = htmlspecialchars(rtrim($substr(htmlspecialchars_decode($content['title']), 0, ($base_title_length-$depth*4)-4))).'...';
976 if (isset($content['test_id'])) {
977 $link .= $content['title'];
979 $link .= '<span class="inlineEdits" id="menu-'.$content['content_id'].'" title="'.$full_title.'">';
980 if($_SESSION['prefs']['PREF_NUMBERING']){
981 $link .= $path.$counter;
983 $link .= ' '.$content['title'].'</span>';
988 $link .= '</strong>';
991 // instructors have privilege to delete content
992 if (authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN) && !isset($content['test_id']) && !is_mobile_device()) {
993 $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").'" style="border:0" height="10" /></a>';
997 { // current content page & nodes with content type "CONTENT_TYPE_FOLDER"
998 $base_title_length = 33;
999 if ($_SESSION['prefs']['PREF_NUMBERING']) {
1000 $base_title_length = 26;
1003 if (isset($highlighted[$content['content_id']])) {
1004 $link .= '<strong>';
1008 if ($content['content_type'] == CONTENT_TYPE_CONTENT || $content['content_type'] == CONTENT_TYPE_WEBLINK)
1009 { // current content page
1010 $full_title = $content['title'];
1011 $link .= '<a href="'.$_my_uri.'"><img src="'.$_base_path.'images/clr.gif" alt="'._AT('you_are_here').': ';
1012 if($_SESSION['prefs']['PREF_NUMBERING']){
1013 $link .= $path.$counter;
1015 $link .= $content['title'].'" height="1" width="1" border="0" /></a><strong style="color:red" title="'.$content['title'].'">'."\n";
1016 if ($truncate && ($strlen($content['title']) > ($base_title_length-$depth*4)) ) {
1017 $content['title'] = htmlspecialchars(rtrim($substr(htmlspecialchars_decode($content['title']), 0, ($base_title_length-$depth*4)-4))).'...';
1019 $link .= '<a name="menu'.$content['content_id'].'"></a><span class="inlineEdits" id="menu-'.$content['content_id'].'" title="'.$full_title.'">';
1020 if($_SESSION['prefs']['PREF_NUMBERING']){
1021 $link .= $path.$counter;
1023 $link .=' '.$content['title'].'</span></strong>';
1025 // instructors have privilege to delete content
1026 if (authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN) && !is_mobile_device()) {
1027 $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").'" style="border:0" height="10" /></a>';
1031 { // nodes with content type "CONTENT_TYPE_FOLDER"
1032 $full_title = $content['title'];
1033 if (authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN) && !is_mobile_device()) {
1034 $link .= '<a href="'.$_base_path."mods/_core/editor/edit_content_folder.php?cid=".$content['content_id'].'" title="'.$full_title. _AT('click_edit').'">'."\n";
1037 $link .= '<span style="cursor:pointer" onclick="javascript: ATutor.course.toggleFolder(\''.$content['content_id'].$from.'\', \''._AT('expand').'\', \''._AT('collapse').'\', '.$this->course_id.'); ">'."\n";
1040 if ($truncate && ($strlen($content['title']) > ($base_title_length-$depth*4)) ) {
1041 $content['title'] = htmlspecialchars(rtrim($substr(htmlspecialchars_decode($content['title']), 0, ($base_title_length-$depth*4)-4))).'...';
1043 if (isset($content['test_id']))
1044 $link .= $content['title'];
1046 $link .= '<span class="inlineEdits" id="menu-'.$content['content_id'].'" title="'.$full_title.'">';
1047 if($_SESSION['prefs']['PREF_NUMBERING']){
1048 $link .= $path.$counter;
1050 $link .= ' '.$content['title'].'</span>';
1052 if (authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN) && !is_mobile_device()) {
1053 $link .= '</a>'."\n";
1056 $link .= '</span>'."\n";
1059 // instructors have privilege to delete content
1060 if (authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN) && !is_mobile_device()) {
1061 $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").'" style="border:0" height="10" /></a>';
1067 $link .= '</strong>';
1071 if ($ignore_state) {
1077 if ( isset($this->_menu[$content['content_id']]) && is_array($this->_menu[$content['content_id']]) ) {
1079 for ($i=0; $i<$depth; $i++) {
1080 if ($children[$i] == 1) {
1081 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_vertline.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
1083 echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
1087 if (($counter == $num_items) && ($depth > 0)) {
1088 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_end.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
1089 $children[$depth] = 0;
1090 } else if ($counter == $num_items) {
1091 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_end.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
1092 $children[$depth] = 0;
1094 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_split.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
1095 $children[$depth] = 1;
1098 if ($_SESSION['s_cid'] == $content['content_id']) {
1099 if (is_array($this->_menu[$content['content_id']])) {
1100 $_SESSION['menu'][$content['content_id']] = 1;
1104 if (isset($_SESSION['menu'][$content['content_id']]) && $_SESSION['menu'][$content['content_id']] == 1) {
1106 echo '<a href="javascript:void(0)" onclick="javascript: ATutor.course.toggleFolder(\''.$content['content_id'].$from.'\', \''._AT('expand').'\', \''._AT('collapse').'\', '.$this->course_id.'); "><img src="'.$_base_path.'images/tree/tree_collapse.gif" 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";
1109 echo '<a href="'.$_my_uri.'collapse='.$content['content_id'].'">'."\n";
1110 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_collapse.gif" 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";
1115 echo '<a href="javascript:void(0)" onclick="javascript: ATutor.course.toggleFolder(\''.$content['content_id'].$from.'\', \''._AT('expand').'\', \''._AT('collapse').'\', '.$this->course_id.'); "><img src="'.$_base_path.'images/tree/tree_collapse.gif" 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";
1118 echo '<a href="'.$_my_uri.'expand='.$content['content_id'].'">'."\n";
1119 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_expand.gif" 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.'); " />';
1125 /* doesn't have children */
1126 if ($counter == $num_items) {
1127 for ($i=0; $i<$depth; $i++) {
1128 if ($children[$i] == 1) {
1129 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_vertline.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
1131 echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
1134 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_end.gif" alt="" border="0" class="img-size-tree" />'."\n";
1136 for ($i=0; $i<$depth; $i++) {
1137 if ($children[$i] == 1) {
1138 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_vertline.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
1140 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_space.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
1143 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_split.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
1145 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_horizontal.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
1151 echo "\n<br /></span>\n\n";
1153 if ( $ignore_state || (isset($_SESSION['menu'][$content['content_id']]) && $_SESSION['menu'][$content['content_id']] == 1)) {
1157 $this->printMenu($content['content_id'],
1176 /* @See include/html/editor_tabs/properties.inc.php
1177 @See editor/arrange_content.php
1179 $print_type: "movable" or "related_content"
1181 function printActionMenu($menu, $parent_id, $depth, $path, $children, $print_type = 'movable') {
1183 global $cid, $_my_uri, $_base_path, $rtl;
1187 $top_level = $menu[$parent_id];
1189 if ( is_array($top_level) ) {
1191 $num_items = count($top_level);
1192 foreach ($top_level as $current_num => $content) {
1193 if (isset($content['test_id'])){
1197 $link = $buttons = '';
1201 if ($print_type == 'movable')
1203 if ($content['content_id'] == $_POST['moved_cid']) {
1204 $radio_selected = ' checked="checked" ';
1207 $radio_selected = '';
1210 $buttons = '<td>'."\n".
1212 ' <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";
1214 if ($current_num + 1 == count($top_level))
1215 $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";
1217 $buttons .= ' </small>'."\n".
1221 if ($content['content_type'] == CONTENT_TYPE_FOLDER)
1222 $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']).'" />';
1224 $buttons .= ' ';
1226 $buttons .= '</td>'."\n".
1227 '<td><input name="moved_cid" value="'.$content['content_id'].'" type="radio" id="r'.$content['content_id'].'" '.$radio_selected .'/></td>'."\n";
1230 $buttons .= '<td>'."\n";
1231 if ($print_type == "related_content")
1233 if ($content['content_type'] == CONTENT_TYPE_CONTENT || $content['content_type'] == CONTENT_TYPE_WEBLINK)
1235 $link .= '<input type="checkbox" name="related[]" value="'.$content['content_id'].'" id="r'.$content['content_id'].'" ';
1236 if (isset($_POST['related']) && in_array($content['content_id'], $_POST['related'])) {
1237 $link .= ' checked="checked"';
1239 $link .= ' />'."\n";
1243 if ($content['content_type'] == CONTENT_TYPE_FOLDER)
1245 $link .= '<img src="'.$_base_path.'images/folder.gif" />';
1247 $link .= ' <label for="r'.$content['content_id'].'">'.$content['title'].'</label>'."\n";
1249 if ( is_array($menu[$content['content_id']]) && !empty($menu[$content['content_id']]) ) {
1252 for ($i=0; $i<$depth; $i++) {
1253 if ($children[$i] == 1) {
1256 if ($end && ($i==0)) {
1257 echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />';
1259 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_vertline.gif" alt="" border="0" width="16" height="16" />';
1262 echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />';
1266 if (($counter == $num_items) && ($depth > 0)) {
1267 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_end.gif" alt="" border="0" width="16" height="16" />';
1268 $children[$depth] = 0;
1271 if (($num_items == $counter) && ($parent_id == 0)) {
1272 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_end.gif" alt="" border="0" width="16" height="16" />';
1275 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_split.gif" alt="" border="0" width="16" height="16" />';
1277 $children[$depth] = 1;
1280 if ($_SESSION['s_cid'] == $content['content_id']) {
1281 if (is_array($menu[$content['content_id']])) {
1282 $_SESSION['menu'][$content['content_id']] = 1;
1286 if ($_SESSION['menu'][$content['content_id']] == 1) {
1287 echo '<img src="'.$_base_path.'images/tree/tree_disabled.gif" alt="'._AT('toggle_disabled').'" border="0" width="16" height="16" title="'._AT('toggle_disabled').'" />';
1290 echo '<img src="'.$_base_path.'images/tree/tree_disabled.gif" alt="'._AT('toggle_disabled').'" border="0" width="16" height="16" title="'._AT('toggle_disabled').'" />';
1294 /* doesn't have children */
1295 if ($counter == $num_items) {
1298 for ($i=0; $i<$depth; $i++) {
1299 if ($children[$i] == 1) {
1300 if ($end && ($i == 0)) {
1301 echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />';
1303 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_vertline.gif" alt="" border="0" width="16" height="16" />';
1306 echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />';
1312 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_end.gif" alt="" border="0" />';
1317 for ($i=0; $i<$depth; $i++) {
1318 if ($children[$i] == 1) {
1319 if ($end && !$print) {
1321 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_space.gif" alt="" border="0" width="16" height="16" />';
1323 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_vertline.gif" alt="" border="0" width="16" height="16" />';
1326 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_space.gif" alt="" border="0" width="16" height="16" />';
1334 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_split.gif" alt="" border="0" width="16" height="16" />';
1336 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_horizontal.gif" alt="" border="0" width="16" height="16" />';
1340 if($_SESSION['prefs']['PREF_NUMBERING']){
1341 echo $path.$counter;
1346 echo '</small></td>'."\n".'</tr>'."\n";
1348 $this->printActionMenu($menu,
1349 $content['content_id'],
1361 /* 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 */
1362 /* finds the max(timestamp) of all parents and returns that, true if less than now */
1363 /* Access: public */
1364 function isReleased($cid) {
1365 if ($this->_menu_info[$cid]['content_parent_id'] == 0) {
1366 // this $cid has no parent, so we check its release date directly
1367 if ($this->_menu_info[$cid]['u_release_date'] <= time()) {
1368 // yup! it's released
1371 // nope! not released
1372 return $this->_menu_info[$cid]['u_release_date'];
1375 // this is a sub page, need to check ALL its parents
1376 $parent = $this->isReleased($this->_menu_info[$cid]['content_parent_id']); // recursion
1378 if ($parent !== TRUE && $parent > $this->_menu_info[$cid]['u_release_date']) {
1380 } else if ($this->_menu_info[$cid]['u_release_date'] <= time()) {
1383 return $this->_menu_info[$cid]['u_release_date'];
1387 /* returns the first test_id if this page has pre-test(s) to be passed,
1388 * or is under a page that has pre-test(s) to be passed,
1389 * 0 if has no pre-test(s) to be passed
1390 * -1 if one of the pre-test(s) has expired, the content should not be displayed in this case
1393 function getPretest($cid) {
1394 $this_pre_test_id = $this->getOnePretest($cid);
1396 if ($this->_menu_info[$cid]['content_parent_id'] == 0) {
1397 // this $cid has no parent, so we check its release date directly
1398 return $this_pre_test_id;
1401 // this is a sub page, need to check ALL its parents
1402 $parent_pre_test_id = $this->getOnePretest($this->_menu_info[$cid]['content_parent_id']);
1404 if ($this_pre_test_id > 0 || $this_pre_test_id == -1)
1405 return $this_pre_test_id;
1406 else if ($parent_pre_test_id > 0 || $parent_pre_test_id == -1)
1407 return $parent_pre_test_id;
1412 /* returns the first test_id if this content has pre-test(s) to be passed,
1413 * 0 if has no pre-test(s) to be passed
1414 * -1 if one of the pre-test(s) has expired, the content should not be displayed in this case
1417 function getOnePretest($cid) {
1419 include_once(AT_INCLUDE_PATH.'../mods/_standard/tests/lib/test_result_functions.inc.php');
1421 $sql = "SELECT *, UNIX_TIMESTAMP(t.start_date) AS start_date, UNIX_TIMESTAMP(t.end_date) AS end_date
1422 FROM ".TABLE_PREFIX."tests t, ".TABLE_PREFIX."content_prerequisites cp
1423 WHERE cp.content_id=".$cid."
1424 AND cp.type = '".CONTENT_PRE_TEST."'
1425 AND cp.item_id=t.test_id";
1426 $result= mysql_query($sql, $db);
1428 while ($row = mysql_fetch_assoc($result))
1430 // check to make sure we can access this test
1431 if (!$row['guests'] && ($_SESSION['enroll'] == AT_ENROLL_NO || $_SESSION['enroll'] == AT_ENROLL_ALUMNUS)) {
1432 $msg->addInfo('NOT_ENROLLED');
1435 if (!$row['guests'] && !authenticate_test($row['test_id'])) {
1436 $msg->addInfo(array('PRETEST_NO_PRIV',$row['title']));
1439 // if the test is not release, not allow student to view the content
1440 if ($row['start_date'] > time() || $row['end_date'] < time()) {
1441 $msg->addInfo(array('PRETEST_EXPIRED',$row['title']));
1445 $sql = "SELECT tr.result_id, count(*) num_of_questions, sum(ta.score) score, sum(tqa.weight) total_weight
1446 FROM ".TABLE_PREFIX."tests_results tr, ".TABLE_PREFIX."tests_answers ta, ".TABLE_PREFIX."tests_questions_assoc tqa
1447 WHERE tr.test_id = ".$row['test_id']."
1448 AND tr.member_id = ".$_SESSION['member_id']."
1449 AND tr.result_id = ta.result_id
1450 AND tr.test_id = tqa.test_id
1451 AND ta.question_id = tqa.question_id
1452 GROUP BY tr.result_id";
1453 $result_score = mysql_query($sql, $db);
1455 $num_of_attempts = 0;
1456 while ($row_score = mysql_fetch_assoc($result_score))
1458 // skip the test when:
1459 // 1. no pass score is defined. this is a survey.
1460 // 2. the student has passed the test
1461 // 3. the test has no question
1462 if (($row['passscore'] == 0 && $row['passpercent'] == 0) ||
1463 $row_score['num_of_questions'] == 0 ||
1464 ($row['passscore']<>0 && $row_score['score']>=$row['passscore']) ||
1465 ($row['passpercent']<>0 && ($row_score['score']/$row_score['total_weight']*100)>=$row['passpercent']))
1471 if ($row['num_takes'] != AT_TESTS_TAKE_UNLIMITED && $num_of_attempts >= $row['num_takes'])
1473 $msg->addInfo(array('PRETEST_FAILED',$row['title']));
1476 return $row['test_id'];
1482 * Return true if this content page allows export, else false.
1483 * @param int content id
1484 * @return true if 'allow_test_export'==1 || is instructor || oauth export into Transformable
1486 function allowTestExport($content_id){
1487 if (isset($_SESSION['is_admin']) || (isset($_REQUEST['m']) && isset($_REQUEST['c']))) {
1490 $sql = "SELECT allow_test_export FROM ".TABLE_PREFIX."content WHERE content_id=$content_id";
1491 $result = mysql_query($sql, $this->db);
1492 if ($row = mysql_fetch_assoc($result)){
1493 if ($row['allow_test_export'] == 1){
1502 * This function returns an array of content tools' shortcuts
1504 * @param: $content_row: an array of the current content information
1505 * @return: an array of all the tool shortcuts that apply to the current content or content folder
1507 public static function getToolShortcuts($content_row)
1509 global $_base_href, $contentManager;
1511 $shortcuts = array();
1512 if (( ($content_row['r_date'] <= $content_row['n_date'])
1513 && ((!$content_row['content_parent_id'] && ($_SESSION['packaging'] == 'top'))
1514 || ($_SESSION['packaging'] == 'all'))
1515 ) || authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN)) {
1516 $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');
1519 if (authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN)) {
1520 if ($content_row['content_type'] == CONTENT_TYPE_CONTENT) {
1521 $shortcuts[] = array(
1522 'title' => _AT('edit_this_page'),
1523 'url' => $_base_href . 'mods/_core/editor/edit_content.php?cid='.$content_row['content_id'],
1524 'icon' => $_base_href . 'images/medit.gif');
1526 $shortcuts[] = array(
1527 'title' => _AT('add_sibling_folder'),
1528 'url' => $_base_href.'mods/_core/editor/edit_content_folder.php?pid='.$contentManager->_menu_info[$content_row['content_id']]['content_parent_id'],
1529 'icon' => $_base_href . 'images/folder_new_sibling.gif');
1531 if ($content_row['content_type'] == CONTENT_TYPE_FOLDER) {
1532 $shortcuts[] = array(
1533 'title' => _AT('add_sub_folder'),
1534 'url' => $_base_href . 'mods/_core/editor/edit_content_folder.php?pid='.$content_row['content_id'],
1535 'icon' => $_base_href . 'images/folder_new_sub.gif');
1538 $shortcuts[] = array(
1539 'title' => _AT('add_sibling_page'),
1540 'url' => $_base_href.'mods/_core/editor/edit_content.php?pid='.$contentManager->_menu_info[$content_row['content_id']]['content_parent_id'],
1541 'icon' => $_base_href . 'images/page_add_sibling.gif');
1543 if ($content_row['content_type'] == CONTENT_TYPE_CONTENT) {
1544 $shortcuts[] = array(
1545 'title' => _AT('delete_this_page'),
1546 'url' => $_base_href . 'mods/_core/editor/delete_content.php?cid='.$content_row['content_id'],
1547 'icon' => $_base_href . 'images/page_delete.gif');
1549 else if ($content_row['content_type'] == CONTENT_TYPE_FOLDER) {
1550 $shortcuts[] = array(
1551 'title' => _AT('add_sub_page'),
1552 'url' => $_base_href . 'mods/_core/editor/edit_content.php?pid='.$content_row['content_id'],
1553 'icon' => $_base_href . 'images/page_add_sub.gif');
1554 $shortcuts[] = array(
1555 'title' => _AT('delete_this_folder'),
1556 'url' => $_base_href . 'mods/_core/editor/delete_content.php?cid='.$content_row['content_id'],
1557 'icon' => $_base_href . 'images/page_delete.gif');