ATutor 2.0
[atutor.git] / include / classes / ContentManager.class.php
1 <?php
2 /****************************************************************/
3 /* ATutor                                                                                                               */
4 /****************************************************************/
5 /* Copyright (c) 2002-2010                                      */
6 /* Inclusive Design Institute                                   */
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         /*      array           */
27         var $_menu_in_order;
28
29         /* int                  */
30         var $course_id;
31
32         // private
33         var $num_sections;
34
35         // private
36         var $max_depth;
37
38         // private
39         var $content_length;
40
41         /* constructor  */
42         function ContentManager(&$db, $course_id) {
43                 $this->db = $db;
44                 $this->course_id = intval($course_id);
45         }
46
47         function initContent( ) {
48                 if (!($this->course_id > 0)) {
49                         return;
50                 }
51                 $sql = "SELECT content_id, content_parent_id, ordering, title, UNIX_TIMESTAMP(release_date) AS u_release_date, content_type 
52                           FROM ".TABLE_PREFIX."content 
53                          WHERE course_id=$this->course_id 
54                          ORDER BY content_parent_id, ordering";
55                 $result = mysql_query($sql, $this->db);
56
57                 /* x could be the ordering or even the content_id       */
58                 /* don't really need the ordering anyway.                       */
59                 /* $_menu[content_parent_id][x] = array('content_id', 'ordering', 'title') */
60                 $_menu = array();
61
62                 /* number of content sections */
63                 $num_sections = 0;
64
65                 $max_depth = array();
66                 $_menu_info = array();
67
68                 while ($row = mysql_fetch_assoc($result)) {
69                         $num_sections++;
70                         $_menu[$row['content_parent_id']][] = array('content_id'=> $row['content_id'],
71                                                                                                                 'ordering'      => $row['ordering'], 
72                                                                                                                 'title'         => htmlspecialchars($row['title']),
73                                                                                                                 'content_type' => $row['content_type']);
74
75                         $_menu_info[$row['content_id']] = array('content_parent_id' => $row['content_parent_id'],
76                                                                                                         'title'                         => htmlspecialchars($row['title']),
77                                                                                                         'ordering'                      => $row['ordering'],
78                                                                                                         'u_release_date'    => $row['u_release_date'],
79                                                                                                         'content_type' => $row['content_type']);
80
81                         /* 
82                          * add test content asscioations
83                          * find associations per content page, and add it as a sublink.
84                          * @author harris
85                          */
86                         $test_rs = $this->getContentTestsAssoc($row['content_id']);
87                         while ($test_row = mysql_fetch_assoc($test_rs)){
88                                 $_menu[$row['content_id']][] = array(   'test_id'       => $test_row['test_id'],
89                                                                                                                 'title'         => htmlspecialchars($test_row['title']),
90                                                                                                                 'content_type' => CONTENT_TYPE_CONTENT);
91                         }
92                         /* End of add test content asscioations */
93
94                         if ($row['content_parent_id'] == 0) {
95                                 $max_depth[$row['content_id']] = 1;
96                         } else {
97                                 $max_depth[$row['content_id']] = $max_depth[$row['content_parent_id']]+1;
98                         }
99                 }
100
101                 $this->_menu = $_menu;
102
103                 $this->_menu_info =  $_menu_info;
104
105                 $this->num_sections = $num_sections;
106
107                 if (count($max_depth) > 1) {
108                         $this->max_depth = max($max_depth);
109                 } else {
110                         $this->max_depth = 0;
111                 }
112
113                 // generate array of all the content ids in the same order that they appear in "content navigation"
114                 $this->_menu_in_order[] = $next_content_id = $this->getNextContentID(0);
115                 while ($next_content_id > 0)
116                 {
117                         $next_content_id = $this->getNextContentID($next_content_id);
118                         
119                         if (in_array($next_content_id, $this->_menu_in_order)) break;
120                         else $this->_menu_in_order[] = $next_content_id;
121                 }
122                 
123                 $this->content_length = count($_menu[0]);
124         }
125
126         // This function is called by initContent to construct $this->_menu_in_order, an array to 
127         // holds all the content ids in the same order that they appear in "content navigation"
128         function getNextContentID($content_id, $order=0) {
129                 // return first root content when $content_id is not given
130                 if (!$content_id) {
131                         return $this->_menu[0][0]['content_id'];
132                 }
133                 
134                 $myParent = $this->_menu_info[$content_id]['content_parent_id'];
135                 $myOrder  = $this->_menu_info[$content_id]['ordering'];
136                 
137                 // calculate $myOrder, add in the number of tests in front of this content page
138                 if (is_array($this->_menu[$myParent])) {
139                         $num_of_tests = 0;
140                         foreach ($this->_menu[$myParent] as $menuContent) {
141                                 if ($menuContent['content_id'] == $content_id) break;
142                                 if (isset($menuContent['test_id'])) $num_of_tests++;
143                         }
144                 }
145                 $myOrder += $num_of_tests;
146                 // end of calculating $myOrder
147                 
148                 /* if this content has children, then take the first one. */
149                 if ( isset($this->_menu[$content_id]) && is_array($this->_menu[$content_id]) && ($order==0) ) {
150                         /* has children */
151                         // if the child is a test, keep searching for the content id
152                         foreach ($this->_menu[$content_id] as $menuID => $menuContent)
153                         {
154                                 if (!empty($menuContent['test_id'])) continue;
155                                 else 
156                                 {
157                                         $nextMenu = $this->_menu[$content_id][$menuID]['content_id'];
158                                         break;
159                                 }
160                         }
161                         
162                         // all children are tests
163                         if (!isset($nextMenu))
164                         {
165                                 if (isset($this->_menu[$myParent][$myOrder]['content_id'])) {
166                                         // has sibling
167                                         return $this->_menu[$myParent][$myOrder]['content_id'];
168                                 }
169                                 else { // no sibling
170                                         $nextMenu = $this->getNextContentID($myParent, 1);
171                                 }
172                         }
173                         return $nextMenu;
174                 } else {
175                         /* no children */
176                         if (isset($this->_menu[$myParent][$myOrder]) && $this->_menu[$myParent][$myOrder] != '') {
177                                 /* Has sibling */
178                                 return $this->_menu[$myParent][$myOrder]['content_id'];
179                         } else {
180                                 /* No more siblings */
181                                 if ($myParent != 0) {
182                                         return $this->getNextContentID($myParent, 1);
183                                 }
184                         }
185                 }
186         }
187         
188         function getContent($parent_id=-1, $length=-1) {
189                 if ($parent_id == -1) {
190                         $my_menu_copy = $this->_menu;
191                         if ($length != -1) {
192                                 $my_menu_copy[0] = array_slice($my_menu_copy[0], 0, $length);
193                         }
194                         return $my_menu_copy;
195                 }
196                 return $this->_menu[$parent_id];
197         }
198
199
200         function &getContentPath($content_id) {
201                 $path = array();
202
203                 $path[] = array('content_id' => $content_id, 'title' => $this->_menu_info[$content_id]['title']);
204
205                 $this->getContentPathRecursive($content_id, $path);
206
207                 $path = array_reverse($path);
208                 return $path;
209         }
210
211
212         function getContentPathRecursive($content_id, &$path) {
213                 $parent_id = $this->_menu_info[$content_id]['content_parent_id'];
214
215                 if ($parent_id > 0) {
216                         $path[] = array('content_id' => $parent_id, 'title' => $this->_menu_info[$parent_id]['title']);
217                         $this->getContentPathRecursive($parent_id, $path);
218                 }
219         }
220
221         function addContent($course_id, $content_parent_id, $ordering, $title, $text, $keywords, 
222                             $related, $formatting, $release_date, $head = '', $use_customized_head = 0, 
223                             $test_message = '', $allow_test_export = 1, $content_type = CONTENT_TYPE_CONTENT) {
224                 
225                 if (!authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN) && ($_SESSION['course_id'] != -1)) {
226                         return false;
227                 }
228
229                 // shift the new neighbouring content down
230                 $sql = "UPDATE ".TABLE_PREFIX."content SET ordering=ordering+1 
231                          WHERE ordering>=$ordering 
232                            AND content_parent_id=$content_parent_id 
233                            AND course_id=$_SESSION[course_id]";
234                 $result = mysql_query($sql, $this->db);
235
236                 /* main topics all have minor_num = 0 */
237                 $sql = "INSERT INTO ".TABLE_PREFIX."content
238                                (course_id,
239                                 content_parent_id,
240                                 ordering,
241                                 last_modified,
242                                 revision,
243                                 formatting,
244                                 release_date,
245                                 head,
246                                 use_customized_head,
247                                 keywords,
248                                 content_path,
249                                 title,
250                                 text,
251                                                 test_message,
252                                                 allow_test_export,
253                                                 content_type)
254                         VALUES ($course_id, 
255                                 $content_parent_id, 
256                                 $ordering, 
257                                 NOW(), 
258                                 0, 
259                                 $formatting, 
260                                 '$release_date', 
261                                 '$head',
262                                 $use_customized_head,
263                                 '$keywords', 
264                                 '', 
265                                 '$title',
266                                 '$text',
267                                                 '$test_message',
268                                                 $allow_test_export,
269                                                 $content_type)";
270
271                 $err = mysql_query($sql, $this->db);
272
273                 /* insert the related content */
274                 $sql = "SELECT LAST_INSERT_ID() AS insert_id";
275                 $result = mysql_query($sql, $this->db);
276                 $row = mysql_fetch_assoc($result);
277                 $cid = $row['insert_id'];
278
279                 $sql = '';
280                 if (is_array($related)) {
281                         foreach ($related as $x => $related_content_id) {
282                                 $related_content_id = intval($related_content_id);
283
284                                 if ($related_content_id != 0) {
285                                         if ($sql != '') {
286                                                 $sql .= ', ';
287                                         }
288                                         $sql .= '('.$cid.', '.$related_content_id.')';
289                                         $sql .= ', ('.$related_content_id.', '.$cid.')';
290                                 }
291                         }
292
293                         if ($sql != '') {
294                                 $sql    = 'INSERT INTO '.TABLE_PREFIX.'related_content VALUES '.$sql;
295                                 $result = mysql_query($sql, $this->db);
296                         }
297                 }
298
299                 return $cid;
300         }
301         
302         function editContent($content_id, $title, $text, $keywords,$related, $formatting, 
303                              $release_date, $head, $use_customized_head, $test_message, 
304                              $allow_test_export) {
305                 if (!authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN)) {
306                         return FALSE;
307                 }
308
309                 /* update the title, text of the newly moved (or not) content */
310                 $sql    = "UPDATE ".TABLE_PREFIX."content 
311                               SET title='$title', head='$head', use_customized_head=$use_customized_head, 
312                                   text='$text', keywords='$keywords', formatting=$formatting, 
313                                   revision=revision+1, last_modified=NOW(), release_date='$release_date', 
314                                   test_message='$test_message', allow_test_export=$allow_test_export 
315                             WHERE content_id=$content_id AND course_id=$_SESSION[course_id]";
316                 $result = mysql_query($sql, $this->db);
317
318                 /* update the related content */
319                 $result = mysql_query("DELETE FROM ".TABLE_PREFIX."related_content WHERE content_id=$content_id OR related_content_id=$content_id", $this->db);
320                 $sql = '';
321                 if (is_array($related)) {
322                         foreach ($related as $x => $related_content_id) {
323                                 $related_content_id = intval($related_content_id);
324
325                                 if ($related_content_id != 0) {
326                                         if ($sql != '') {
327                                                 $sql .= ', ';
328                                         }
329                                         $sql .= '('.$content_id.', '.$related_content_id.')';
330                                         $sql .= ', ('.$related_content_id.', '.$content_id.')';
331                                 }
332                         }
333
334                         if ($sql != '') {
335                                 /* delete the old related content */
336                                 $result = mysql_query("DELETE FROM ".TABLE_PREFIX."related_content WHERE content_id=$content_id OR related_content_id=$content_id", $this->db);
337
338                                 /* insert the new, and the old related content again */
339                                 $sql    = 'INSERT INTO '.TABLE_PREFIX.'related_content VALUES '.$sql;
340                                 $result = mysql_query($sql, $this->db);
341                         }
342                 }
343         }
344
345         function moveContent($content_id, $new_content_parent_id, $new_content_ordering) {
346                 global $msg;
347                 
348                 if (!authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN)) {
349                         return FALSE;
350                 }
351
352                 /* first get the content to make sure it exists */
353                 $sql    = "SELECT ordering, content_parent_id FROM ".TABLE_PREFIX."content WHERE content_id=$content_id AND course_id=$_SESSION[course_id]";
354                 $result = mysql_query($sql, $this->db);
355                 if (!($row = mysql_fetch_assoc($result)) ) {
356                         return FALSE;
357                 }
358                 $old_ordering           = $row['ordering'];
359                 $old_content_parent_id  = $row['content_parent_id'];
360                 
361                 $sql    = "SELECT max(ordering) max_ordering FROM ".TABLE_PREFIX."content WHERE content_parent_id=$old_content_parent_id AND course_id=$_SESSION[course_id]";
362                 $result = mysql_query($sql, $this->db);
363                 $row = mysql_fetch_assoc($result);
364                 $max_ordering = $row['max_ordering'];
365                 
366                 if ($content_id == $new_content_parent_id) {
367                         $msg->addError("NO_SELF_AS_PARENT");
368                         return;
369                 }
370                 
371                 if ($old_content_parent_id == $new_content_parent_id && $old_ordering == $new_content_ordering) {
372                         $msg->addError("SAME_LOCATION");
373                         return;
374                 }
375                 
376                 $content_path = $this->getContentPath($new_content_parent_id);
377                 foreach ($content_path as $parent){
378                         if ($parent['content_id'] == $content_id) {
379                                 $msg->addError("NO_CHILD_AS_PARENT");
380                                 return;
381                         }
382                 }
383                 
384                 // if the new_content_ordering is greater than the maximum ordering of the parent content, 
385                 // set the $new_content_ordering to the maximum ordering. This happens when move the content 
386                 // to the last element under the same parent content.
387                 if ($old_content_parent_id == $new_content_parent_id && $new_content_ordering > $max_ordering) 
388                         $new_content_ordering = $max_ordering;
389                 
390                 if (($old_content_parent_id != $new_content_parent_id) || ($old_ordering != $new_content_ordering)) {
391                         // remove the gap left by the moved content
392                         $sql = "UPDATE ".TABLE_PREFIX."content 
393                                    SET ordering=ordering-1 
394                                  WHERE ordering>$old_ordering 
395                                    AND content_parent_id=$old_content_parent_id 
396                                    AND content_id<>$content_id 
397                                    AND course_id=$_SESSION[course_id]";
398                         $result = mysql_query($sql, $this->db);
399
400                         // shift the new neighbouring content down
401                         $sql = "UPDATE ".TABLE_PREFIX."content 
402                                    SET ordering=ordering+1 
403                                  WHERE ordering>=$new_content_ordering 
404                                    AND content_parent_id=$new_content_parent_id 
405                                    AND content_id<>$content_id 
406                                    AND course_id=$_SESSION[course_id]";
407                         $result = mysql_query($sql, $this->db);
408
409                         $sql    = "UPDATE ".TABLE_PREFIX."content 
410                                       SET content_parent_id=$new_content_parent_id, ordering=$new_content_ordering 
411                                     WHERE content_id=$content_id AND course_id=$_SESSION[course_id]";
412                         $result = mysql_query($sql, $this->db);
413                 }
414         }
415         
416         function deleteContent($content_id) {
417                 if (!authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN)) {
418                         return false;
419                 }
420
421                 /* check if exists */
422                 $sql    = "SELECT ordering, content_parent_id FROM ".TABLE_PREFIX."content WHERE content_id=$content_id AND course_id=$_SESSION[course_id]";
423                 $result = mysql_query($sql, $this->db);
424                 if (!($row = @mysql_fetch_assoc($result)) ) {
425                         return false;
426                 }
427                 $ordering                       = $row['ordering'];
428                 $content_parent_id      = $row['content_parent_id'];
429
430                 /* check if this content has sub content        */
431                 $children = $this->_menu[$content_id];
432
433                 if (is_array($children) && (count($children)>0) ) {
434                         /* delete its children recursively first*/
435                         foreach ($children as $x => $info) {
436                                 $this->deleteContentRecursive($info['content_id']);
437                         }
438                 }
439
440                 /* delete this content page                                     */
441                 $sql    = "DELETE FROM ".TABLE_PREFIX."content WHERE content_id=$content_id AND course_id=$_SESSION[course_id]";
442                 $result = mysql_query($sql, $this->db);
443
444                 /* delete this content from member tracking page        */
445                 $sql    = "DELETE FROM ".TABLE_PREFIX."member_track WHERE content_id=$content_id AND course_id=$_SESSION[course_id]";
446                 $result = mysql_query($sql, $this->db);
447
448                 $sql    = "DELETE FROM ".TABLE_PREFIX."related_content WHERE content_id=$content_id OR related_content_id=$content_id";
449                 $result = mysql_query($sql, $this->db);
450
451                 /* delete the content tests association */
452                 $sql    = "DELETE FROM ".TABLE_PREFIX."content_tests_assoc WHERE content_id=$content_id";
453                 $result = mysql_query($sql, $this->db);
454
455                 /* delete the content forum association */
456                 $sql    = "DELETE FROM ".TABLE_PREFIX."content_forums_assoc WHERE content_id=$content_id";
457                 $result = mysql_query($sql, $this->db);
458
459                 /* Delete all AccessForAll contents */
460                 require_once(AT_INCLUDE_PATH.'../mods/_core/imsafa/classes/A4a.class.php');
461                 $a4a = new A4a($content_id);
462                 $a4a->deleteA4a();
463
464                 /* re-order the rest of the content */
465                 $sql = "UPDATE ".TABLE_PREFIX."content SET ordering=ordering-1 WHERE ordering>=$ordering AND content_parent_id=$content_parent_id AND course_id=$_SESSION[course_id]";
466                 $result = mysql_query($sql, $this->db);
467                 /* end moving block */
468
469                 /* remove the "resume" to this page, b/c it was deleted */
470                 $sql = "UPDATE ".TABLE_PREFIX."course_enrollment SET last_cid=0 WHERE course_id=$_SESSION[course_id] AND last_cid=$content_id";
471                 $result = mysql_query($sql, $this->db);
472
473                 return true;
474         }
475
476
477         /* private. call from deleteContent only. */
478         function deleteContentRecursive($content_id) {
479                 /* check if this content has sub content        */
480                 $children = $this->_menu[$content_id];
481
482                 if (is_array($children) && (count($children)>0) ) {
483                         /* delete its children recursively first*/
484                         foreach ($children as $x => $info) {
485                                 $this->deleteContent($info['content_id']);
486                         }
487                 }
488
489                 /* delete this content page                                     */
490                 $sql    = "DELETE FROM ".TABLE_PREFIX."content WHERE content_id=$content_id AND course_id=$_SESSION[course_id]";
491                 $result = mysql_query($sql, $this->db);
492
493                 /* delete this content from member tracking page        */
494                 $sql    = "DELETE FROM ".TABLE_PREFIX."member_track WHERE content_id=$content_id";
495                 $result = mysql_query($sql, $this->db);
496
497                 $sql    = "DELETE FROM ".TABLE_PREFIX."related_content WHERE content_id=$content_id OR related_content_id=$content_id";
498                 $result = mysql_query($sql, $this->db);
499
500                 /* delete the content tests association */
501                 $sql    = "DELETE FROM ".TABLE_PREFIX."content_tests_assoc WHERE content_id=$content_id";
502                 $result = mysql_query($sql, $this->db);
503         }
504
505         function getContentPage($content_id) {
506                 $sql    = "SELECT *, DATE_FORMAT(release_date, '%Y-%m-%d %H:%i:00') AS release_date, release_date+0 AS r_date, NOW()+0 AS n_date FROM ".TABLE_PREFIX."content 
507                             WHERE content_id=$content_id";
508                 $result = mysql_query($sql, $this->db);
509
510                 return $result;
511         }
512         
513         /* @See editor/edit_content.php include/html/dropdowns/related_topics.inc.php include/lib/editor_tabs_functions.inc.php */
514         function getRelatedContent($content_id, $all=false) {
515                 if ($content_id == 0) {
516                         return;
517                 }
518                 if ($content_id == '') {
519                         return;
520                 }
521                 $related_content = array();
522
523                 if ($all) {
524                         $sql = "SELECT * FROM ".TABLE_PREFIX."related_content WHERE content_id=$content_id OR related_content_id=$content_id";
525                 } else {
526                         $sql = "SELECT * FROM ".TABLE_PREFIX."related_content WHERE content_id=$content_id";
527                 }
528                 $result = mysql_query($sql, $this->db);
529
530                 while ($row = mysql_fetch_assoc($result)) {
531                         if ($row['related_content_id'] != $content_id) {
532                                 $related_content[] = $row['related_content_id'];
533                         } else {
534                                 $related_content[] = $row['content_id'];
535                         }
536                 }
537
538                 return $related_content;
539         }
540
541         /** 
542          * Return a list of tests associated with the selected content
543          * @param       int             the content id that all tests are associated with it.
544          * @return      array   list of tests
545          * @date        Sep 10, 2008
546          * @author      Harris
547          */
548         function & getContentTestsAssoc($content_id){
549                 $sql    = "SELECT ct.test_id, t.title FROM (SELECT * FROM ".TABLE_PREFIX."content_tests_assoc WHERE content_id=$content_id) AS ct LEFT JOIN ".TABLE_PREFIX."tests t ON ct.test_id=t.test_id";
550                 $result = mysql_query($sql, $this->db);
551                 return $result;
552         }
553
554         /*TODO***************BOLOGNA***************REMOVE ME**********/
555         function & getContentForumsAssoc($content_id){
556                 $sql    = "SELECT cf.forum_id, f.title FROM (SELECT * FROM ".TABLE_PREFIX."content_forums_assoc WHERE content_id=$content_id) AS cf LEFT JOIN ".TABLE_PREFIX."forums f ON cf.forum_id=f.forum_id";
557                 $result = mysql_query($sql, $this->db);
558                 return $result;
559         }
560
561         function & cleanOutput($value) {
562                 return stripslashes(htmlspecialchars($value));
563         }
564
565
566         /* @See include/html/editor_tabs/properties.inc.php */
567         /* Access: Public */
568         function getNumSections() {
569                 return $this->num_sections;
570         }
571
572         /* Access: Public */
573         function getMaxDepth() {
574                 return $this->max_depth;
575         }
576
577         /* Access: Public */
578         function getContentLength() {
579                 return $this->content_length;
580         }
581
582         /* @See include/html/dropdowns/local_menu.inc.php */
583         function getLocationPositions($parent_id, $content_id) {
584                 $siblings = $this->getContent($parent_id);
585                 for ($i=0;$i<count($siblings); $i++){
586                         if ($siblings[$i]['content_id'] == $content_id) {
587                                 return $i;
588                         }
589                 }
590                 return 0;       
591         }
592
593         /* Access: Private */
594         function getNumbering($content_id) {
595                 $path = $this->getContentPath($content_id);
596                 $parent = 0;
597                 $numbering = '';
598                 foreach ($path as $page) {
599                         $num = $this->getLocationPositions($parent, $page['content_id']) +1;
600                         $parent = $page['content_id'];
601                         $numbering .= $num.'.';
602                 }
603                 $numbering = substr($numbering, 0, -1);
604
605                 return $numbering;
606         }
607
608         function getPreviousContent($content_id) {
609                 if (is_array($this->_menu_in_order))
610                 {
611                         foreach ($this->_menu_in_order as $content_location => $this_content_id)
612                         {
613                                 if ($this_content_id == $content_id) break;
614                         }
615                         
616                         for ($i=$content_location-1; $i >= 0; $i--)
617                         {
618                                 $content_type = $this->_menu_info[$this->_menu_in_order[$i]]['content_type'];
619                                 
620                                 if ($content_type == CONTENT_TYPE_CONTENT || $content_type == CONTENT_TYPE_WEBLINK)
621                                         return array('content_id'       => $this->_menu_in_order[$i],
622                                                  'ordering'             => $this->_menu_info[$this->_menu_in_order[$i]]['ordering'],
623                                                      'title'            => $this->_menu_info[$this->_menu_in_order[$i]]['title']);
624                         }
625                 }
626                 return NULL;
627         }
628         
629         function getNextContent($content_id) {
630                 if (is_array($this->_menu_in_order))
631                 {
632                         foreach ($this->_menu_in_order as $content_location => $this_content_id)
633                         {
634                                 if ($this_content_id == $content_id) break;
635                         }
636                         
637                         for ($i=$content_location+1; $i < count($this->_menu_in_order); $i++)
638                         {
639                                 $content_type = $this->_menu_info[$this->_menu_in_order[$i]]['content_type'];
640                                 
641                                 if ($content_type == CONTENT_TYPE_CONTENT || $content_type == CONTENT_TYPE_WEBLINK)
642                                         return(array('content_id'       => $this->_menu_in_order[$i],
643                                                  'ordering'             => $this->_menu_info[$this->_menu_in_order[$i]]['ordering'],
644                                                      'title'            => $this->_menu_info[$this->_menu_in_order[$i]]['title']));
645                         }
646                 }
647                 return NULL;
648         }
649         
650         /* @See include/header.inc.php */
651         function generateSequenceCrumbs($cid) {
652                 global $_base_path;
653
654                 $sequence_links = array();
655
656                 $first = $this->getNextContent(0); // get first
657                 if ($_SESSION['prefs']['PREF_NUMBERING'] && $first) {
658                         $first['title'] = $this->getNumbering($first['content_id']).' '.$first['title'];
659                 }
660                 if ($first) {
661                         $first['url'] = $_base_path.url_rewrite('content.php?cid='.$first['content_id']);
662                         $sequence_links['first'] = $first;
663                 }
664
665                 if (!$cid && $_SESSION['s_cid']) {
666                         $resume['title'] = $this->_menu_info[$_SESSION['s_cid']]['title'];
667
668                         if ($_SESSION['prefs']['PREF_NUMBERING']) {
669                                 $resume['title'] = $this->getNumbering($_SESSION['s_cid']).' ' . $resume['title'];
670                         }
671
672                         $resume['url'] = $_base_path.url_rewrite('content.php?cid='.$_SESSION['s_cid']);
673
674                         $sequence_links['resume'] = $resume;
675                 } else {
676                         if ($cid) {
677                                 $previous = $this->getPreviousContent($cid);
678                         }
679                         $next = $this->getNextContent($cid ? $cid : 0);
680
681                         if ($_SESSION['prefs']['PREF_NUMBERING']) {
682                                 $previous['title'] = $this->getNumbering($previous['content_id']).' '.$previous['title'];
683                                 $next['title'] = $this->getNumbering($next['content_id']).' '.$next['title'];
684                         }
685
686                         $next['url'] = $_base_path.url_rewrite('content.php?cid='.$next['content_id']);
687                         if (isset($previous['content_id'])) {
688                                 $previous['url'] = $_base_path.url_rewrite('content.php?cid='.$previous['content_id']);
689                         }
690                         
691                         if (isset($previous['content_id'])) {
692                                 $sequence_links['previous'] = $previous;
693                         } else if ($cid) {
694                                 $previous['url']   = $_base_path . url_rewrite('index.php');
695                                 $previous['title'] = _AT('home');
696                                 $sequence_links['previous'] = $previous;
697                         }
698                         if (!empty($next['content_id'])) {
699                                 $sequence_links['next'] = $next;
700                         }
701                 }
702
703                 return $sequence_links;
704         }
705
706         /** Generate javascript to hide all root content folders, except the one with current content page
707          * access: private
708          * @return print out javascript function initContentMenu()
709          */
710         function initMenu(){
711                 global $_base_path;
712                 
713                 echo '
714 function initContentMenu() {
715         tree_collapse_icon = "'.$_base_path.'images/tree/tree_collapse.gif";
716         tree_expand_icon = "'.$_base_path.'images/tree/tree_expand.gif";
717                 
718 ';
719                 
720                 $sql = "SELECT content_id
721                           FROM ".TABLE_PREFIX."content 
722                          WHERE course_id=$this->course_id
723                            AND content_type = ".CONTENT_TYPE_FOLDER;
724                 $result = mysql_query($sql, $this->db);
725
726                 // collapse all root content folders
727                 while ($row = mysql_fetch_assoc($result)) {
728                         echo '
729         if (ATutor.getcookie("c'.$_SESSION['course_id'].'_'.$row['content_id'].'") == "1")
730         {
731                 jQuery("#folder"+'.$row['content_id'].').show();
732                 jQuery("#tree_icon"+'.$row['content_id'].').attr("src", tree_collapse_icon);
733                 jQuery("#tree_icon"+'.$row['content_id'].').attr("alt", "'._AT("collapse").'");
734                 jQuery("#tree_icon"+'.$row['content_id'].').attr("title", "'._AT("collapse").'");
735         }
736         else
737         {
738                 jQuery("#folder"+'.$row['content_id'].').hide();
739                 jQuery("#tree_icon"+'.$row['content_id'].').attr("src", tree_expand_icon);
740                 jQuery("#tree_icon"+'.$row['content_id'].').attr("alt", "'._AT("expand").'");
741                 jQuery("#tree_icon"+'.$row['content_id'].').attr("title", "'._AT("expand").'");
742         }
743 ';
744                 }
745                 
746                 // expand the content folder that has current content
747                 if (isset($_SESSION['s_cid']) && $_SESSION['s_cid'] > 0) {
748                         $current_content_path = $this->getContentPath($_SESSION['s_cid']);
749                         
750                         for ($i=0; $i < count($current_content_path)-1; $i++)
751                                 echo '
752         jQuery("#folder"+'.$current_content_path[$i]['content_id'].').show();
753         jQuery("#tree_icon"+'.$current_content_path[$i]['content_id'].').attr("src", tree_collapse_icon);
754         jQuery("#tree_icon"+'.$current_content_path[$i]['content_id'].').attr("alt", "'._AT("collapse").'");
755         ATutor.setcookie("c'.$_SESSION['course_id'].'_'.$current_content_path[$i]['content_id'].'", "1", 1);
756 ';
757                 }
758                 echo '}'; // end of javascript function initContentMenu()
759         }
760         
761         /* @See include/html/dropdowns/menu_menu.inc.php */
762         function printMainMenu( ) {
763                 if (!($this->course_id > 0)) {
764                         return;
765                 }
766                 
767                 global $_base_path;
768                 
769                 $parent_id    = 0;
770                 $depth        = 0;
771                 $path         = '';
772                 $children     = array();
773                 $truncate     = true;
774                 $ignore_state = true;
775
776                 $this->start = true;
777                 
778                 // if change the location of this line, change function switchEditMode(), else condition accordingly
779                 echo '<div id="editable_table">';
780                 
781                 if (authenticate(AT_PRIV_ADMIN,AT_PRIV_RETURN) && !is_mobile_device())
782                 {
783                         echo "\n".'
784                         <div class="menuedit">
785                         <a href="'.$_base_path.'mods/_core/editor/edit_content_folder.php">
786                                 <img id="img_create_top_folder" src="'.$_base_path.'images/folder_new.gif" alt="'._AT("add_top_folder").'" title="'._AT("add_top_folder").'" style="border:0;height:1.2em" />
787                         </a>'."\n".
788                         '<a href="'.$_base_path.'mods/_core/editor/edit_content.php">
789                                 <img id="img_create_top_content" src="'.$_base_path.'images/page_add.gif" alt="'._AT("add_top_page").'" title="'._AT("add_top_page").'" style="border:0;height:1.2em" />
790                         </a>'."\n".
791                         '<a href="javascript:void(0)" onclick="javascript:switchEditMode();">
792                                 <img id="img_switch_edit_mode" src="'.$_base_path.'images/medit.gif" alt="'._AT("enter_edit_mode").'" title="'._AT("enter_edit_mode").'" style="border:0;height:1.2em" />
793                         </a>
794                         </div>'."\n";
795                 }
796                 $this->printMenu($parent_id, $depth, $path, $children, $truncate, $ignore_state);
797                 
798                 // javascript for inline editor
799                 echo '
800 <script type="text/javascript">
801 ';
802                 // only expand the content folder that has the current content page
803                 $this->initMenu();
804                 
805                 echo '
806 function switchEditMode() {
807         title_edit = "'._AT("enter_edit_mode").'";
808         img_edit = "'.$_base_path.'images/medit.gif";
809         
810         title_view = "'._AT("exit_edit_mode").'";
811         img_view = "'.$_base_path.'images/mlock.gif";
812         
813         if (jQuery("#img_switch_edit_mode").attr("src") == img_edit)
814         {
815                 jQuery("#img_switch_edit_mode").attr("src", img_view);
816                 jQuery("#img_switch_edit_mode").attr("alt", title_view);
817                 jQuery("#img_switch_edit_mode").attr("title", title_view);
818                 inlineEditsSetup();
819         }
820         else
821         { // refresh the content navigation to exit the edit mode
822                 jQuery.post("'. $_base_path. 'mods/_core/content/refresh_content_nav.php", {}, 
823                                         function(data) {jQuery("#editable_table").replaceWith(data); initContentMenu();});
824         }
825 }
826
827 function inlineEditsSetup() {
828         jQuery("#editable_table").find(".inlineEdits").each(function() {
829                 jQuery(this).text(jQuery(this).attr("title"));
830         });
831         
832         var tableEdit = fluid.inlineEdits("#editable_table", {
833                 selectors : {
834                         text : ".inlineEdits",
835                         editables : "span:has(span.inlineEdits)"
836                 },
837                 defaultViewText: "",
838                 applyEditPadding: false,
839                 useTooltip: true,
840                 listeners: {
841                         afterFinishEdit : function (newValue, oldValue, editNode, viewNode) {
842                                 if (newValue != oldValue) 
843                                 {
844                                         rtn = jQuery.post("'. $_base_path. 'mods/_core/content/menu_inline_editor_submit.php", { "field":viewNode.id, "value":newValue }, 
845                                                           function(data) {}, "json");
846                                 }
847                         }
848                 }
849         });
850
851         jQuery(".fl-inlineEdit-edit").css("width", "80px")
852
853 };
854
855 initContentMenu();
856 </script>
857 ';
858                 echo '</div>';
859         }
860
861         /* @See tools/sitemap/index.php */
862         function printSiteMapMenu() {
863                 $parent_id    = 0;
864                 $depth        = 1;
865                 $path         = '';
866                 $children     = array();
867                 $truncate     = false;
868                 $ignore_state = true;
869
870                 $this->start = true;
871                 $this->printMenu($parent_id, $depth, $path, $children, $truncate, $ignore_state, 'sitemap');
872         }
873
874         /* @See index.php */
875         function printTOCMenu($cid, $top_num) {
876                 $parent_id    = $cid;
877                 $depth        = 1;
878                 $path         = $top_num.'.';
879                 $children     = array();
880                 $truncate     = false;
881                 $ignore_state = false;
882
883                 $this->start = true;
884                 $this->printMenu($parent_id, $depth, $path, $children, $truncate, $ignore_state);
885         }
886
887         /* @See index.php include/html/dropdowns/local_menu.inc.php */
888         function printSubMenu($cid, $top_num) {
889                 $parent_id    = $cid;
890                 $depth        = 1;
891                 $path         = $top_num.'.';
892                 $children     = array();
893                 $truncate     = true;
894                 $ignore_state = false;
895         
896                 $this->start = true;
897                 $this->printMenu($parent_id, $depth, $path, $children, $truncate, $ignore_state);
898         }
899
900         /* @See include/html/menu_menu.inc.php  */
901         /* Access: PRIVATE */
902         function printMenu($parent_id, $depth, $path, $children, $truncate, $ignore_state, $from = '') {
903                 global $cid, $_my_uri, $_base_path, $rtl, $substr, $strlen;
904                 static $temp_path;
905
906                 if (!isset($temp_path)) {
907                         if ($cid) {
908                                 $temp_path      = $this->getContentPath($cid);
909                         } else {
910                                 $temp_path      = $this->getContentPath($_SESSION['s_cid']);
911                         }
912                 }
913
914                 $highlighted = array();
915                 if (is_array($temp_path)) {
916                         foreach ($temp_path as $temp_path_item) {
917                                 $_SESSION['menu'][$temp_path_item['content_id']] = 1;
918                                 $highlighted[$temp_path_item['content_id']] = true;
919                         }
920                 }
921
922                 if ($this->start) {
923                         reset($temp_path);
924                         $this->start = false;
925                 }
926
927                 if ( isset($this->_menu[$parent_id]) && is_array($this->_menu[$parent_id]) ) {
928                         $top_level = $this->_menu[$parent_id];
929                         $counter = 1;
930                         $num_items = count($top_level);
931                         
932                         echo '<div id="folder'.$parent_id.$from.'">'."\n";
933                         
934                         foreach ($top_level as $garbage => $content) {
935                                 $link = '';
936                                 //tests do not have content id
937                                 $content['content_id'] = isset($content['content_id']) ? $content['content_id'] : '';
938
939                                 if (!$ignore_state) {
940                                         $link .= '<a name="menu'.$content['content_id'].'"></a>';
941                                 }
942
943                                 $on = false;
944
945                                 if ( (($_SESSION['s_cid'] != $content['content_id']) || ($_SESSION['s_cid'] != $cid)) && ($content['content_type'] == CONTENT_TYPE_CONTENT || $content['content_type'] == CONTENT_TYPE_WEBLINK)) 
946                                 { // non-current content nodes with content type "CONTENT_TYPE_CONTENT"
947                                         if (isset($highlighted[$content['content_id']])) {
948                                                 $link .= '<strong>';
949                                                 $on = true;
950                                         }
951
952                                         //content test extension  @harris
953                                         //if this is a test link.
954                                         if (isset($content['test_id'])){
955                                                 $title_n_alt =  $content['title'];
956                                                 $in_link = 'mods/_standard/tests/test_intro.php?tid='.$content['test_id'];
957                                                 $img_link = ' <img src="'.$_base_path.'images/check.gif" title="'.$title_n_alt.'" alt="'.$title_n_alt.'" />';
958                                         } else {
959                                                 $in_link = 'content.php?cid='.$content['content_id'];
960                                                 $img_link = '';
961                                         }
962                                         
963                                         $full_title = $content['title'];
964                                         $link .= $img_link . ' <a href="'.$_base_path.url_rewrite($in_link).'" title="';
965                                         $base_title_length = 29;
966                                         if ($_SESSION['prefs']['PREF_NUMBERING']) {
967                                                 $base_title_length = 24;
968                                         }
969
970                                         $link .= $content['title'].'">';
971
972                                         if ($truncate && ($strlen($content['title']) > ($base_title_length-$depth*4)) ) {
973                                                 $content['title'] = htmlspecialchars(rtrim($substr(htmlspecialchars_decode($content['title']), 0, ($base_title_length-$depth*4)-4))).'...';
974                                         }
975                                         
976                                         if (isset($content['test_id'])) {
977                                                 $link .= $content['title'];
978                                         } else {
979                                                 $link .= '<span class="inlineEdits" id="menu-'.$content['content_id'].'" title="'.$full_title.'">';
980                                                 if($_SESSION['prefs']['PREF_NUMBERING']){
981                                                   $link .= $path.$counter;
982                                                 }
983                                                 $link .= '&nbsp;'.$content['title'].'</span>';
984                                         }
985                                         
986                                         $link .= '</a>';
987                                         if ($on) {
988                                                 $link .= '</strong>';
989                                         }
990                                         
991                                         // instructors have privilege to delete content
992                                         if (authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN) && !isset($content['test_id']) && !is_mobile_device()) {
993                                                 $link .= '<a href="'.$_base_path.'mods/_core/editor/delete_content.php?cid='.$content['content_id'].'"><img src="'.AT_BASE_HREF.'images/x.gif" alt="'._AT("delete_content").'" title="'._AT("delete_content").'" style="border:0" height="10" /></a>';
994                                         }
995                                 } 
996                                 else 
997                                 { // current content page & nodes with content type "CONTENT_TYPE_FOLDER"
998                                         $base_title_length = 33;
999                                         if ($_SESSION['prefs']['PREF_NUMBERING']) {
1000                                                 $base_title_length = 26;
1001                                         }
1002                                         
1003                                         if (isset($highlighted[$content['content_id']])) {
1004                                                 $link .= '<strong>';
1005                                                 $on = true;
1006                                         }
1007
1008                                         if ($content['content_type'] == CONTENT_TYPE_CONTENT || $content['content_type'] == CONTENT_TYPE_WEBLINK)
1009                                         { // current content page
1010                                                 $full_title = $content['title'];
1011                                                 $link .= '<a href="'.$_my_uri.'"><img src="'.$_base_path.'images/clr.gif" alt="'._AT('you_are_here').': ';
1012                                                 if($_SESSION['prefs']['PREF_NUMBERING']){
1013                                                   $link .= $path.$counter;
1014                                                 }
1015                                                   $link .= $content['title'].'" height="1" width="1" border="0" /></a><strong style="color:red" title="'.$content['title'].'">'."\n";
1016                                                 if ($truncate && ($strlen($content['title']) > ($base_title_length-$depth*4)) ) {
1017                                                         $content['title'] = htmlspecialchars(rtrim($substr(htmlspecialchars_decode($content['title']), 0, ($base_title_length-$depth*4)-4))).'...';
1018                                                 }
1019                                                 $link .= '<a name="menu'.$content['content_id'].'"></a><span class="inlineEdits" id="menu-'.$content['content_id'].'" title="'.$full_title.'">';
1020                                                 if($_SESSION['prefs']['PREF_NUMBERING']){
1021                                                   $link .= $path.$counter;
1022                                                 }
1023                                                 $link .='&nbsp;'.$content['title'].'</span></strong>';
1024                                                 
1025                                                 // instructors have privilege to delete content
1026                                                 if (authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN) && !is_mobile_device()) {
1027                                                         $link .= '<a href="'.$_base_path.'mods/_core/editor/delete_content.php?cid='.$content['content_id'].'"><img src="'.AT_BASE_HREF.'images/x.gif" alt="'._AT("delete_content").'" title="'._AT("delete_content").'" style="border:0" height="10" /></a>';
1028                                                 }
1029                                         }
1030                                         else
1031                                         { // nodes with content type "CONTENT_TYPE_FOLDER"
1032                                                 $full_title = $content['title'];
1033                                                 if (authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN) && !is_mobile_device()) {
1034                                                         $link .= '<a href="'.$_base_path."mods/_core/editor/edit_content_folder.php?cid=".$content['content_id'].'" title="'.$full_title. _AT('click_edit').'">'."\n";
1035                                                 }
1036                                                 else {
1037                                                         $link .= '<span style="cursor:pointer" onclick="javascript: ATutor.course.toggleFolder(\''.$content['content_id'].$from.'\', \''._AT('expand').'\', \''._AT('collapse').'\', '.$this->course_id.'); ">'."\n";
1038                                                 }
1039                                                 
1040                                                 if ($truncate && ($strlen($content['title']) > ($base_title_length-$depth*4)) ) {
1041                                                         $content['title'] = htmlspecialchars(rtrim($substr(htmlspecialchars_decode($content['title']), 0, ($base_title_length-$depth*4)-4))).'...';
1042                                                 }
1043                                                 if (isset($content['test_id']))
1044                                                         $link .= $content['title'];
1045                                                 else
1046                                                         $link .= '<span class="inlineEdits" id="menu-'.$content['content_id'].'" title="'.$full_title.'">';
1047                                                 if($_SESSION['prefs']['PREF_NUMBERING']){
1048                                                   $link .= $path.$counter;
1049                                                 }
1050                                                   $link .= '&nbsp;'.$content['title'].'</span>';
1051                                                 
1052                                                 if (authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN) && !is_mobile_device()) {
1053                                                         $link .= '</a>'."\n";
1054                                                 }
1055                                                 else {
1056                                                         $link .= '</span>'."\n";
1057                                                 }
1058                                                 
1059                                                 // instructors have privilege to delete content
1060                                                 if (authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN) && !is_mobile_device()) {
1061                                                         $link .= '<a href="'.$_base_path.'mods/_core/editor/delete_content.php?cid='.$content['content_id'].'"><img src="'.AT_BASE_HREF.'images/x.gif" alt="'._AT("delete_content").'" title="'._AT("delete_content").'" style="border:0" height="10" /></a>';
1062                                                 }
1063
1064                                         }
1065                                         
1066                                         if ($on) {
1067                                                 $link .= '</strong>';
1068                                         }
1069                                 }
1070
1071                                 if ($ignore_state) {
1072                                         $on = true;
1073                                 }
1074
1075                                 echo '<span>'."\n";
1076                                 
1077                                 if ( isset($this->_menu[$content['content_id']]) && is_array($this->_menu[$content['content_id']]) ) {
1078                                         /* has children */
1079                                         for ($i=0; $i<$depth; $i++) {
1080                                                 if ($children[$i] == 1) {
1081                                                         echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_vertline.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
1082                                                 } else {
1083                                                         echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
1084                                                 }
1085                                         }
1086
1087                                         if (($counter == $num_items) && ($depth > 0)) {
1088                                                 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_end.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
1089                                                 $children[$depth] = 0;
1090                                         } else if ($counter == $num_items) {
1091                                                 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_end.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
1092                                                 $children[$depth] = 0;
1093                                         } else {
1094                                                 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_split.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
1095                                                 $children[$depth] = 1;
1096                                         }
1097
1098                                         if ($_SESSION['s_cid'] == $content['content_id']) {
1099                                                 if (is_array($this->_menu[$content['content_id']])) {
1100                                                         $_SESSION['menu'][$content['content_id']] = 1;
1101                                                 }
1102                                         }
1103
1104                                         if (isset($_SESSION['menu'][$content['content_id']]) && $_SESSION['menu'][$content['content_id']] == 1) {
1105                                                 if ($on) {
1106                                                         echo '<a href="javascript:void(0)" onclick="javascript: ATutor.course.toggleFolder(\''.$content['content_id'].$from.'\', \''._AT('expand').'\', \''._AT('collapse').'\', '.$this->course_id.'); "><img src="'.$_base_path.'images/tree/tree_collapse.gif" id="tree_icon'.$content['content_id'].$from.'" alt="'._AT('collapse').'" border="0" width="16" height="16" title="'._AT('collapse').'" class="img-size-tree" /></a>'."\n";
1107                                                         
1108                                                 } else {
1109                                                         echo '<a href="'.$_my_uri.'collapse='.$content['content_id'].'">'."\n";
1110                                                         echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_collapse.gif" id="tree_icon'.$content['content_id'].$from.'" alt="'._AT('collapse').'" border="0" width="16" height="16" title="'._AT('collapse').' '.$content['title'].'" class="img-size-tree" onclick="javascript: ATutor.course.toggleFolder(\''.$content['content_id'].$from.'\', \''._AT('expand').'\', \''._AT('collapse').'\', '.$this->course_id.'); " />'."\n";
1111                                                         echo '</a>'."\n";
1112                                                 }
1113                                         } else {
1114                                                 if ($on) {
1115                                                         echo '<a href="javascript:void(0)" onclick="javascript: ATutor.course.toggleFolder(\''.$content['content_id'].$from.'\', \''._AT('expand').'\', \''._AT('collapse').'\', '.$this->course_id.'); "><img src="'.$_base_path.'images/tree/tree_collapse.gif" id="tree_icon'.$content['content_id'].$from.'" alt="'._AT('collapse').'" border="0" width="16" height="16" title="'._AT('collapse').'" class="img-size-tree" /></a>'."\n";
1116                                                         
1117                                                 } else {
1118                                                         echo '<a href="'.$_my_uri.'expand='.$content['content_id'].'">'."\n";
1119                                                         echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_expand.gif" id="tree_icon'.$content['content_id'].$from.'" alt="'._AT('expand').'" border="0" width="16" height="16"    title="'._AT('expand').' '.$content['title'].'" class="img-size-tree" onclick="javascript: ATutor.course.toggleFolder(\''.$content['content_id'].$from.'\', \''._AT('expand').'\', \''._AT('collapse').'\', '.$this->course_id.'); " />';
1120                                                         echo '</a>'."\n";
1121                                                 }
1122                                         }
1123
1124                                 } else {
1125                                         /* doesn't have children */
1126                                         if ($counter == $num_items) {
1127                                                 for ($i=0; $i<$depth; $i++) {
1128                                                         if ($children[$i] == 1) {
1129                                                                 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_vertline.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
1130                                                         } else {
1131                                                                 echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
1132                                                         }
1133                                                 }
1134                                                 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_end.gif" alt="" border="0" class="img-size-tree" />'."\n";
1135                                         } else {
1136                                                 for ($i=0; $i<$depth; $i++) {
1137                                                         if ($children[$i] == 1) {
1138                                                                 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_vertline.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
1139                                                         } else {
1140                                                                 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_space.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
1141                                                         }
1142                                                 }
1143                                                 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_split.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
1144                                         }
1145                                         echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_horizontal.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />'."\n";
1146                                 }
1147
1148                                 
1149                                 echo $link;
1150                                 
1151                                 echo "\n<br /></span>\n\n";
1152                                 
1153                                 if ( $ignore_state || (isset($_SESSION['menu'][$content['content_id']]) && $_SESSION['menu'][$content['content_id']] == 1)) {
1154
1155                                         $depth ++;
1156
1157                                         $this->printMenu($content['content_id'],
1158                                                                                 $depth, 
1159                                                                                 $path.$counter.'.', 
1160                                                                                 $children,
1161                                                                                 $truncate, 
1162                                                                                 $ignore_state,
1163                                                                                 $from);
1164
1165                                                                                 
1166                                         $depth--;
1167
1168                                 }
1169                                 $counter++;
1170                         } // end of foreach
1171
1172                         print "</div>\n\n";
1173                 }
1174         }
1175
1176         /* @See include/html/editor_tabs/properties.inc.php
1177            @See editor/arrange_content.php
1178            
1179             $print_type: "movable" or "related_content"
1180          */
1181         function printActionMenu($menu, $parent_id, $depth, $path, $children, $print_type = 'movable') {
1182                 
1183                 global $cid, $_my_uri, $_base_path, $rtl;
1184
1185                 static $end;
1186
1187                 $top_level = $menu[$parent_id];
1188
1189                 if ( is_array($top_level) ) {
1190                         $counter = 1;
1191                         $num_items = count($top_level);
1192                         foreach ($top_level as $current_num => $content) {
1193                                 if (isset($content['test_id'])){
1194                                         continue;
1195                                 }
1196
1197                                 $link = $buttons = '';
1198
1199                                 echo '<tr>'."\n";
1200                                 
1201                                 if ($print_type == 'movable')
1202                                 {
1203                                         if ($content['content_id'] == $_POST['moved_cid']) {
1204                                                 $radio_selected = ' checked="checked" ';
1205                                         }
1206                                         else {
1207                                                 $radio_selected = '';
1208                                         }
1209                                 
1210                                         $buttons = '<td>'."\n".
1211                                                    '   <small>'."\n".
1212                                                    '      <input type="image" name="move['.$parent_id.'_'.$content['ordering'].']" src="'.$_base_path.'images/before.gif" alt="'._AT('before_topic', $content['title']).'" title="'._AT('before_topic', $content['title']).'" style="height:1.5em; width:1.9em;" />'."\n";
1213
1214                                         if ($current_num + 1 == count($top_level))
1215                                                 $buttons .= '      <input type="image" name="move['.$parent_id.'_'.($content['ordering']+1).']" src="'.$_base_path.'images/after.gif" alt="'._AT('after_topic', $content['title']).'" title="'._AT('after_topic', $content['title']).'" style="height:1.5em; width:1.9em;" />'."\n";
1216                                         
1217                                         $buttons .= '   </small>'."\n".
1218                                                    '</td>'."\n".
1219                                                    '<td>';
1220                                         
1221                                         if ($content['content_type'] == CONTENT_TYPE_FOLDER)
1222                                                 $buttons .= '<input type="image" name="move['.$content['content_id'].'_1]" src="'.$_base_path.'images/child_of.gif" style="height:1.25em; width:1.7em;" alt="'._AT('child_of', $content['title']).'" title="'._AT('child_of', $content['title']).'" />';
1223                                         else
1224                                                 $buttons .= '&nbsp;';
1225                                                 
1226                                         $buttons .= '</td>'."\n".
1227                                                    '<td><input name="moved_cid" value="'.$content['content_id'].'" type="radio" id="r'.$content['content_id'].'" '.$radio_selected .'/></td>'."\n";
1228                                 }
1229                                 
1230                                 $buttons .= '<td>'."\n";
1231                                 if ($print_type == "related_content")
1232                                 {
1233                                         if ($content['content_type'] == CONTENT_TYPE_CONTENT || $content['content_type'] == CONTENT_TYPE_WEBLINK)
1234                                         {
1235                                                 $link .= '<input type="checkbox" name="related[]" value="'.$content['content_id'].'" id="r'.$content['content_id'].'" ';
1236                                                 if (isset($_POST['related']) && in_array($content['content_id'], $_POST['related'])) {
1237                                                         $link .= ' checked="checked"';
1238                                                 }
1239                                                 $link .= ' />'."\n";
1240                                         }
1241                                 }       
1242                                 
1243                                 if ($content['content_type'] == CONTENT_TYPE_FOLDER)
1244                                 {
1245                                         $link .= '<img src="'.$_base_path.'images/folder.gif" />';
1246                                 }
1247                                 $link .= '&nbsp;<label for="r'.$content['content_id'].'">'.$content['title'].'</label>'."\n";
1248
1249                                 if ( is_array($menu[$content['content_id']]) && !empty($menu[$content['content_id']]) ) {
1250                                         /* has children */
1251
1252                                         for ($i=0; $i<$depth; $i++) {
1253                                                 if ($children[$i] == 1) {
1254                                                         echo $buttons;
1255                                                         unset($buttons);
1256                                                         if ($end && ($i==0)) {
1257                                                                 echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />';
1258                                                         } else {
1259                                                                 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_vertline.gif" alt="" border="0" width="16" height="16" />';
1260                                                         }
1261                                                 } else {
1262                                                         echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />';
1263                                                 }
1264                                         }
1265
1266                                         if (($counter == $num_items) && ($depth > 0)) {
1267                                                 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_end.gif" alt="" border="0" width="16" height="16" />';
1268                                                 $children[$depth] = 0;
1269                                         } else {
1270                                                 echo $buttons;
1271                                                 if (($num_items == $counter) && ($parent_id == 0)) {
1272                                                         echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_end.gif" alt="" border="0" width="16" height="16" />';
1273                                                         $end = true;
1274                                                 } else {
1275                                                         echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_split.gif" alt="" border="0" width="16" height="16" />';
1276                                                 }
1277                                                 $children[$depth] = 1;
1278                                         }
1279
1280                                         if ($_SESSION['s_cid'] == $content['content_id']) {
1281                                                 if (is_array($menu[$content['content_id']])) {
1282                                                         $_SESSION['menu'][$content['content_id']] = 1;
1283                                                 }
1284                                         }
1285
1286                                         if ($_SESSION['menu'][$content['content_id']] == 1) {
1287                                                 echo '<img src="'.$_base_path.'images/tree/tree_disabled.gif" alt="'._AT('toggle_disabled').'" border="0" width="16" height="16" title="'._AT('toggle_disabled').'" />';
1288
1289                                         } else {
1290                                                 echo '<img src="'.$_base_path.'images/tree/tree_disabled.gif" alt="'._AT('toggle_disabled').'" border="0" width="16" height="16" title="'._AT('toggle_disabled').'" />';
1291                                         }
1292
1293                                 } else {
1294                                         /* doesn't have children */
1295                                         if ($counter == $num_items) {
1296                                                 if ($depth) {
1297                                                         echo $buttons;
1298                                                         for ($i=0; $i<$depth; $i++) {
1299                                                                 if ($children[$i] == 1) {
1300                                                                         if ($end && ($i == 0)) {
1301                                                                                 echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />';
1302                                                                         } else {
1303                                                                                 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_vertline.gif" alt="" border="0" width="16" height="16" />';
1304                                                                         }
1305                                                                 } else {
1306                                                                         echo '<img src="'.$_base_path.'images/clr.gif" alt="" border="0" width="16" height="16" class="img-size-tree" />';
1307                                                                 }
1308                                                         }
1309                                                 } else {
1310                                                         echo $buttons;
1311                                                 }
1312                                                 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_end.gif" alt="" border="0" />';
1313                                         } else {
1314                                                 if ($depth) {
1315                                                         echo $buttons;
1316                                                         $print = false;
1317                                                         for ($i=0; $i<$depth; $i++) {
1318                                                                 if ($children[$i] == 1) {
1319                                                                         if ($end && !$print) {
1320                                                                                 $print = true;
1321                                                                                 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_space.gif" alt="" border="0" width="16" height="16" />';
1322                                                                         } else {
1323                                                                                 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_vertline.gif" alt="" border="0" width="16" height="16" />';
1324                                                                         }
1325                                                                 } else {
1326                                                                         echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_space.gif" alt="" border="0" width="16" height="16" />';
1327                                                                 }
1328                                                         }
1329                                                         $print = false;
1330                                                 } else {
1331                                                         echo $buttons;
1332                                                 }
1333                 
1334                                                 echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_split.gif" alt="" border="0" width="16" height="16" />';
1335                                         }
1336                                         echo '<img src="'.$_base_path.'images/'.$rtl.'tree/tree_horizontal.gif" alt="" border="0" width="16" height="16" />';
1337                                 }
1338
1339                                 echo '<small>';
1340                                   if($_SESSION['prefs']['PREF_NUMBERING']){
1341                                         echo $path.$counter;
1342                                     }
1343                                 
1344                                 echo $link;
1345                                 
1346                                 echo '</small></td>'."\n".'</tr>'."\n";
1347
1348                                 $this->printActionMenu($menu,
1349                                                                         $content['content_id'],
1350                                                                         ++$depth, 
1351                                                                         $path.$counter.'.', 
1352                                                                         $children,
1353                                                                         $print_type);
1354                                 $depth--;
1355
1356                                 $counter++;
1357                         }
1358                 }
1359         }
1360
1361         /* returns the timestamp of release if this page has not yet been released, or is under a page that has not been released, true otherwise */
1362         /* finds the max(timestamp) of all parents and returns that, true if less than now */
1363         /* Access: public */
1364         function isReleased($cid) {
1365                 if ($this->_menu_info[$cid]['content_parent_id'] == 0) {
1366                         // this $cid has no parent, so we check its release date directly
1367                         if ($this->_menu_info[$cid]['u_release_date'] <= time()) {      
1368                                 // yup! it's released
1369                                 return true;
1370                         } else {
1371                                 // nope! not released
1372                                 return $this->_menu_info[$cid]['u_release_date'];
1373                         }
1374                 }
1375                 // this is a sub page, need to check ALL its parents
1376                 $parent = $this->isReleased($this->_menu_info[$cid]['content_parent_id']); // recursion
1377
1378                 if ($parent !== TRUE && $parent > $this->_menu_info[$cid]['u_release_date']) {
1379                         return $parent;
1380                 } else if ($this->_menu_info[$cid]['u_release_date'] <= time()) {
1381                         return true;
1382                 } else {
1383                         return $this->_menu_info[$cid]['u_release_date'];
1384                 }
1385         }
1386
1387         /* returns the first test_id if this page has pre-test(s) to be passed, 
1388          * or is under a page that has pre-test(s) to be passed, 
1389          * 0 if has no pre-test(s) to be passed
1390          * -1 if one of the pre-test(s) has expired, the content should not be displayed in this case
1391          * Access: public 
1392          */
1393         function getPretest($cid) {
1394                 $this_pre_test_id = $this->getOnePretest($cid);
1395                 
1396                 if ($this->_menu_info[$cid]['content_parent_id'] == 0) {
1397                         // this $cid has no parent, so we check its release date directly
1398                         return $this_pre_test_id;
1399                 }
1400                 
1401                 // this is a sub page, need to check ALL its parents
1402                 $parent_pre_test_id = $this->getOnePretest($this->_menu_info[$cid]['content_parent_id']);
1403                 
1404                 if ($this_pre_test_id > 0 || $this_pre_test_id == -1)
1405                         return $this_pre_test_id;
1406                 else if ($parent_pre_test_id > 0 || $parent_pre_test_id == -1)
1407                         return $parent_pre_test_id;
1408                 else
1409                         return 0;
1410         }
1411
1412         /* returns the first test_id if this content has pre-test(s) to be passed, 
1413          * 0 if has no pre-test(s) to be passed
1414          * -1 if one of the pre-test(s) has expired, the content should not be displayed in this case
1415          * Access: public 
1416          */
1417         function getOnePretest($cid) {
1418                 global $db, $msg;
1419                 include_once(AT_INCLUDE_PATH.'../mods/_standard/tests/lib/test_result_functions.inc.php');
1420                 
1421                 $sql = "SELECT *, UNIX_TIMESTAMP(t.start_date) AS start_date, UNIX_TIMESTAMP(t.end_date) AS end_date 
1422                           FROM ".TABLE_PREFIX."tests t, ".TABLE_PREFIX."content_prerequisites cp
1423                          WHERE cp.content_id=".$cid."
1424                            AND cp.type = '".CONTENT_PRE_TEST."'
1425                            AND cp.item_id=t.test_id";
1426                 $result= mysql_query($sql, $db);
1427                 
1428                 while ($row = mysql_fetch_assoc($result))
1429                 {
1430                         // check to make sure we can access this test
1431                         if (!$row['guests'] && ($_SESSION['enroll'] == AT_ENROLL_NO || $_SESSION['enroll'] == AT_ENROLL_ALUMNUS)) {
1432                                 $msg->addInfo('NOT_ENROLLED');
1433                         }
1434                         
1435                         if (!$row['guests'] && !authenticate_test($row['test_id'])) {
1436                                 $msg->addInfo(array('PRETEST_NO_PRIV',$row['title']));
1437                         }
1438                         
1439                         // if the test is not release, not allow student to view the content
1440                         if ($row['start_date'] > time() || $row['end_date'] < time()) {
1441                                 $msg->addInfo(array('PRETEST_EXPIRED',$row['title']));
1442                                 return -1;
1443                         }
1444                         
1445                         $sql = "SELECT tr.result_id, count(*) num_of_questions, sum(ta.score) score, sum(tqa.weight) total_weight
1446                                   FROM ".TABLE_PREFIX."tests_results tr, ".TABLE_PREFIX."tests_answers ta, ".TABLE_PREFIX."tests_questions_assoc tqa 
1447                                  WHERE tr.test_id = ".$row['test_id']."
1448                                    AND tr.member_id = ".$_SESSION['member_id']."
1449                                    AND tr.result_id = ta.result_id
1450                                    AND tr.test_id = tqa.test_id
1451                                    AND ta.question_id = tqa.question_id
1452                                  GROUP BY tr.result_id";
1453                         $result_score = mysql_query($sql, $db);
1454                         
1455                         $num_of_attempts = 0;
1456                         while ($row_score = mysql_fetch_assoc($result_score))
1457                         {
1458                                 // skip the test when:
1459                                 // 1. no pass score is defined. this is a survey.
1460                                 // 2. the student has passed the test 
1461                                 // 3. the test has no question
1462                                 if (($row['passscore'] == 0 && $row['passpercent'] == 0) ||
1463                                     $row_score['num_of_questions'] == 0 ||
1464                                     ($row['passscore']<>0 && $row_score['score']>=$row['passscore']) || 
1465                                     ($row['passpercent']<>0 && ($row_score['score']/$row_score['total_weight']*100)>=$row['passpercent']))
1466                                     continue 2;
1467                                 
1468                                 $num_of_attempts++;
1469                         }
1470                         
1471                         if ($row['num_takes'] != AT_TESTS_TAKE_UNLIMITED && $num_of_attempts >= $row['num_takes'])
1472                         {
1473                                 $msg->addInfo(array('PRETEST_FAILED',$row['title']));
1474                         }
1475                         else
1476                                 return $row['test_id'];
1477                 }
1478                 return 0;
1479         }
1480
1481         /** 
1482          * Return true if this content page allows export, else false.
1483          * @param       int     content id
1484          * @return      true if 'allow_test_export'==1 || is instructor || oauth export into Transformable
1485          */
1486         function allowTestExport($content_id){
1487                 if (isset($_SESSION['is_admin']) || (isset($_REQUEST['m']) && isset($_REQUEST['c']))) {
1488                         return true;
1489                 }
1490                 $sql = "SELECT allow_test_export FROM ".TABLE_PREFIX."content WHERE content_id=$content_id";
1491                 $result = mysql_query($sql, $this->db);
1492                 if ($row = mysql_fetch_assoc($result)){
1493                         if ($row['allow_test_export'] == 1){
1494                                 return true;
1495                         }
1496                         return false;
1497                 }
1498                 return false;
1499         }
1500
1501         /**
1502          * This function returns an array of content tools' shortcuts
1503          * @access: public
1504          * @param: $content_row: an array of the current content information
1505          * @return: an array of all the tool shortcuts that apply to the current content or content folder
1506          */
1507         public static function getToolShortcuts($content_row)
1508         {
1509                 global $_base_href, $contentManager;
1510                 
1511                 $shortcuts = array();
1512                 if ((   ($content_row['r_date'] <= $content_row['n_date'])
1513                                 && ((!$content_row['content_parent_id'] && ($_SESSION['packaging'] == 'top'))
1514                                         || ($_SESSION['packaging'] == 'all'))
1515                         ) || authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN)) {
1516                         $shortcuts[] = array('title' => _AT('export_content'), 'url' => $_base_href . 'mods/_core/imscp/ims_export.php?cid='.$content_row['content_id'], 'icon' => $_base_href . 'images/download.png');
1517                 }
1518                 
1519                 if (authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN)) {
1520                         if ($content_row['content_type'] == CONTENT_TYPE_CONTENT) {
1521                                 $shortcuts[] = array(
1522                                 'title' => _AT('edit_this_page'),   
1523                                 'url' => $_base_href . 'mods/_core/editor/edit_content.php?cid='.$content_row['content_id'],
1524                                 'icon' => $_base_href . 'images/medit.gif');
1525                         }
1526                         $shortcuts[] = array(
1527                                 'title' => _AT('add_sibling_folder'), 
1528                                 'url' => $_base_href.'mods/_core/editor/edit_content_folder.php?pid='.$contentManager->_menu_info[$content_row['content_id']]['content_parent_id'], 
1529                                 'icon' => $_base_href . 'images/folder_new_sibling.gif');
1530                 
1531                         if ($content_row['content_type'] == CONTENT_TYPE_FOLDER) {
1532                                 $shortcuts[] = array(
1533                                         'title' => _AT('add_sub_folder'),   
1534                                         'url' => $_base_href . 'mods/_core/editor/edit_content_folder.php?pid='.$content_row['content_id'], 
1535                                         'icon' => $_base_href . 'images/folder_new_sub.gif');
1536                         }
1537                         
1538                         $shortcuts[] = array(
1539                                 'title' => _AT('add_sibling_page'), 
1540                                 'url' => $_base_href.'mods/_core/editor/edit_content.php?pid='.$contentManager->_menu_info[$content_row['content_id']]['content_parent_id'], 
1541                                 'icon' => $_base_href . 'images/page_add_sibling.gif');
1542
1543                         if ($content_row['content_type'] == CONTENT_TYPE_CONTENT) {
1544                                 $shortcuts[] = array(
1545                                         'title' => _AT('delete_this_page'), 
1546                                         'url' => $_base_href . 'mods/_core/editor/delete_content.php?cid='.$content_row['content_id'], 
1547                                         'icon' => $_base_href . 'images/page_delete.gif');
1548                         }
1549                         else if ($content_row['content_type'] == CONTENT_TYPE_FOLDER) {
1550                                 $shortcuts[] = array(
1551                                         'title' => _AT('add_sub_page'),     
1552                                         'url' => $_base_href . 'mods/_core/editor/edit_content.php?pid='.$content_row['content_id'], 
1553                                         'icon' => $_base_href . 'images/page_add_sub.gif');
1554                                 $shortcuts[] = array(
1555                                         'title' => _AT('delete_this_folder'), 
1556                                         'url' => $_base_href . 'mods/_core/editor/delete_content.php?cid='.$content_row['content_id'], 
1557                                         'icon' => $_base_href . 'images/page_delete.gif');
1558                         }
1559                 }
1560                 
1561                 return $shortcuts;
1562         }
1563 }
1564
1565 ?>