2 /****************************************************************/
4 /****************************************************************/
5 /* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg */
6 /* Adaptive Technology Resource Centre / University of Toronto */
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 /****************************************************************/
39 function ContentManager(&$db, $course_id) {
41 $this->course_id = $course_id;
44 function initContent( ) {
45 if (!($this->course_id > 0)) {
48 $sql = "SELECT content_id, content_parent_id, ordering, title, UNIX_TIMESTAMP(release_date) AS u_release_date FROM ".TABLE_PREFIX."content WHERE course_id=$this->course_id ORDER BY content_parent_id, ordering";
49 $result = mysql_query($sql, $this->db);
51 /* x could be the ordering or even the content_id */
52 /* don't really need the ordering anyway. */
53 /* $_menu[content_parent_id][x] = array('content_id', 'ordering', 'title') */
56 /* number of content sections */
60 $_menu_info = array();
62 while ($row = mysql_fetch_assoc($result)) {
64 $_menu[$row['content_parent_id']][] = array('content_id'=> $row['content_id'],
65 'ordering' => $row['ordering'],
66 'title' => htmlspecialchars($row['title']));
68 $_menu_info[$row['content_id']] = array('content_parent_id' => $row['content_parent_id'],
69 'title' => htmlspecialchars($row['title']),
70 'ordering' => $row['ordering'],
71 'u_release_date' => $row['u_release_date']);
74 * add test content asscioations
75 * find associations per content page, and add it as a sublink.
78 $test_rs = $this->getContentTestsAssoc($row['content_id']);
79 while ($test_row = mysql_fetch_assoc($test_rs)){
80 $_menu[$row['content_id']][] = array( 'test_id' => $test_row['test_id'],
81 'title' => htmlspecialchars($test_row['title']));
83 // $_menu_info[$test_row['test_id']] = array( 'content_parent_id' => $row['content_id'],
84 // 'title' => htmlspecialchars($test_row['title']));
86 /* End of add test content asscioations */
88 if ($row['content_parent_id'] == 0) {
89 $max_depth[$row['content_id']] = 1;
91 $max_depth[$row['content_id']] = $max_depth[$row['content_parent_id']]+1;
95 $this->_menu = $_menu;
97 $this->_menu_info = $_menu_info;
99 $this->num_sections = $num_sections;
101 if (count($max_depth) > 1) {
102 $this->max_depth = max($max_depth);
104 $this->max_depth = 0;
107 $this->content_length = count($_menu[0]);
111 function getContent($parent_id=-1, $length=-1) {
112 if ($parent_id == -1) {
113 $my_menu_copy = $this->_menu;
115 $my_menu_copy[0] = array_slice($my_menu_copy[0], 0, $length);
117 return $my_menu_copy;
119 return $this->_menu[$parent_id];
123 function &getContentPath($content_id) {
126 $path[] = array('content_id' => $content_id, 'title' => $this->_menu_info[$content_id]['title']);
128 $this->getContentPathRecursive($content_id, $path);
130 $path = array_reverse($path);
135 function getContentPathRecursive($content_id, &$path) {
136 $parent_id = $this->_menu_info[$content_id]['content_parent_id'];
138 if ($parent_id > 0) {
139 $path[] = array('content_id' => $parent_id, 'title' => $this->_menu_info[$parent_id]['title']);
140 $this->getContentPathRecursive($parent_id, $path);
145 function addContent($course_id, $content_parent_id, $ordering, $title, $text, $keywords, $related, $formatting, $release_date, $head = '', $use_customized_head = 0, $test_message = '', $allow_test_export = 1) {
147 if (!authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN) && ($_SESSION['course_id'] != -1)) {
151 // shift the new neighbouring content down
152 $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]";
153 $result = mysql_query($sql, $this->db);
155 /* main topics all have minor_num = 0 */
156 $sql = "INSERT INTO ".TABLE_PREFIX."content
180 $use_customized_head,
186 $allow_test_export)";
188 $err = mysql_query($sql, $this->db);
190 /* insert the related content */
191 $sql = "SELECT LAST_INSERT_ID() AS insert_id";
192 $result = mysql_query($sql, $this->db);
193 $row = mysql_fetch_assoc($result);
194 $cid = $row['insert_id'];
197 if (is_array($related)) {
198 foreach ($related as $x => $related_content_id) {
199 $related_content_id = intval($related_content_id);
201 if ($related_content_id != 0) {
205 $sql .= '('.$cid.', '.$related_content_id.')';
206 $sql .= ', ('.$related_content_id.', '.$cid.')';
211 $sql = 'INSERT INTO '.TABLE_PREFIX.'related_content VALUES '.$sql;
212 $result = mysql_query($sql, $this->db);
220 function editContent($content_id, $title, $text, $keywords, $new_content_ordering, $related, $formatting, $new_content_parent_id, $release_date, $head, $use_customized_head, $test_message, $allow_test_export) {
221 if (!authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN)) {
225 /* first get the content to make sure it exists */
226 $sql = "SELECT ordering, content_parent_id FROM ".TABLE_PREFIX."content WHERE content_id=$content_id AND course_id=$_SESSION[course_id]";
227 $result = mysql_query($sql, $this->db);
228 if (!($row = mysql_fetch_assoc($result)) ) {
231 $old_ordering = $row['ordering'];
232 $content_parent_id = $row['content_parent_id'];
233 if (($content_parent_id != $new_content_parent_id) || ($old_ordering != $new_content_ordering)) {
234 // remove the gap left by the moved content
235 $sql = "UPDATE ".TABLE_PREFIX."content SET ordering=ordering-1 WHERE ordering>=$old_ordering AND content_parent_id=$content_parent_id AND content_id<>$content_id AND course_id=$_SESSION[course_id]";
236 $result = mysql_query($sql, $this->db);
238 // shift the new neighbouring content down
239 $sql = "UPDATE ".TABLE_PREFIX."content SET ordering=ordering+1 WHERE ordering>=$new_content_ordering AND content_parent_id=$new_content_parent_id AND content_id<>$content_id AND course_id=$_SESSION[course_id]";
240 $result = mysql_query($sql, $this->db);
243 /* update the title, text of the newly moved (or not) content */
244 $sql = "UPDATE ".TABLE_PREFIX."content SET title='$title', head='$head', use_customized_head=$use_customized_head, text='$text', keywords='$keywords', formatting=$formatting, content_parent_id=$new_content_parent_id, ordering=$new_content_ordering, revision=revision+1, last_modified=NOW(), release_date='$release_date', test_message='$test_message', allow_test_export=$allow_test_export WHERE content_id=$content_id AND course_id=$_SESSION[course_id]";
245 $result = mysql_query($sql, $this->db);
247 /* update the related content */
248 $result = mysql_query("DELETE FROM ".TABLE_PREFIX."related_content WHERE content_id=$content_id OR related_content_id=$content_id", $this->db);
250 if (is_array($related)) {
251 foreach ($related as $x => $related_content_id) {
252 $related_content_id = intval($related_content_id);
254 if ($related_content_id != 0) {
258 $sql .= '('.$content_id.', '.$related_content_id.')';
259 $sql .= ', ('.$related_content_id.', '.$content_id.')';
264 /* delete the old related content */
265 $result = mysql_query("DELETE FROM ".TABLE_PREFIX."related_content WHERE content_id=$content_id OR related_content_id=$content_id", $this->db);
267 /* insert the new, and the old related content again */
268 $sql = 'INSERT INTO '.TABLE_PREFIX.'related_content VALUES '.$sql;
269 $result = mysql_query($sql, $this->db);
275 function deleteContent($content_id) {
276 if (!authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN)) {
280 /* check if exists */
281 $sql = "SELECT ordering, content_parent_id FROM ".TABLE_PREFIX."content WHERE content_id=$content_id AND course_id=$_SESSION[course_id]";
282 $result = mysql_query($sql, $this->db);
283 if (!($row = @mysql_fetch_assoc($result)) ) {
286 $ordering = $row['ordering'];
287 $content_parent_id = $row['content_parent_id'];
289 /* check if this content has sub content */
290 $children = $this->_menu[$content_id];
292 if (is_array($children) && (count($children)>0) ) {
293 /* delete its children recursively first*/
294 foreach ($children as $x => $info) {
295 $this->deleteContentRecursive($info['content_id']);
299 /* delete this content page */
300 $sql = "DELETE FROM ".TABLE_PREFIX."content WHERE content_id=$content_id AND course_id=$_SESSION[course_id]";
301 $result = mysql_query($sql, $this->db);
303 /* delete this content from member tracking page */
304 $sql = "DELETE FROM ".TABLE_PREFIX."member_track WHERE content_id=$content_id AND course_id=$_SESSION[course_id]";
305 $result = mysql_query($sql, $this->db);
307 $sql = "DELETE FROM ".TABLE_PREFIX."related_content WHERE content_id=$content_id OR related_content_id=$content_id";
308 $result = mysql_query($sql, $this->db);
310 /* delete the content tests association */
311 $sql = "DELETE FROM ".TABLE_PREFIX."content_tests_assoc WHERE content_id=$content_id";
312 $result = mysql_query($sql, $this->db);
314 /* Delete all AccessForAll contents */
315 require_once(AT_INCLUDE_PATH.'classes/A4a/A4a.class.php');
316 $a4a = new A4a($content_id);
319 /* re-order the rest of the content */
320 $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]";
321 $result = mysql_query($sql, $this->db);
322 /* end moving block */
324 /* remove the "resume" to this page, b/c it was deleted */
325 $sql = "UPDATE ".TABLE_PREFIX."course_enrollment SET last_cid=0 WHERE course_id=$_SESSION[course_id] AND last_cid=$content_id";
326 $result = mysql_query($sql, $this->db);
332 /* private. call from deleteContent only. */
333 function deleteContentRecursive($content_id) {
334 /* check if this content has sub content */
335 $children = $this->_menu[$content_id];
337 if (is_array($children) && (count($children)>0) ) {
338 /* delete its children recursively first*/
339 foreach ($children as $x => $info) {
340 $this->deleteContent($info['content_id']);
344 /* delete this content page */
345 $sql = "DELETE FROM ".TABLE_PREFIX."content WHERE content_id=$content_id AND course_id=$_SESSION[course_id]";
346 $result = mysql_query($sql, $this->db);
348 /* delete this content from member tracking page */
349 $sql = "DELETE FROM ".TABLE_PREFIX."member_track WHERE content_id=$content_id";
350 $result = mysql_query($sql, $this->db);
352 $sql = "DELETE FROM ".TABLE_PREFIX."related_content WHERE content_id=$content_id OR related_content_id=$content_id";
353 $result = mysql_query($sql, $this->db);
355 /* delete the content tests association */
356 $sql = "DELETE FROM ".TABLE_PREFIX."content_tests_assoc WHERE content_id=$content_id";
357 $result = mysql_query($sql, $this->db);
360 function & getContentPage($content_id) {
361 $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 WHERE content_id=$content_id AND course_id=$this->course_id";
362 $result = mysql_query($sql, $this->db);
367 /* @See editor/edit_content.php include/html/dropdowns/related_topics.inc.php include/lib/editor_tabs_functions.inc.php */
368 function getRelatedContent($content_id, $all=false) {
369 if ($content_id == 0) {
372 if ($content_id == '') {
375 $related_content = array();
378 $sql = "SELECT * FROM ".TABLE_PREFIX."related_content WHERE content_id=$content_id OR related_content_id=$content_id";
380 $sql = "SELECT * FROM ".TABLE_PREFIX."related_content WHERE content_id=$content_id";
382 $result = mysql_query($sql, $this->db);
384 while ($row = mysql_fetch_assoc($result)) {
385 if ($row['related_content_id'] != $content_id) {
386 $related_content[] = $row['related_content_id'];
388 $related_content[] = $row['content_id'];
392 return $related_content;
396 * Return a list of tests associated with the selected content
397 * @param int the content id that all tests are associated with it.
398 * @return array list of tests
402 function & getContentTestsAssoc($content_id){
403 $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";
404 $result = mysql_query($sql, $this->db);
409 function & cleanOutput($value) {
410 return stripslashes(htmlspecialchars($value));
414 /* @See include/html/editor_tabs/properties.inc.php */
416 function getNumSections() {
417 return $this->num_sections;
421 function getMaxDepth() {
422 return $this->max_depth;
426 function getContentLength() {
427 return $this->content_length;
430 /* @See include/html/dropdowns/local_menu.inc.php */
431 function getLocationPositions($parent_id, $content_id) {
432 $siblings = $this->getContent($parent_id);
433 for ($i=0;$i<count($siblings); $i++){
434 if ($siblings[$i]['content_id'] == $content_id) {
441 /* Access: Private */
442 function getNumbering($content_id) {
443 $path = $this->getContentPath($content_id);
446 foreach ($path as $page) {
447 $num = $this->getLocationPositions($parent, $page['content_id']) +1;
448 $parent = $page['content_id'];
449 $numbering .= $num.'.';
451 $numbering = substr($numbering, 0, -1);
456 /* Access: Private */
457 function getPreviousContent($content_id, $order=0) {
458 $myParent = $this->_menu_info[$content_id]['content_parent_id'];
459 $myOrder = $this->_menu_info[$content_id]['ordering'];
461 if (isset($this->_menu[$myParent][$myOrder-2]) && ($this->_menu[$myParent][$myOrder-2] != '') && ($order==0)) {
462 // has sibling: checking if sibling has children
464 $mySibling = $this->_menu[$myParent][$myOrder-2];
466 if ( isset($this->_menu[$mySibling['content_id']]) && is_array($this->_menu[$mySibling['content_id']]) && ($order==0) ) {
467 $num_children = count($this->_menu[$mySibling['content_id']]);
469 // sibling has $num_children children
470 return($this->getPreviousContent($this->_menu[$mySibling['content_id']][$num_children-1]['content_id'], 1));
473 // sibling has no children. return it
474 return($this->_menu[$myParent][$myOrder-2]);
478 if ($myParent == 0) {
479 /* we're at the top */
483 /* No more siblings */
485 return(array('content_id' => $myParent,
486 'ordering' => $this->_menu_info[$myParent]['ordering'],
487 'title' => $this->_menu_info[$myParent]['title']));
489 if ( isset($this->_menu[$content_id]) && is_array($this->_menu[$content_id]) ) {
490 $num_children = count($this->_menu[$content_id]);
491 return ($this->getPreviousContent($this->_menu[$content_id][$num_children-1]['content_id'], 1));
495 return(array('content_id' => $content_id,
496 'ordering' => $this->_menu_info[$content_id]['ordering'],
497 'title' => $this->_menu_info[$content_id]['title']));
503 /* Access: Private */
504 function getNextContent($content_id, $order=0) {
505 if (!$content_id) { return; }
507 $myParent = $this->_menu_info[$content_id]['content_parent_id'];
508 $myOrder = $this->_menu_info[$content_id]['ordering'];
509 /* if this content has children, then take the first one. */
510 if ( isset($this->_menu[$content_id]) && is_array($this->_menu[$content_id]) && ($order==0) ) {
512 return($this->_menu[$content_id][0]);
515 if (isset($this->_menu[$myParent][$myOrder]) && $this->_menu[$myParent][$myOrder] != '') {
517 return($this->_menu[$myParent][$myOrder]);
519 /* No more siblings */
520 if ($myParent != 0) {
521 return($this->getNextContent($myParent, 1));
527 /* @See include/header.inc.php */
528 function generateSequenceCrumbs($cid) {
531 $sequence_links = array();
533 $first = $this->getNextContent(0); // get first
534 if ($_SESSION['prefs']['PREF_NUMBERING'] && $first) {
535 $first['title'] = $this->getNumbering($first['content_id']).' '.$first['title'];
538 $first['url'] = $_base_path.url_rewrite('content.php?cid='.$first['content_id']);
539 $sequence_links['first'] = $first;
542 if (!$cid && $_SESSION['s_cid']) {
543 $resume['title'] = $this->_menu_info[$_SESSION['s_cid']]['title'];
545 if ($_SESSION['prefs']['PREF_NUMBERING']) {
546 $resume['title'] = $this->getNumbering($_SESSION['s_cid']).' ' . $resume['title'];
549 $resume['url'] = $_base_path.url_rewrite('content.php?cid='.$_SESSION['s_cid']);
551 $sequence_links['resume'] = $resume;
554 $previous = $this->getPreviousContent($cid);
556 $next = $this->getNextContent($cid ? $cid : 0);
558 if ($_SESSION['prefs']['PREF_NUMBERING']) {
559 $previous['title'] = $this->getNumbering($previous['content_id']).' '.$previous['title'];
560 $next['title'] = $this->getNumbering($next['content_id']).' '.$next['title'];
563 $next['url'] = $_base_path.url_rewrite('content.php?cid='.$next['content_id']);
564 if (isset($previous['content_id'])) {
565 $previous['url'] = $_base_path.url_rewrite('content.php?cid='.$previous['content_id']);
568 if (isset($previous['content_id'])) {
569 $sequence_links['previous'] = $previous;
571 $previous['url'] = $_base_path . url_rewrite('index.php');
572 $previous['title'] = _AT('home');
573 $sequence_links['previous'] = $previous;
575 if (!empty($next['content_id'])) {
576 $sequence_links['next'] = $next;
580 return $sequence_links;
583 /* @See include/html/dropdowns/menu_menu.inc.php */
584 function printMainMenu( ) {
590 $ignore_state = false;
593 $this->printMenu($parent_id, $depth, $path, $children, $truncate, $ignore_state);
596 /* @See tools/sitemap/index.php */
597 function printSiteMapMenu() {
603 $ignore_state = true;
606 $this->printMenu($parent_id, $depth, $path, $children, $truncate, $ignore_state);
610 function printTOCMenu($cid, $top_num) {
613 $path = $top_num.'.';
616 $ignore_state = false;
619 $this->printMenu($parent_id, $depth, $path, $children, $truncate, $ignore_state);
622 /* @See index.php include/html/dropdowns/local_menu.inc.php */
623 function printSubMenu($cid, $top_num) {
626 $path = $top_num.'.';
629 $ignore_state = false;
632 $this->printMenu($parent_id, $depth, $path, $children, $truncate, $ignore_state);
635 /* @See include/html/menu_menu.inc.php */
636 /* Access: PRIVATE */
637 function printMenu($parent_id, $depth, $path, $children, $truncate, $ignore_state) {
639 global $cid, $_my_uri, $_base_path, $rtl, $substr, $strlen;
642 if (!isset($temp_path)) {
644 $temp_path = $this->getContentPath($cid);
646 $temp_path = $this->getContentPath($_SESSION['s_cid']);
650 $highlighted = array();
651 if (is_array($temp_path)) {
652 foreach ($temp_path as $temp_path_item) {
653 $_SESSION['menu'][$temp_path_item['content_id']] = 1;
654 $highlighted[$temp_path_item['content_id']] = true;
660 $this->start = false;
663 if ( isset($this->_menu[$parent_id]) && is_array($this->_menu[$parent_id]) ) {
664 $top_level = $this->_menu[$parent_id];
666 $num_items = count($top_level);
667 foreach ($top_level as $garbage => $content) {
669 //tests do not have content id
670 $content['content_id'] = isset($content['content_id']) ? $content['content_id'] : '';
672 if (!$ignore_state) {
673 $link .= '<a name="menu'.$content['content_id'].'"></a>';
678 if ( ($_SESSION['s_cid'] != $content['content_id']) || ($_SESSION['s_cid'] != $cid) ) {
679 if (isset($highlighted[$content['content_id']])) {
684 //content test extension @harris
685 //if this is a test link.
686 if (isset($content['test_id'])){
687 $title_n_alt = _AT('tests') . ' - ' . $content['title'];
688 $in_link = 'tools/test_intro.php?tid='.$content['test_id'];
689 $img_link = ' <img src="'.$_base_path.'images/check.gif" title="'.$title_n_alt.'" alt="'.$title_n_alt.'" />';
691 $in_link = 'content.php?cid='.$content['content_id'];
694 $link .= $img_link . ' <a href="'.$_base_path.url_rewrite($in_link).'" title="';
695 if ($_SESSION['prefs']['PREF_NUMBERING']) {
696 $link .= $path.$counter.' ';
699 $link .= $content['title'].'">';
701 if ($truncate && ($strlen($content['title']) > (28-$depth*4)) ) {
702 $content['title'] = rtrim($substr($content['title'], 0, (28-$depth*4)-4)).'...';
704 $link .= $content['title'];
707 $link .= '</strong>';
710 $link .= '<a href="'.$_my_uri.'"><img src="'.$_base_path.'images/clr.gif" alt="'._AT('you_are_here').': '.$content['title'].'" height="1" width="1" border="0" /></a><strong title="'.$content['title'].'">'."\n";
711 if ($truncate && ($strlen($content['title']) > (26-$depth*4)) ) {
712 $content['title'] = rtrim($substr($content['title'], 0, (26-$depth*4)-4)).'...';
714 $link .= trim($content['title']).'</strong>';
722 if ( isset($this->_menu[$content['content_id']]) && is_array($this->_menu[$content['content_id']]) ) {
724 for ($i=0; $i<$depth; $i++) {
725 if ($children[$i] == 1) {
726 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_vertline.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
728 echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
732 if (($counter == $num_items) && ($depth > 0)) {
733 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_end.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
734 $children[$depth] = 0;
735 } else if ($counter == $num_items) {
736 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_end.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
737 $children[$depth] = 0;
739 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_split.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
740 $children[$depth] = 1;
743 if ($_SESSION['s_cid'] == $content['content_id']) {
744 if (is_array($this->_menu[$content['content_id']])) {
745 $_SESSION['menu'][$content['content_id']] = 1;
749 if (isset($_SESSION['menu'][$content['content_id']]) && $_SESSION['menu'][$content['content_id']] == 1) {
751 echo '<img src="'.$_base_path.'images/tree/tree_disabled.gif" alt="'._AT('toggle_disabled').'" border="0" width="16" height="16" title="'._AT('toggle_disabled').'" class="img-size-tree" />'."\n";
754 echo '<a href="'.$_my_uri.'collapse='.$content['content_id'].'">'."\n";
755 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_collapse.gif" alt="'._AT('collapse').'" border="0" width="16" height="16" title="'._AT('collapse').' '.$content['title'].'" class="img-size-tree" />'."\n";
760 echo '<img src="'.$_base_path.'images/tree/tree_disabled.gif" alt="'._AT('toggle_disabled').'" border="0" width="16" height="16" title="'._AT('toggle_disabled').'" class="img-size-tree" />'."\n";
763 echo '<a href="'.$_my_uri.'expand='.$content['content_id'].'">'."\n";
764 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_expand.gif" alt="'._AT('expand').'" border="0" width="16" height="16" title="'._AT('expand').' '.$content['title'].'" class="img-size-tree" />';
770 /* doesn't have children */
771 if ($counter == $num_items) {
772 for ($i=0; $i<$depth; $i++) {
773 if ($children[$i] == 1) {
774 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_vertline.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
776 echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
779 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_end.gif" alt="" border="0" class="img-size-tree" />'."\n";
781 for ($i=0; $i<$depth; $i++) {
782 if ($children[$i] == 1) {
783 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_vertline.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
785 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_space.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
788 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_split.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
790 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_horizontal.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
793 if ($_SESSION['prefs']['PREF_NUMBERING']) {
801 if ( $ignore_state || (isset($_SESSION['menu'][$content['content_id']]) && $_SESSION['menu'][$content['content_id']] == 1)) {
805 $this->printMenu($content['content_id'],
821 /* @See include/html/editor_tabs/properties.inc.php */
822 function printMoveMenu($menu, $parent_id, $depth, $path, $children) {
824 global $cid, $_my_uri, $_base_path, $rtl;
826 static $end, $ignore;
828 $top_level = $menu[$parent_id];
830 if ( is_array($top_level) ) {
832 $num_items = count($top_level);
833 foreach ($top_level as $garbage => $content) {
834 if (isset($content['test_id'])){
842 if (($parent_id == $_POST['new_pid']) && ($content['ordering'] < $_POST['new_ordering'])) {
843 $text = _AT('before_topic', $content['title']);
845 } else if ($parent_id != $_POST['new_pid']) {
846 $text = _AT('before_topic', $content['title']);
849 $text = _AT('after_topic', $content['title']);
852 if ($ignore && ($_POST['cid'] > 0)) {
853 $buttons = '<td><small> </small></td><td><small> </small></td><td>';
854 } else if ($_POST['new_pid'] == $content['content_id']) {
855 $buttons = '<td align="center"><small><input type="image" name="move['.$parent_id.'_'.$content['ordering'].']" src="'.$_base_path.'images/'.$img.'" alt="'.$text.'" title="'.$text.'" style="height:1.5em; width:1.9em;" /></small></td><td><small> </small></td><td>';
858 $buttons = '<td align="center"><small><input type="image" name="move['.$parent_id.'_'.$content['ordering'].']" src="'.$_base_path.'images/'.$img.'" alt="'.$text.'" title="'.$text.'" style="height:1.5em; width:1.9em;" /></small></td><td><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']).'" /></td><td>';
862 if (( $content['content_id'] == $cid ) || ($content['content_id'] == -1)) {
864 $link .= '<strong>'.trim($_POST['title']).' '._AT('current_location').'</strong>';
865 $buttons = '<td colspan="2"><small> </small></td><td>';
867 $link .= '<input type="checkbox" name="related[]" value="'.$content['content_id'].'" id="r'.$content['content_id'].'" ';
868 if (isset($_POST['related']) && in_array($content['content_id'], $_POST['related'])) {
869 $link .= ' checked="checked"';
871 $link .= ' /><label for="r'.$content['content_id'].'">'.$content['title'].'</label>';
874 if ( is_array($menu[$content['content_id']]) && !empty($menu[$content['content_id']]) ) {
877 for ($i=0; $i<$depth; $i++) {
878 if ($children[$i] == 1) {
881 if ($end && ($i==0)) {
882 echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />';
884 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_vertline.gif" alt="" border="0" width="16" height="16" />';
887 echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />';
891 if (($counter == $num_items) && ($depth > 0)) {
892 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_end.gif" alt="" border="0" width="16" height="16" />';
893 $children[$depth] = 0;
896 if (($num_items == $counter) && ($parent_id == 0)) {
897 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_end.gif" alt="" border="0" width="16" height="16" />';
900 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_split.gif" alt="" border="0" width="16" height="16" />';
902 $children[$depth] = 1;
905 if ($_SESSION['s_cid'] == $content['content_id']) {
906 if (is_array($menu[$content['content_id']])) {
907 $_SESSION['menu'][$content['content_id']] = 1;
911 if ($_SESSION['menu'][$content['content_id']] == 1) {
912 echo '<img src="'.$_base_path.'images/tree/tree_disabled.gif" alt="'._AT('toggle_disabled').'" border="0" width="16" height="16" title="'._AT('toggle_disabled').'" />';
915 echo '<img src="'.$_base_path.'images/tree/tree_disabled.gif" alt="'._AT('toggle_disabled').'" border="0" width="16" height="16" title="'._AT('toggle_disabled').'" />';
919 /* doesn't have children */
920 if ($counter == $num_items) {
923 for ($i=0; $i<$depth; $i++) {
924 if ($children[$i] == 1) {
925 if ($end && ($i == 0)) {
926 echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />';
928 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_vertline.gif" alt="" border="0" width="16" height="16" />';
931 echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />';
937 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_end.gif" alt="" border="0" />';
942 for ($i=0; $i<$depth; $i++) {
943 if ($children[$i] == 1) {
944 if ($end && !$print) {
946 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_space.gif" alt="" border="0" width="16" height="16" />';
948 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_vertline.gif" alt="" border="0" width="16" height="16" />';
951 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_space.gif" alt="" border="0" width="16" height="16" />';
959 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_split.gif" alt="" border="0" width="16" height="16" />';
961 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_horizontal.gif" alt="" border="0" width="16" height="16" />';
964 echo '<small> '.$path.$counter;
968 echo '</small></td></tr>';
970 $this->printMoveMenu($menu,
971 $content['content_id'],
979 if ( $content['content_id'] == $cid ) {
987 /* 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 */
988 /* finds the max(timestamp) of all parents and returns that, true if less than now */
990 function isReleased($cid) {
991 if ($this->_menu_info[$cid]['content_parent_id'] == 0) {
992 // this $cid has no parent, so we check its release date directly
993 if ($this->_menu_info[$cid]['u_release_date'] <= time()) {
994 // yup! it's released
997 // nope! not released
998 return $this->_menu_info[$cid]['u_release_date'];
1001 // this is a sub page, need to check ALL its parents
1002 $parent = $this->isReleased($this->_menu_info[$cid]['content_parent_id']); // recursion
1004 if ($parent !== TRUE && $parent > $this->_menu_info[$cid]['u_release_date']) {
1006 } else if ($this->_menu_info[$cid]['u_release_date'] <= time()) {
1009 return $this->_menu_info[$cid]['u_release_date'];
1014 * Return true if this content page allows export, else false.
1015 * @param int content id
1016 * @return true if 'allow_test_export'==1 || is instructor
1018 function allowTestExport($content_id){
1019 if (isset($_SESSION['is_admin'])){
1022 $sql = "SELECT allow_test_export FROM ".TABLE_PREFIX."content WHERE content_id=$content_id";
1023 $result = mysql_query($sql, $this->db);
1024 if ($row = mysql_fetch_assoc($result)){
1025 if ($row['allow_test_export'] == 1){