(no commit message)
[atutor.git] / include / classes / ContentManager.class.php
1 <?php
2 /****************************************************************/
3 /* ATutor                                                                                                               */
4 /****************************************************************/
5 /* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
6 /* Adaptive Technology Resource Centre / University of Toronto  */
7 /* http://atutor.ca                                                                                             */
8 /*                                                              */
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 /****************************************************************/
13 // $Id$
14
15 class ContentManager
16 {
17         /* db handler   */
18         var $db;
19
20         /*      array           */
21         var $_menu;
22
23         /*      array           */
24         var $_menu_info;
25
26         /* int                  */
27         var $course_id;
28
29         // private
30         var $num_sections;
31
32         // private
33         var $max_depth;
34
35         // private
36         var $content_length;
37
38         /* constructor  */
39         function ContentManager(&$db, $course_id) {
40                 $this->db = $db;
41                 $this->course_id = $course_id;
42         }
43
44         function initContent( ) {
45                 if (!($this->course_id > 0)) {
46                         return;
47                 }
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);
50
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') */
54                 $_menu = array();
55
56                 /* number of content sections */
57                 $num_sections = 0;
58
59                 $max_depth = array();
60                 $_menu_info = array();
61
62                 while ($row = mysql_fetch_assoc($result)) {
63                         $num_sections++;
64                         $_menu[$row['content_parent_id']][] = array('content_id'=> $row['content_id'],
65                                                                                                                 'ordering'      => $row['ordering'], 
66                                                                                                                 'title'         => htmlspecialchars($row['title']));
67
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']);
72
73                         /* 
74                          * add test content asscioations
75                          * find associations per content page, and add it as a sublink.
76                          * @author harris
77                          */
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']));
82
83 //                              $_menu_info[$test_row['test_id']] = array(      'content_parent_id' => $row['content_id'],
84 //                                                                                                                      'title'                         => htmlspecialchars($test_row['title']));                               
85                         }
86                         /* End of add test content asscioations */
87
88                         if ($row['content_parent_id'] == 0) {
89                                 $max_depth[$row['content_id']] = 1;
90                         } else {
91                                 $max_depth[$row['content_id']] = $max_depth[$row['content_parent_id']]+1;
92                         }
93                 }
94
95                 $this->_menu = $_menu;
96
97                 $this->_menu_info =  $_menu_info;
98
99                 $this->num_sections = $num_sections;
100
101                 if (count($max_depth) > 1) {
102                         $this->max_depth = max($max_depth);
103                 } else {
104                         $this->max_depth = 0;
105                 }
106
107                 $this->content_length = count($_menu[0]);
108         }
109
110
111         function getContent($parent_id=-1, $length=-1) {
112                 if ($parent_id == -1) {
113                         $my_menu_copy = $this->_menu;
114                         if ($length != -1) {
115                                 $my_menu_copy[0] = array_slice($my_menu_copy[0], 0, $length);
116                         }
117                         return $my_menu_copy;
118                 }
119                 return $this->_menu[$parent_id];
120         }
121
122
123         function &getContentPath($content_id) {
124                 $path = array();
125
126                 $path[] = array('content_id' => $content_id, 'title' => $this->_menu_info[$content_id]['title']);
127
128                 $this->getContentPathRecursive($content_id, $path);
129
130                 $path = array_reverse($path);
131                 return $path;
132         }
133
134
135         function getContentPathRecursive($content_id, &$path) {
136                 $parent_id = $this->_menu_info[$content_id]['content_parent_id'];
137
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);
141                 }
142         }
143
144
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) {
146                 
147                 if (!authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN) && ($_SESSION['course_id'] != -1)) {
148                         return false;
149                 }
150
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);
154
155                 /* main topics all have minor_num = 0 */
156                 $sql = "INSERT INTO ".TABLE_PREFIX."content
157                                (course_id,
158                                 content_parent_id,
159                                 ordering,
160                                 last_modified,
161                                 revision,
162                                 formatting,
163                                 release_date,
164                                 head,
165                                 use_customized_head,
166                                 keywords,
167                                 content_path,
168                                 title,
169                                 text,
170                                                 test_message,
171                                                 allow_test_export)
172                         VALUES ($course_id, 
173                                 $content_parent_id, 
174                                 $ordering, 
175                                 NOW(), 
176                                 0, 
177                                 $formatting, 
178                                 '$release_date', 
179                                 '$head',
180                                 $use_customized_head,
181                                 '$keywords', 
182                                 '', 
183                                 '$title',
184                                 '$text',
185                                                 '$test_message',
186                                                 $allow_test_export)";
187
188                 $err = mysql_query($sql, $this->db);
189
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'];
195
196                 $sql = '';
197                 if (is_array($related)) {
198                         foreach ($related as $x => $related_content_id) {
199                                 $related_content_id = intval($related_content_id);
200
201                                 if ($related_content_id != 0) {
202                                         if ($sql != '') {
203                                                 $sql .= ', ';
204                                         }
205                                         $sql .= '('.$cid.', '.$related_content_id.')';
206                                         $sql .= ', ('.$related_content_id.', '.$cid.')';
207                                 }
208                         }
209
210                         if ($sql != '') {
211                                 $sql    = 'INSERT INTO '.TABLE_PREFIX.'related_content VALUES '.$sql;
212                                 $result = mysql_query($sql, $this->db);
213                         }
214                 }
215
216                 return $cid;
217         }
218
219
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)) {
222                         return FALSE;
223                 }
224
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)) ) {
229                         return FALSE;
230                 }
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);
237
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);
241                 }
242
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);
246
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);
249                 $sql = '';
250                 if (is_array($related)) {
251                         foreach ($related as $x => $related_content_id) {
252                                 $related_content_id = intval($related_content_id);
253
254                                 if ($related_content_id != 0) {
255                                         if ($sql != '') {
256                                                 $sql .= ', ';
257                                         }
258                                         $sql .= '('.$content_id.', '.$related_content_id.')';
259                                         $sql .= ', ('.$related_content_id.', '.$content_id.')';
260                                 }
261                         }
262
263                         if ($sql != '') {
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);
266
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);
270                         }
271                 }
272         }
273
274
275         function deleteContent($content_id) {
276                 if (!authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN)) {
277                         return false;
278                 }
279
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)) ) {
284                         return false;
285                 }
286                 $ordering                       = $row['ordering'];
287                 $content_parent_id      = $row['content_parent_id'];
288
289                 /* check if this content has sub content        */
290                 $children = $this->_menu[$content_id];
291
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']);
296                         }
297                 }
298
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);
302
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);
306
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);
309
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);
313
314                 /* Delete all AccessForAll contents */
315                 require_once(AT_INCLUDE_PATH.'classes/A4a/A4a.class.php');
316                 $a4a = new A4a($content_id);
317                 $a4a->deleteA4a();
318
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 */
323
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);
327
328                 return true;
329         }
330
331
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];
336
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']);
341                         }
342                 }
343
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);
347
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);
351
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);
354
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);
358         }
359
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);
363
364                 return $result;
365         }
366         
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) {
370                         return;
371                 }
372                 if ($content_id == '') {
373                         return;
374                 }
375                 $related_content = array();
376
377                 if ($all) {
378                         $sql = "SELECT * FROM ".TABLE_PREFIX."related_content WHERE content_id=$content_id OR related_content_id=$content_id";
379                 } else {
380                         $sql = "SELECT * FROM ".TABLE_PREFIX."related_content WHERE content_id=$content_id";
381                 }
382                 $result = mysql_query($sql, $this->db);
383
384                 while ($row = mysql_fetch_assoc($result)) {
385                         if ($row['related_content_id'] != $content_id) {
386                                 $related_content[] = $row['related_content_id'];
387                         } else {
388                                 $related_content[] = $row['content_id'];
389                         }
390                 }
391
392                 return $related_content;
393         }
394
395         /** 
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
399          * @date        Sep 10, 2008
400          * @author      Harris
401          */
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);
405                 return $result;
406         }
407
408
409         function & cleanOutput($value) {
410                 return stripslashes(htmlspecialchars($value));
411         }
412
413
414         /* @See include/html/editor_tabs/properties.inc.php */
415         /* Access: Public */
416         function getNumSections() {
417                 return $this->num_sections;
418         }
419
420         /* Access: Public */
421         function getMaxDepth() {
422                 return $this->max_depth;
423         }
424
425         /* Access: Public */
426         function getContentLength() {
427                 return $this->content_length;
428         }
429
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) {
435                                 return $i;
436                         }
437                 }
438                 return 0;       
439         }
440
441         /* Access: Private */
442         function getNumbering($content_id) {
443                 $path = $this->getContentPath($content_id);
444                 $parent = 0;
445                 $numbering = '';
446                 foreach ($path as $page) {
447                         $num = $this->getLocationPositions($parent, $page['content_id']) +1;
448                         $parent = $page['content_id'];
449                         $numbering .= $num.'.';
450                 }
451                 $numbering = substr($numbering, 0, -1);
452
453                 return $numbering;
454         }
455
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'];
460
461                 if (isset($this->_menu[$myParent][$myOrder-2]) && ($this->_menu[$myParent][$myOrder-2] != '') && ($order==0)) {
462                         // has sibling: checking if sibling has children
463                         
464                         $mySibling = $this->_menu[$myParent][$myOrder-2];
465                         
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']]);
468
469                                 // sibling has $num_children children
470                                 return($this->getPreviousContent($this->_menu[$mySibling['content_id']][$num_children-1]['content_id'], 1));
471
472                         } else {
473                                 // sibling has no children. return it
474                                 return($this->_menu[$myParent][$myOrder-2]);
475                         }
476
477                 } else {
478                         if ($myParent == 0) {
479                                 /* we're at the top */
480                                 return '';
481                         }
482
483                         /* No more siblings */
484                         if ($order == 0) {
485                                 return(array('content_id'       => $myParent,
486                                                          'ordering'             => $this->_menu_info[$myParent]['ordering'],
487                                                          'title'                => $this->_menu_info[$myParent]['title']));
488                         } else {
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));
492
493                                 } else {
494                                         /* no children */
495                                         return(array('content_id'       => $content_id,
496                                                                  'ordering'             => $this->_menu_info[$content_id]['ordering'],
497                                                                  'title'                => $this->_menu_info[$content_id]['title']));
498                                 }
499                         }
500                 }
501         }
502
503         /* Access: Private */
504         function getNextContent($content_id, $order=0) {
505                 if (!$content_id) { return; }
506
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) ) {
511                         /* has children */
512                         return($this->_menu[$content_id][0]);
513                 } else {
514                         /* no children */
515                         if (isset($this->_menu[$myParent][$myOrder]) && $this->_menu[$myParent][$myOrder] != '') {
516                                 /* Has sibling */
517                                 return($this->_menu[$myParent][$myOrder]);
518                         } else {
519                                 /* No more siblings */
520                                 if ($myParent != 0) {
521                                         return($this->getNextContent($myParent, 1));
522                                 }
523                         }
524                 }
525         }
526
527         /* @See include/header.inc.php */
528         function generateSequenceCrumbs($cid) {
529                 global $_base_path;
530
531                 $sequence_links = array();
532
533                 $first = $this->getNextContent(0); // get first
534                 if ($_SESSION['prefs']['PREF_NUMBERING'] && $first) {
535                         $first['title'] = $this->getNumbering($first['content_id']).' '.$first['title'];
536                 }
537                 if ($first) {
538                         $first['url'] = $_base_path.url_rewrite('content.php?cid='.$first['content_id']);
539                         $sequence_links['first'] = $first;
540                 }
541
542                 if (!$cid && $_SESSION['s_cid']) {
543                         $resume['title'] = $this->_menu_info[$_SESSION['s_cid']]['title'];
544
545                         if ($_SESSION['prefs']['PREF_NUMBERING']) {
546                                 $resume['title'] = $this->getNumbering($_SESSION['s_cid']).' ' . $resume['title'];
547                         }
548
549                         $resume['url'] = $_base_path.url_rewrite('content.php?cid='.$_SESSION['s_cid']);
550
551                         $sequence_links['resume'] = $resume;
552                 } else {
553                         if ($cid) {
554                                 $previous = $this->getPreviousContent($cid);
555                         }
556                         $next = $this->getNextContent($cid ? $cid : 0);
557
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'];
561                         }
562
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']);
566                         }
567                         
568                         if (isset($previous['content_id'])) {
569                                 $sequence_links['previous'] = $previous;
570                         } else if ($cid) {
571                                 $previous['url']   = $_base_path . url_rewrite('index.php');
572                                 $previous['title'] = _AT('home');
573                                 $sequence_links['previous'] = $previous;
574                         }
575                         if (!empty($next['content_id'])) {
576                                 $sequence_links['next'] = $next;
577                         }
578                 }
579
580                 return $sequence_links;
581         }
582
583         /* @See include/html/dropdowns/menu_menu.inc.php */
584         function printMainMenu( ) {
585                 $parent_id    = 0;
586                 $depth        = 0;
587                 $path         = '';
588                 $children     = array();
589                 $truncate     = true;
590                 $ignore_state = false;
591
592                 $this->start = true;
593                 $this->printMenu($parent_id, $depth, $path, $children, $truncate, $ignore_state);
594         }
595
596         /* @See tools/sitemap/index.php */
597         function printSiteMapMenu() {
598                 $parent_id    = 0;
599                 $depth        = 1;
600                 $path         = '';
601                 $children     = array();
602                 $truncate     = false;
603                 $ignore_state = true;
604
605                 $this->start = true;
606                 $this->printMenu($parent_id, $depth, $path, $children, $truncate, $ignore_state);
607         }
608
609         /* @See index.php */
610         function printTOCMenu($cid, $top_num) {
611                 $parent_id    = $cid;
612                 $depth        = 1;
613                 $path         = $top_num.'.';
614                 $children     = array();
615                 $truncate     = false;
616                 $ignore_state = false;
617
618                 $this->start = true;
619                 $this->printMenu($parent_id, $depth, $path, $children, $truncate, $ignore_state);
620         }
621
622         /* @See index.php include/html/dropdowns/local_menu.inc.php */
623         function printSubMenu($cid, $top_num) {
624                 $parent_id    = $cid;
625                 $depth        = 1;
626                 $path         = $top_num.'.';
627                 $children     = array();
628                 $truncate     = true;
629                 $ignore_state = false;
630         
631                 $this->start = true;
632                 $this->printMenu($parent_id, $depth, $path, $children, $truncate, $ignore_state);
633         }
634
635         /* @See include/html/menu_menu.inc.php  */
636         /* Access: PRIVATE */
637         function printMenu($parent_id, $depth, $path, $children, $truncate, $ignore_state) {
638                 
639                 global $cid, $_my_uri, $_base_path, $rtl, $substr, $strlen;
640                 static $temp_path;
641
642                 if (!isset($temp_path)) {
643                         if ($cid) {
644                                 $temp_path      = $this->getContentPath($cid);
645                         } else {
646                                 $temp_path      = $this->getContentPath($_SESSION['s_cid']);
647                         }
648                 }
649
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;
655                         }
656                 }
657
658                 if ($this->start) {
659                         reset($temp_path);
660                         $this->start = false;
661                 }
662
663                 if ( isset($this->_menu[$parent_id]) && is_array($this->_menu[$parent_id]) ) {
664                         $top_level = $this->_menu[$parent_id];
665                         $counter = 1;
666                         $num_items = count($top_level);
667                         foreach ($top_level as $garbage => $content) {
668                                 $link = '';
669                                 //tests do not have content id
670                                 $content['content_id'] = isset($content['content_id']) ? $content['content_id'] : '';
671
672                                 if (!$ignore_state) {
673                                         $link .= '<a name="menu'.$content['content_id'].'"></a>';
674                                 }
675
676                                 $on = false;
677
678                                 if ( ($_SESSION['s_cid'] != $content['content_id']) || ($_SESSION['s_cid'] != $cid) ) {
679                                         if (isset($highlighted[$content['content_id']])) {
680                                                 $link .= '<strong>';
681                                                 $on = true;
682                                         }
683
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.'" />';
690                                         } else {
691                                                 $in_link = 'content.php?cid='.$content['content_id'];
692                                                 $img_link = '';
693                                         }
694                                         $link .= $img_link . ' <a href="'.$_base_path.url_rewrite($in_link).'" title="';
695                                         if ($_SESSION['prefs']['PREF_NUMBERING']) {
696                                                 $link .= $path.$counter.' ';
697                                         }
698
699                                         $link .= $content['title'].'">';
700
701                                         if ($truncate && ($strlen($content['title']) > (28-$depth*4)) ) {
702                                                 $content['title'] = rtrim($substr($content['title'], 0, (28-$depth*4)-4)).'...';
703                                         }
704                                         $link .= $content['title'];
705                                         $link .= '</a>';
706                                         if ($on) {
707                                                 $link .= '</strong>';
708                                         }
709                                 } else {
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)).'...';
713                                         }
714                                         $link .= trim($content['title']).'</strong>';
715                                         $on = true;
716                                 }
717
718                                 if ($ignore_state) {
719                                         $on = true;
720                                 }
721
722                                 if ( isset($this->_menu[$content['content_id']]) && is_array($this->_menu[$content['content_id']]) ) {
723                                         /* has children */
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";
727                                                 } else {
728                                                         echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
729                                                 }
730                                         }
731
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;
738                                         } else {
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;
741                                         }
742
743                                         if ($_SESSION['s_cid'] == $content['content_id']) {
744                                                 if (is_array($this->_menu[$content['content_id']])) {
745                                                         $_SESSION['menu'][$content['content_id']] = 1;
746                                                 }
747                                         }
748
749                                         if (isset($_SESSION['menu'][$content['content_id']]) && $_SESSION['menu'][$content['content_id']] == 1) {
750                                                 if ($on) {
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";
752
753                                                 } else {
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";
756                                                         echo '</a>'."\n";
757                                                 }
758                                         } else {
759                                                 if ($on) {
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";
761
762                                                 } else {
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" />';
765                                                         echo '</a>'."\n";
766                                                 }
767                                         }
768
769                                 } else {
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";
775                                                         } else {
776                                                                 echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
777                                                         }
778                                                 }
779                                                 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_end.gif" alt="" border="0" class="img-size-tree" />'."\n";
780                                         } else {
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";
784                                                         } else {
785                                                                 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_space.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
786                                                         }
787                                                 }
788                                                 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_split.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
789                                         }
790                                         echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_horizontal.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
791                                 }
792
793                                 if ($_SESSION['prefs']['PREF_NUMBERING']) {
794                                         echo $path.$counter;
795                                 }
796                                 
797                                 echo $link;
798                                 
799                                 echo '<br />';
800
801                                 if ( $ignore_state || (isset($_SESSION['menu'][$content['content_id']]) && $_SESSION['menu'][$content['content_id']] == 1)) {
802
803                                         $depth ++;
804
805                                         $this->printMenu($content['content_id'],
806                                                                                 $depth, 
807                                                                                 $path.$counter.'.', 
808                                                                                 $children,
809                                                                                 $truncate, 
810                                                                                 $ignore_state);
811
812                                                                                 
813                                         $depth--;
814
815                                 }
816                                 $counter++;
817                         }
818                 }
819         }
820
821         /* @See include/html/editor_tabs/properties.inc.php */
822         function printMoveMenu($menu, $parent_id, $depth, $path, $children) {
823                 
824                 global $cid, $_my_uri, $_base_path, $rtl;
825
826                 static $end, $ignore;
827
828                 $top_level = $menu[$parent_id];
829
830                 if ( is_array($top_level) ) {
831                         $counter = 1;
832                         $num_items = count($top_level);
833                         foreach ($top_level as $garbage => $content) {
834                                 if (isset($content['test_id'])){
835                                         continue;
836                                 }
837
838                                 $link = ' ';
839
840                                 echo '<tr>';
841
842                                 if (($parent_id == $_POST['new_pid']) && ($content['ordering'] < $_POST['new_ordering'])) {
843                                         $text = _AT('before_topic', $content['title']);
844                                         $img = 'before.gif';
845                                 } else if ($parent_id != $_POST['new_pid']) {
846                                         $text = _AT('before_topic', $content['title']);
847                                         $img = 'before.gif';
848                                 } else {
849                                         $text = _AT('after_topic', $content['title']);
850                                         $img = 'after.gif';
851                                 }
852                                 if ($ignore && ($_POST['cid'] > 0)) {
853                                         $buttons = '<td><small>&nbsp;</small></td><td><small>&nbsp;</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>&nbsp;</small></td><td>';
856                                 } else {
857
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>';
859
860                                 }
861
862                                 if (( $content['content_id'] == $cid ) || ($content['content_id'] == -1)) {
863                                         $ignore = true;
864                                         $link .= '<strong>'.trim($_POST['title']).' '._AT('current_location').'</strong>';
865                                         $buttons = '<td colspan="2"><small>&nbsp;</small></td><td>';
866                                 } else {
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"';
870                                         }
871                                         $link .= ' /><label for="r'.$content['content_id'].'">'.$content['title'].'</label>';
872                                 }
873
874                                 if ( is_array($menu[$content['content_id']]) && !empty($menu[$content['content_id']]) ) {
875                                         /* has children */
876
877                                         for ($i=0; $i<$depth; $i++) {
878                                                 if ($children[$i] == 1) {
879                                                         echo $buttons;
880                                                         unset($buttons);
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" />';
883                                                         } else {
884                                                                 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_vertline.gif" alt="" border="0" width="16" height="16" />';
885                                                         }
886                                                 } else {
887                                                         echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />';
888                                                 }
889                                         }
890
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;
894                                         } else {
895                                                 echo $buttons;
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" />';
898                                                         $end = true;
899                                                 } else {
900                                                         echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_split.gif" alt="" border="0" width="16" height="16" />';
901                                                 }
902                                                 $children[$depth] = 1;
903                                         }
904
905                                         if ($_SESSION['s_cid'] == $content['content_id']) {
906                                                 if (is_array($menu[$content['content_id']])) {
907                                                         $_SESSION['menu'][$content['content_id']] = 1;
908                                                 }
909                                         }
910
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').'" />';
913
914                                         } else {
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').'" />';
916                                         }
917
918                                 } else {
919                                         /* doesn't have children */
920                                         if ($counter == $num_items) {
921                                                 if ($depth) {
922                                                         echo $buttons;
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" />';
927                                                                         } else {
928                                                                                 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_vertline.gif" alt="" border="0" width="16" height="16" />';
929                                                                         }
930                                                                 } else {
931                                                                         echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />';
932                                                                 }
933                                                         }
934                                                 } else {
935                                                         echo $buttons;
936                                                 }
937                                                 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_end.gif" alt="" border="0" />';
938                                         } else {
939                                                 if ($depth) {
940                                                         echo $buttons;
941                                                         $print = false;
942                                                         for ($i=0; $i<$depth; $i++) {
943                                                                 if ($children[$i] == 1) {
944                                                                         if ($end && !$print) {
945                                                                                 $print = true;
946                                                                                 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_space.gif" alt="" border="0" width="16" height="16" />';
947                                                                         } else {
948                                                                                 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_vertline.gif" alt="" border="0" width="16" height="16" />';
949                                                                         }
950                                                                 } else {
951                                                                         echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_space.gif" alt="" border="0" width="16" height="16" />';
952                                                                 }
953                                                         }
954                                                         $print = false;
955                                                 } else {
956                                                         echo $buttons;
957                                                 }
958                 
959                                                 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_split.gif" alt="" border="0" width="16" height="16" />';
960                                         }
961                                         echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_horizontal.gif" alt="" border="0" width="16" height="16" />';
962                                 }
963
964                                 echo '<small> '.$path.$counter;
965                                 
966                                 echo $link;
967                                 
968                                 echo '</small></td></tr>';
969
970                                 $this->printMoveMenu($menu,
971                                                                         $content['content_id'],
972                                                                         ++$depth, 
973                                                                         $path.$counter.'.', 
974                                                                         $children);
975                                 $depth--;
976
977                                 $counter++;
978
979                                 if ( $content['content_id'] == $cid ) {
980                                         $ignore =false;
981                                 }
982                         }
983                 }
984         }
985
986
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 */
989         /* Access: public */
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
995                                 return true;
996                         } else {
997                                 // nope! not released
998                                 return $this->_menu_info[$cid]['u_release_date'];
999                         }
1000                 }
1001                 // this is a sub page, need to check ALL its parents
1002                 $parent = $this->isReleased($this->_menu_info[$cid]['content_parent_id']); // recursion
1003
1004                 if ($parent !== TRUE && $parent > $this->_menu_info[$cid]['u_release_date']) {
1005                         return $parent;
1006                 } else if ($this->_menu_info[$cid]['u_release_date'] <= time()) {
1007                         return true;
1008                 } else {
1009                         return $this->_menu_info[$cid]['u_release_date'];
1010                 }
1011         }
1012
1013         /** 
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
1017          */
1018         function allowTestExport($content_id){
1019                 if (isset($_SESSION['is_admin'])){      
1020                         return true;
1021                 }
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){
1026                                 return true;
1027                         }
1028                         return false;
1029                 }
1030                 return false;
1031         }
1032 }
1033
1034 ?>