MDL-18910 moving modedit features to modname_supports()
[moodle.git] / mod / wiki / lib.php
1 <?php  // $Id$
3 /// Library of functions and constants for module wiki
4 /// (replace wiki with the name of your module and delete this line)
7 $wiki_CONSTANT = 7;     /// for example
8 $site = get_site();
9 $WIKI_TYPES = array ('teacher' =>   get_string('defaultcourseteacher'),
10                      'group' =>     get_string('groups',"wiki"),
11                      'student' =>   get_string('defaultcoursestudent') );
12 define("EWIKI_ESCAPE_AT", 0);       # For the algebraic filter
14 // How long locks stay around without being confirmed (seconds)
15 define("WIKI_LOCK_PERSISTENCE",120);
17 // How often to confirm that you still want a lock
18 define("WIKI_LOCK_RECONFIRM",60);
20 // Session variable used to store wiki locks
21 define('SESSION_WIKI_LOCKS','wikilocks');
23 /*** Moodle 1.7 compatibility functions *****
24  *
25  ********************************************/
26 function wiki_context($wiki) {
27     //TODO: add some $cm caching if needed
28     if (is_object($wiki)) {
29         $wiki = $wiki->id;
30     }
31     if (! $cm = get_coursemodule_from_instance('wiki', $wiki)) {
32         print_error('invalidcoursemodule');
33     }
35     return get_context_instance(CONTEXT_MODULE, $cm->id);
36 }
38 function wiki_is_teacher($wiki, $userid=NULL) {
39     return has_capability('mod/wiki:manage', wiki_context($wiki), $userid);
40 }
42 function wiki_is_teacheredit($wiki, $userid=NULL) {
43     return has_capability('mod/wiki:manage', wiki_context($wiki), $userid)
44        and has_capability('moodle/site:accessallgroups', wiki_context($wiki), $userid);
45 }
47 function wiki_is_student($wiki, $userid=NULL) {
48     return has_capability('mod/wiki:participate', wiki_context($wiki), $userid);
49 }
51 function wiki_get_students($wiki, $groups='', $sort='u.lastaccess', $fields='u.*') {
52     return $users = get_users_by_capability(wiki_context($wiki), 'mod/wiki:participate', $fields, $sort, '', '', $groups);
53 }
55 /* end of compatibility functions */
58 function wiki_add_instance($wiki) {
59     global $DB;
60 /// Given an object containing all the necessary data,
61 /// (defined by the form in mod_form.php) this function
62 /// will create a new instance and return the id number
63 /// of the new instance.
65     $wiki->timemodified = time();
67     # May have to add extra stuff in here #
69     /// Determine the pagename for this wiki and save.
70     $wiki->pagename = wiki_page_name($wiki);
72     return $DB->insert_record("wiki", $wiki);
73 }
76 function wiki_update_instance($wiki) {
77     global $DB;
78 /// Given an object containing all the necessary data,
79 /// (defined by the form in mod_form.php) this function
80 /// will update an existing instance with new data.
82     /// Determine the pagename for this wiki.
83     $wiki->pagename = wiki_page_name($wiki);
85     $wiki->timemodified = time();
86     $wiki->id = $wiki->instance;
87     return $DB->update_record("wiki", $wiki);
88 }
90 /// Delete all Directories recursively
91 function wiki_rmdir($basedir) {
92   $handle = @opendir($basedir);
93   if($handle) {
94     while (false!==($folder = readdir($handle))) {
95        if($folder != "." && $folder != ".." && $folder != "CVS") {
96           wiki_rmdir("$basedir/$folder");  // recursive
97        }
98     }
99     closedir($handle);
100   }
101   @rmdir($basedir);
104 function wiki_delete_instance($id) {
105 /// Given an ID of an instance of this module,
106 /// this function will permanently delete the instance
107 /// and any data that depends on it.
108     global $CFG, $DB;
110     if (! $wiki = $DB->get_record("wiki", array("id"=>$id))) {
111         return false;
112     }
114     $result = true;
116     #Delete Files
117 ### Should probably check regardless of this setting in case its been changed...
118     if($wiki->ewikiacceptbinary) {
119       if ($basedir = $CFG->dataroot."/".$wiki->course."/".$CFG->moddata."/wiki/$id") {
120           if ($files = get_directory_list($basedir)) {
121               foreach ($files as $file) {
122                   #if ($file != $exception) {
123                       unlink("$basedir/$file");
124                       notify("Existing file '$file' has been deleted!");
125                   #}
126               }
127           }
128           #if (!$exception) {  // Delete directory as well, if empty
129               wiki_rmdir("$basedir");
130           #}
131       }
132     }
134     # Delete any dependent records here #
135     if(!$DB->delete_records("wiki_locks", array("wikiid"=>$wiki->id))) {
136         $result = false;
137     }
139     if (! $DB->delete_records("wiki", array("id"=>$wiki->id))) {
140         $result = false;
141     }
143     /// Delete all wiki_entries and wiki_pages.
144     if (($wiki_entries = wiki_get_entries($wiki)) !== false) {
145         foreach ($wiki_entries as $wiki_entry) {
146             if (! $DB->delete_records("wiki_pages", array("wiki"=>$wiki_entry->id))) {
147                 $result = false;
148             }
149             if (! $DB->delete_records("wiki_entries", array("id"=>$wiki_entry->id))) {
150                 $result = false;
151             }
152         }
153     }
155     return $result;
158 function wiki_user_outline($course, $user, $mod, $wiki) {
159 /// Return a small object with summary information about what a
160 /// user has done with a given particular instance of this module
161 /// Used for user activity reports.
162 /// $return->time = the time they did it
163 /// $return->info = a short text description
165     $return = NULL;
166     return $return;
169 function wiki_user_complete($course, $user, $mod, $wiki) {
170 /// Print a detailed representation of what a  user has done with
171 /// a given particular instance of this module, for user activity reports.
173     return true;
176 function wiki_print_recent_activity($course, $isteacher, $timestart) {
177 /// Given a course and a time, this module should find recent activity
178 /// that has occurred in wiki activities and print it out.
179 /// Return true if there was output, or false is there was none.
181     global $CFG, $DB;
182     
183     $sql = "SELECT l.*, cm.instance
184               FROM {log} l JOIN {course_modules} cm ON l.cmid = cm.id 
185              WHERE l.time > ? AND l.course = ? 
186                    AND l.module = 'wiki' AND action LIKE 'edit%'
187           ORDER BY l.time ASC";
188             
189     if (!$logs = $DB->get_records_sql($sql, array($timestart, $course->id))){
190         return false;
191     }
193     $modinfo = get_fast_modinfo($course);
194     $wikis = array();
196     foreach ($logs as $log) {
197         $cm = $modinfo->instances['wiki'][$log->instance];
198         if (!$cm->uservisible) {
199             continue;
200         }
202     /// Process log->url and rebuild it here to properly clean the pagename - MDL-15896
203         $extractedpage = preg_replace('/^.*&page=/', '', $log->url);
204         $log->url = preg_replace('/page=.*$/', 'page='.urlencode($extractedpage), $log->url);
206         $wikis[$log->info] = wiki_log_info($log);
207         $wikis[$log->info]->pagename = $log->info;
208         $wikis[$log->info]->time = $log->time;
209         $wikis[$log->info]->url  = str_replace('&', '&amp;', $log->url);
210     }
212     if (!$wikis) {
213         return false;
214     }
215     print_headline(get_string('updatedwikipages', 'wiki').':', 3);
216     foreach ($wikis as $wiki) {
217         print_recent_activity_note($wiki->time, $wiki, $wiki->pagename,
218                                    $CFG->wwwroot.'/mod/wiki/'.$wiki->url);
219     }
221     return false;
224 function wiki_log_info($log) {
225     global $CFG, $DB;
226     return $DB->get_record_sql("SELECT u.firstname, u.lastname
227                                   FROM {user} u
228                                  WHERE u.id = ?", array($log->userid));
231 function wiki_cron () {
232 /// Function to be run periodically according to the moodle cron
233 /// This function searches for things that need to be done, such
234 /// as sending out mail, toggling flags etc ...
235     global $DB;
237     // Delete expired locks
238     $result = $DB->delete_records_select('wiki_locks','lockedseen < '.(time()-WIKI_LOCK_PERSISTENCE));
240     return $result;
243 function wiki_grades($wikiid) {
244 /// Must return an array of grades for a given instance of this module,
245 /// indexed by user.  It also returns a maximum allowed grade.
247     return NULL;
250 function wiki_get_participants($wikiid) {
251 //Returns the users with data in one wiki
252 //(users with records in wiki_pages and wiki_entries)
253     global $CFG, $DB;
255     //Get users from wiki_pages
256     $st_pages = $DB->get_records_sql("SELECT DISTINCT u.id, u.id
257                                         FROM {user} u, {wiki_entries} e, {wiki_pages} p
258                                         WHERE e.wikiid = ? and
259                                               p.wiki = e.id and
260                                               u.id = p.userid", array($wikiid));
262     //Get users from wiki_entries
263     $st_entries = $DB->get_records_sql("SELECT DISTINCT u.id, u.id
264                                           FROM {user} u, {wiki_entries} e
265                                          WHERE e.wikiid = ? and
266                                                u.id = e.userid", array($wikiid));
268     //Add entries to pages
269     if ($st_entries) {
270         foreach ($st_entries as $st_entry) {
271             $st_pages[$st_entry->id] = $st_entry;
272         }
273     }
275     return $st_pages;
279 //////////////////////////////////////////////////////////////////////////////////////
280 /// Any other wiki functions go here.  Each of them must have a name that
281 /// starts with wiki_
283 function wiki_wiki_name($wikiname) {
284 /// Return the passed in string in Wiki name format.
285 /// Remove any leading and trailing whitespace, capitalize all the words
286 /// and then remove any internal whitespace.
288     if (wiki_is_wiki_name($wikiname)) {
289         return $wikiname;
290     }
291     else {
292         /// Create uppercase words and remove whitespace.
293         $wikiname = preg_replace("/(\w+)\s/", "$1", ucwords(trim($wikiname)));
295         /// Check again - there may only be one word.
296         if (wiki_is_wiki_name($wikiname)) {
297             return $wikiname;
298         }
299         /// If there is only one word, append default wiki name to it.
300         else {
301             return $wikiname.get_string('wikidefaultpagename', 'wiki');
302         }
303     }
306 function wiki_is_wiki_name($wikiname) {
307 /// Check for correct wikiname syntax and return true or false.
309     /// If there are spaces between the words, incorrect format.
310     if (preg_match_all('/\w+/', $wikiname, $out) > 1) {
311         return false;
312     }
313     /// If there isn't more than one group of uppercase letters separated by
314     /// lowercase letters or '_', incorrect format.
315     else if (preg_match_all('/[A-Z]+[a-z_]+/', $wikiname, $out) > 1) {
316         return true;
317     }
318     else {
319         return false;
320     }
323 function wiki_page_name(&$wiki) {
324 /// Determines the wiki's page name and returns it.
325     if (!empty($wiki->initialcontent)) {
326         $ppos = strrpos($wiki->initialcontent, '/');
327         if ($ppos === false) {
328             $pagename = $wiki->initialcontent;
329         }
330         else {
331             $pagename = substr($wiki->initialcontent, $ppos+1);
332         }
333     }
334     else if (!empty($wiki->pagename)) {
335         $pagename = $wiki->pagename;
336     }
337     else {
338         $pagename = $wiki->name;
339     }
340     return $pagename;
343 function wiki_content_dir(&$wiki) {
344 /// Determines the wiki's default content directory (if there is one).
345     global $CFG;
347     if (!empty($wiki->initialcontent)) {
348         $ppos = strrpos($wiki->initialcontent, '/');
349         if ($ppos === false) {
350             $subdir = '';
351         }
352         else {
353             $subdir = substr($wiki->initialcontent, 0, $ppos+1);
354         }
355         $contentdir = $CFG->dataroot.'/'.$wiki->course.'/'.$subdir;
356     }
357     else {
358         $contentdir = false;
359     }
360     return $contentdir;
363 function wiki_get_course_wikis($courseid, $wtype='*') {
364 /// Returns all wikis for the specified course and optionally of the specified type.
365     global $DB;
367     $select = 'course = ?';
368     $params = array($courseid);
369     if ($wtype != '*') {
370         $select .= ' AND wtype = ?';
371         $params[] = $wtype;
372     }
373     return $DB->get_records_select('wiki', $select, $params, 'id');
376 function wiki_has_entries(&$wiki) {
377 /// Returns true if wiki already has wiki entries; otherwise false.
378     global $DB;
380     return $DB->record_exists('wiki_entries', array('wikiid'=>$wiki->id));
383 function wiki_get_entries(&$wiki, $byindex=NULL) {
384 /// Returns an array with all wiki entries indexed by entry id; false if there are none.
385 /// If the optional $byindex is specified, returns the entries indexed by that field.
386 /// Valid values for $byindex are 'student', 'group'.
387     global $CFG, $DB;
388     
389     if ($byindex == 'student') {
390         return $DB->get_records('wiki_entries', array('wikiid'=>$wiki->id), '',
391                            'userid,id,wikiid,course,groupid,pagename,timemodified');
392     }
393     else if ($byindex == 'group') {
394         return $DB->get_records('wiki_entries', array('wikiid'=>$wiki->id), '',
395                            'groupid,id,wikiid,course,userid,pagename,timemodified');
396     }
397     else {
398         return $DB->get_records('wiki_entries', array('wikiid'=>$wiki->id));
399     }
402 function wiki_get_default_entry(&$wiki, &$course, $userid=0, $groupid=0) {
403 /// Returns the wiki entry according to the wiki type.
404 /// Optionally, will return wiki entry for $userid student wiki, or
405 /// $groupid group or teacher wiki.
406 /// Creates one if it needs to and it can.
407     global $USER;
408     /// If there is a groupmode, get the user's group id.
409     $groupmode = groups_get_activity_groupmode($wiki);
410     // if groups mode is in use and no group supplied, use the first one found
411     if ($groupmode && !$groupid) {
412         if(($mygroupids=mygroupid($course->id)) && count($mygroupids)>0) {
413             // Use first group. They ought to be able to change later
414             $groupid=$mygroupids[0];
415         } else {
416             // Whatever groups are in the course, pick one
417             $coursegroups = groups_get_all_groups($course->id);
418             if(!$coursegroups || count($coursegroups)==0) {
419                 print_error('groupmodeerror', 'wiki');
420             }
421             $unkeyed=array_values($coursegroups); // Make sure first item is index 0
422             $groupid=$unkeyed[0]->id;
423         }
424     }
426     /// If the wiki entry doesn't exist, can this user create it?
427     if (($wiki_entry = wiki_get_entry($wiki, $course, $userid, $groupid)) === false) {
428         if (wiki_can_add_entry($wiki, $USER, $course, $userid, $groupid)) {
429             wiki_add_entry($wiki, $course, $userid, $groupid);
430             if (($wiki_entry = wiki_get_entry($wiki, $course, $userid, $groupid)) === false) {
431                 print_error('cannotaddentry', 'wiki');
432             }
433         }
434     }
435     //print_object($wiki_entry);
436     return $wiki_entry;
439 function wiki_get_entry(&$wiki, &$course, $userid=0, $groupid=0) {
440 /// Returns the wiki entry according to the wiki type.
441 /// Optionally, will return wiki entry for $userid student wiki, or
442 /// $groupid group or teacher wiki.
443     global $USER;
445     switch ($wiki->wtype) {
446     case 'student':
447         /// If a specific user was requested, return it, if allowed.
448         if ($userid and wiki_user_can_access_student_wiki($wiki, $userid, $course)) {
449             $wentry = wiki_get_student_entry($wiki, $userid);
450         }
452         /// If there is no entry for this user, check if this user is a teacher.
453         else if (!$wentry = wiki_get_student_entry($wiki, $USER->id)) {
454 /*            if (wiki_is_teacher($wiki, $USER->id)) {
455                 /// If this user is a teacher, return the first entry.
456                 if ($wentries = wiki_get_entries($wiki)) {
457                     $wentry = current($wentries);
458                 }
459             }*/
460         }
461         break;
463     case 'group':
464         /// If there is a groupmode, get the user's group id.
465         $groupmode = groups_get_activity_groupmode($wiki);
466         if($groupmode) {
467             if(!$groupid) {
468                 if(($mygroupids=mygroupid($course->id)) && count($mygroupids)>0) {
469                     // Use first group. They ought to be able to change later
470                     $groupid=$mygroupids[0];
471                 } else {
472                     // Whatever groups are in the course, pick one
473                     $coursegroups = groups_get_all_groups($course->id);
474                     if(!$coursegroups || count($coursegroups)==0) {
475                         print_error('groupmodeerror', 'wiki');
476                     }
477                     $unkeyed=array_values($coursegroups); // Make sure first item is index 0
478                     $groupid=$unkeyed[0]->id;
479                 }
480             }
482             //echo "groupid is in wiki_get_entry ".$groupid."<br />";
483             /// If a specific group was requested, return it, if allowed.
484             if ($groupid and wiki_user_can_access_group_wiki($wiki, $groupid, $course)) {
485                 $wentry = wiki_get_group_entry($wiki, $groupid);
486             } else {
487                 print_error('cannotaccessgroup', 'wiki');
488             }
489         }
490         /// If mode is 'nogroups', then groupid is zero.
491         else {
492             $wentry = wiki_get_group_entry($wiki, 0);
493         }
494         break;
496     case 'teacher':
497         /// If there is a groupmode, get the user's group id.
498         if (groupmode($course, $wiki)) {
499             $mygroupids = mygroupid($course->id);//same here, default to the first one
500             $groupid = $groupid ? $groupid : $mygroupids[0]/*mygroupid($course->id)*/;
501         }
503         /// If a specific group was requested, return it, if allowed.
504         if (wiki_user_can_access_teacher_wiki($wiki, $groupid, $course)) {
505             $wentry = wiki_get_teacher_entry($wiki, $groupid);
506         }
507         break;
508     }
509     return $wentry;
512 function wiki_get_teacher_entry(&$wiki, $groupid=0) {
513     global $DB;
514 /// Returns the wiki entry for the wiki teacher type.
515     return $DB->get_record('wiki_entries', array('wikiid'=>$wiki->id, 'course'=>$wiki->course, 'groupid'=>$groupid));
518 function wiki_get_group_entry(&$wiki, $groupid=null) {
519     global $DB;
520 /// Returns the wiki entry for the given group.
521     return $DB->get_record('wiki_entries', array('wikiid'=>$wiki->id, 'groupid'=>$groupid));
524 function wiki_get_student_entry(&$wiki, $userid=null) {
525 /// Returns the wiki entry for the given student.
526     global $USER, $DB;
528     if (is_null($userid)) {
529         $userid = $USER->id;
530     }
531     return $DB->get_record('wiki_entries', array('wikiid'=>$wiki->id, 'userid'=>$userid));
534 function wiki_get_other_wikis(&$wiki, &$user, &$course, $currentid=0) {
535     /// Returns a list of other wikis to display, depending on the type, group and user.
536     /// Returns the key containing the currently selected entry as well.
538     global $CFG, $id, $DB;
540     $wikis = false;
542     $groupmode = groups_get_activity_groupmode($wiki);
543     $mygroupid = mygroupid($course->id);
544     $isteacher = wiki_is_teacher($wiki, $user->id);
545     $isteacheredit = wiki_is_teacheredit($wiki, $user->id);
547     $groupingid = null;
548     $cm = new stdClass;
549     $cm->id = $wiki->cmid;
550     $cm->groupmode = $wiki->groupmode;
551     $cm->groupingid = $wiki->groupingid;
552     $cm->groupmembersonly = $wiki->groupmembersonly;
553     if (!empty($CFG->enablegroupings) && !empty($cm->groupingid)) {
554         $groupingid = $wiki->groupingid;
555     }
556     
557     
558     switch ($wiki->wtype) {
560     case 'student':
561         /// Get all the existing entries for this wiki.
562         $wiki_entries = wiki_get_entries($wiki, 'student');
563         
564         if (!empty($CFG->enablegroupings) && !empty($wiki->groupingid)) {
565             $sql = "SELECT gm.userid FROM {groups_members} gm " .
566                     "INNER JOIN {groupings_groups} gg ON gm.groupid = gg.groupid " .
567                     "WHERE gg.groupingid = ? ";
568     
569             $groupingmembers = $DB->get_records_sql($sql, array($wiki->groupingid));
570         }
571         
572         if ($isteacher and (SITEID != $course->id)) {
574             /// If the user is an editing teacher, or a non-editing teacher not assigned to a group, show all student
575             /// wikis, regardless of creation.
576             if ((SITEID != $course->id) and ($isteacheredit or ($groupmode == NOGROUPS))) {
577                 if ($students = get_users_by_capability(get_context_instance(CONTEXT_COURSE, $course->id), 'moodle/course:view', '', '', '', '', '', '', false)) {
578                     /// Default pagename is dependent on the wiki settings.
579                     $defpagename = empty($wiki->pagename) ? get_string('wikidefaultpagename', 'wiki') : $wiki->pagename;
581                     foreach ($students as $student) {
582                         if (!empty($CFG->enablegroupings) && !empty($wiki->groupingid) && empty($groupingmembers[$student->id])) {
583                             continue;
584                         }
585                         /// If this student already has an entry, use its pagename.
586                         if ($wiki_entries[$student->id]) {
587                             $pagename = $wiki_entries[$student->id]->pagename;
588                         }
589                         else {
590                             $pagename = $defpagename;
591                         }
593                         $key = 'view.php?id='.$id.'&userid='.$student->id.'&page='.$pagename;
594                         $wikis[$key] = fullname($student).':'.$pagename;
595                     }
596                 }
597             }
598             else if ($groupmode == SEPARATEGROUPS) {
600                 if ($students = wiki_get_students($wiki, $mygroupid)) {
601                     $defpagename = empty($wiki->pagename) ? get_string('wikidefaultpagename', 'wiki') : $wiki->pagename;
602                     foreach ($students as $student) {
603                         if (!empty($CFG->enablegroupings) && !empty($wiki->groupingid) && empty($groupingmembers[$student->id])) {
604                             continue;
605                         }
606                         /// If this student already has an entry, use its pagename.
607                         if ($wiki_entries[$student->id]) {
608                             $pagename = $wiki_entries[$student->id]->pagename;
609                         }
610                         else {
611                             $pagename = $defpagename;
612                         }
614                         $key = 'view.php?id='.$id.'&userid='.$student->id.'&page='.$pagename;
615                         $wikis[$key] = fullname($student).':'.$pagename;
616                     }
617                 }
618             }
619             else if ($groupmode == VISIBLEGROUPS) {
620                 /// Get all students in your group.
621                 if ($students = wiki_get_students($wiki, $mygroupid)) {
622                     $defpagename = empty($wiki->pagename) ? get_string('wikidefaultpagename', 'wiki') : $wiki->pagename;
623                     foreach ($students as $student) {
624                         if (!empty($CFG->enablegroupings) && !empty($wiki->groupingid) && empty($groupingmembers[$student->id])) {
625                             continue;
626                         }
627                         /// If this student already has an entry, use its pagename.
628                         if ($wiki_entries[$student->id]) {
629                             $pagename = $wiki_entries[$student->id]->pagename;
630                         }
631                         else {
632                             $pagename = $defpagename;
633                         }
634                         $key = 'view.php?id='.$id.'&userid='.$student->id.'&page='.$pagename;
635                         $wikis[$key] = fullname($student).':'.$pagename;
636                     }
637                 }
638                 /// Get all student wikis created, regardless of group.
639                 if (!empty($CFG->enablegroupings) && !empty($wiki->groupingid)) {
640                     $sql = 'SELECT w.id, w.userid, w.pagename, u.firstname, u.lastname '
641                           .'    FROM {wiki_entries} w '
642                           .'    INNER JOIN {user} u ON w.userid = u.id '
643                           .'    INNER JOIN {groups_members} gm ON gm.userid = u.id '
644                           .'    INNER JOIN {groupings_groups} gg ON gm.groupid = gg.groupid '
645                           .'    WHERE w.wikiid = ? AND gg.groupingid = ?'
646                           .'    ORDER BY w.id';
647                     $params = array($wiki->id, $wiki->groupingid);
648                 } else {
649                     $sql = 'SELECT w.id, w.userid, w.pagename, u.firstname, u.lastname '
650                           .'    FROM {wiki_entries} w, {user} u '
651                           .'    WHERE w.wikiid = ? AND u.id = w.userid '
652                           .'    ORDER BY w.id';
653                     $params = array($wiki->id);
654                 }
655                 $wiki_entries = $DB->get_records_sql($sql, $params);
656                 $wiki_entries=is_array($wiki_entries)?$wiki_entries:array();
657                 foreach ($wiki_entries as $wiki_entry) {
658                     $key = 'view.php?id='.$id.'&userid='.$wiki_entry->userid.'&page='.$wiki_entry->pagename;
659                     $wikis[$key] = fullname($wiki_entry).':'.$wiki_entry->pagename;
660                     if ($currentid == $wiki_entry->id) {
661                         $wikis['selected'] = $key;
662                     }
663                 }
664             }
665         }
666         else {
667             /// A user can see other student wikis if they are a member of the same
668             /// group (for separate groups) or there are visible groups, or if this is
669             /// a site-level wiki, and they are an administrator.
670             if (($groupmode == VISIBLEGROUPS) or wiki_is_teacheredit($wiki)) {
671                 $viewall = true;
672             }
673             else if ($groupmode == SEPARATEGROUPS) {
674                 $viewall = mygroupid($course->id);
675             }
676             else {
677                 $viewall = false;
678             }
680             if ($viewall !== false) {
681                 if (!empty($CFG->enablegroupings) && !empty($wiki->groupingid)) {
682                     $sql = 'SELECT w.id, w.userid, w.pagename, u.firstname, u.lastname '
683                           .'    FROM {wiki_entries} w '
684                           .'    INNER JOIN {user} u ON w.userid = u.id '
685                           .'    INNER JOIN {groups_members} gm ON gm.userid = u.id '
686                           .'    INNER JOIN {groupings_groups} gg ON gm.groupid = gg.groupid '
687                           .'    WHERE w.wikiid = ? AND gg.groupingid = ?'
688                           .'    ORDER BY w.id';
689                     $params = array($wiki->id, $wiki->groupingid);
690                 } else {
691                     $sql = 'SELECT w.id, w.userid, w.pagename, u.firstname, u.lastname '
692                           .'    FROM {wiki_entries} w, {user} u '
693                           .'    WHERE w.wikiid = ? AND u.id = w.userid '
694                           .'    ORDER BY w.id';
695                     $params = array($wiki->id);
696                 }
697                 $wiki_entries = $DB->get_records_sql($sql, $params);
698                 $wiki_entries=is_array($wiki_entries)?$wiki_entries:array();
699                 foreach ($wiki_entries as $wiki_entry) {
700                     if (!empty($CFG->enablegroupings) && !empty($wiki->groupingid) && empty($groupingmembers[$wiki_entry->userid])) {
701                         continue;
702                     }
703                 
704                     if (($viewall === true) or groups_is_member($viewall, $wiki_entry->userid)) {
705                         $key = 'view.php?id='.$id.'&userid='.$wiki_entry->userid.'&page='.$wiki_entry->pagename;
706                         $wikis[$key] = fullname($wiki_entry).':'.$wiki_entry->pagename;
707                         if ($currentid == $wiki_entry->id) {
708                             $wikis['selected'] = $key;
709                         }
710                     }
711                 }
712             }
713         }
714         break;
716     case 'group':
717         /// If the user is an editing teacher, or a non-editing teacher not assigned to a group, show all group
718         /// wikis, regardless of creation.
720         /// If user is a member of multiple groups, need to show current group etc?
722         /// Get all the existing entries for this wiki.
723         $wiki_entries = wiki_get_entries($wiki, 'group');
724         
725         if ($groupmode and ($isteacheredit or ($isteacher and !$mygroupid))) {
726             if ($groups = groups_get_all_groups($course->id, null, $groupingid)) {
727                 $defpagename = empty($wiki->pagename) ? get_string('wikidefaultpagename', 'wiki') : $wiki->pagename;
728                 foreach ($groups as $group) {
730                     /// If this group already has an entry, use its pagename.
731                     if (isset($wiki_entries[$group->id])) {
732                         $pagename = $wiki_entries[$group->id]->pagename;
733                     }
734                     else {
735                         $pagename = $defpagename;
736                     }
738                     $key = 'view.php?id='.$id.($group->id?"&groupid=".$group->id:"").'&page='.$pagename;
739                     $wikis[$key] = $group->name.':'.$pagename;
740                 }
741             }
742         }
743         //if a studnet with multiple groups in SPG
744         else if ($groupmode == SEPARATEGROUPS){
745             if ($groups = groups_get_all_groups($course->id, $user->id, $groupingid)){
747                 $defpagename = empty($wiki->pagename) ? get_string('wikidefaultpagename', 'wiki') : $wiki->pagename;
748                 foreach ($groups as $group) {
749                     /// If this group already has an entry, use its pagename.
750                     if (isset($wiki_entries[$group->id])) {
751                         $pagename = $wiki_entries[$group->id]->pagename;
752                     }
753                     else {
754                         $pagename = $defpagename;
755                     }
756                     $key = 'view.php?id='.$id.($group->id?"&groupid=".$group->id:"").'&page='.$pagename;
757                     $wikis[$key] = $group->name.':'.$pagename;
758                 }
760             }
762         }
763         /// A user can see other group wikis if there are visible groups.
764         else if ($groupmode == VISIBLEGROUPS) {
765             if (!empty($CFG->enablegroupings) && !empty($wiki->groupingid)) {
766                 $sql = 'SELECT w.id, w.groupid, w.pagename, g.name as gname '
767                       .'    FROM {wiki_entries} w '
768                       .'    INNER JOIN {groups} g ON g.id = w.groupid '
769                       .'    INNER JOIN {groupings_groups} gg ON g.id = gg.groupid '
770                       .'    WHERE w.wikiid = ? AND gg.groupingid = ?'
771                       .'    ORDER BY w.groupid';
772                     $params = array($wiki->id, $wiki->groupingid);
773             } else {
774                 $sql = 'SELECT w.id, w.groupid, w.pagename, g.name as gname '
775                       .'    FROM {wiki_entries} w, {groups} g '
776                       .'    WHERE w.wikiid = ? AND g.id = w.groupid '
777                       .'    ORDER BY w.groupid';
778                     $params = array($wiki->id);
779             }
780             $wiki_entries = $DB->get_records_sql($sql, $params);
781             $wiki_entries=is_array($wiki_entries)?$wiki_entries:array();
782             foreach ($wiki_entries as $wiki_entry) {
783                 $key = 'view.php?id='.$id.($wiki_entry->groupid?"&groupid=".$wiki_entry->groupid:"").'&page='.$wiki_entry->pagename;
784                 $wikis[$key] = $wiki_entry->gname.':'.$wiki_entry->pagename;
785                 if ($currentid == $wiki_entry->id) {
786                     $wikis['selected'] = $key;
787                 }
788             }
789         }
790         break;
792     case 'teacher':
793         if ($isteacher) {
794             /// If the user is an editing teacher, or a non-editing teacher not assigned to a group, show all
795             /// teacher wikis, regardless of creation.
796             if ($groupmode and ($isteacheredit or ($isteacher and !$mygroupid))) {
797                 if ($groups = groups_get_all_groups($course->id, null, $groupingid)) {
798                     $defpagename = empty($wiki->pagename) ? get_string('wikidefaultpagename', 'wiki') : $wiki->pagename;
799                     foreach ($groups as $group) {
800                         /// If this group already has an entry, use its pagename.
801                         if ($wiki_entries[$group->id]) {
802                             $pagename = $wiki_entries[$group->id]->pagename;
803                         }
804                         else {
805                             $pagename = $defpagename;
806                         }
808                         $key = 'view.php?id='.$id.($group->id?"&groupid=".$group->id:"").'&page='.$pagename;
809                         $wikis[$key] = $group->name.':'.$pagename;
810                     }
811                 }
812             }
813             /// A teacher can see all other group teacher wikis.
814             else if ($groupmode) {
815             if (!empty($CFG->enablegroupings) && !empty($wiki->groupingid)) {
816                 $sql = 'SELECT w.id, w.groupid, w.pagename, g.name as gname '
817                       .'    FROM {wiki_entries} w '
818                       .'    INNER JOIN {groups} g ON g.id = w.groupid '
819                       .'    INNER JOIN {groupings_groups} gg ON g.id = gg.groupid '
820                       .'    WHERE w.wikiid = ? AND gg.groupingid = ?'
821                       .'    ORDER BY w.groupid';
822                     $params = array($wiki->id, $wiki->groupingid);
823             } else {
824                 $sql = 'SELECT w.id, w.groupid, w.pagename, g.name as gname '
825                       .'    FROM {wiki_entries} w, {groups} g '
826                       .'    WHERE w.wikiid = ? AND g.id = w.groupid '
827                       .'    ORDER BY w.groupid';
828                     $params = array($wiki->id);
829             }
830                 $wiki_entries = $DB->get_records_sql($sql, $params);
831                 $wiki_entries=is_array($wiki_entries)?$wiki_entries:array();
832                 foreach ($wiki_entries as $wiki_entry) {
833                     $key = 'view.php?id='.$id.($wiki_entry->groupid?"&groupid=".$wiki_entry->groupid:"").'&page='.$wiki_entry->pagename;
834                     $wikis[$key] = $wiki_entry->gname.':'.$wiki_entry->pagename;
835                     if ($currentid == $wiki_entry->id) {
836                         $wikis['selected'] = $key;
837                     }
838                 }
839             }
840         }
841         else {
842             /// A user can see other teacher wikis if they are a teacher, a member of the same
843             /// group (for separate groups) or there are visible groups.
844             if ($groupmode == VISIBLEGROUPS) {
845                 $viewall = true;
846             }
847             else if ($groupmode == SEPARATEGROUPS) {
848                 $viewall = $mygroupid;
849             }
850             else {
851                 $viewall = false;
852             }
853             if ($viewall !== false) {
854                 if (!empty($CFG->enablegroupings) && !empty($wiki->groupingid)) {
855                     $sql = 'SELECT w.id, w.groupid, w.pagename, g.name as gname '
856                           .'    FROM {wiki_entries} w '
857                           .'    INNER JOIN {groups} g ON g.id = w.groupid '
858                           .'    INNER JOIN {groupings_groups} gg ON g.id = gg.groupid '
859                           .'    WHERE w.wikiid = ? AND gg.groupingid = ?'
860                           .'    ORDER BY w.groupid';
861                     $params = array($wiki->id, $wiki->groupingid);
862                 } else {
863                     $sql = 'SELECT w.id, w.groupid, w.pagename, g.name as gname '
864                           .'    FROM {wiki_entries} w, {groups} g '
865                           .'    WHERE w.wikiid = ? AND g.id = w.groupid '
866                           .'    ORDER BY w.groupid';
867                     $params = array($wiki->id);
868                 }
869                 $wiki_entries = $DB->get_records_sql($sql, $params);
870                 $wiki_entries=is_array($wiki_entries)?$wiki_entries:array();
873                 foreach ($wiki_entries as $wiki_entry) {
874                     if (($viewall === true) or @in_array($wiki_entry->groupid, $viewall)/*$viewall == $wiki_entry->groupid*/) {
875                         $key = 'view.php?id='.$id.($wiki_entry->groupid?"&groupid=".$wiki_entry->groupid:"").'&page='.$wiki_entry->pagename;
876                         $wikis[$key] = $wiki_entry->gname.':'.$wiki_entry->pagename;
877                         if ($currentid == $wiki_entry->id) {
878                             $wikis['selected'] = $key;
879                         }
880                     }
881                 }
882             }
883         }
884         break;
885     }
886     
887     return $wikis;
890 function wiki_add_entry(&$wiki, &$course, $userid=0, $groupid=0) {
891 /// Adds a new wiki entry of the specified type, unless already entered.
892 /// No checking is done here. It is assumed that the caller has the correct
893 /// privileges to add this entry.
895     global $USER, $DB;
897     /// If this wiki already has a wiki_type entry, return false.
898     if (wiki_get_entry($wiki, $course, $userid, $groupid) !== false) {
899         return false;
900     }
902     $wiki_entry = new Object();
904     switch ($wiki->wtype) {
906     case 'student':
907         $wiki_entry->wikiid = $wiki->id;
908         $wiki_entry->userid = $userid ? $userid : $USER->id;
909         $wiki_entry->pagename = wiki_page_name($wiki);
910         $wiki_entry->timemodified = time();
911         break;
913     case 'group':
914         /// Get the groupmode. It's been added to the wiki object.
915         $groupmode = groups_get_activity_groupmode($wiki);
917         ///give the first groupid by default and try
918         $mygroups = mygroupid($course->id);
920         /// If there is a groupmode, get the group id.
921         if ($groupmode) {
922             $groupid = $groupid ? $groupid : $mygroups[0]/*mygroupid($course->id)*/;
923         }
924         /// If mode is 'nogroups', then groupid is zero.
925         else {
926             $groupid = 0;
927         }
928         $wiki_entry->wikiid = $wiki->id;
929         $wiki_entry->groupid = $groupid;
930         $wiki_entry->pagename = wiki_page_name($wiki);
931         $wiki_entry->timemodified = time();
933         break;
935     case 'teacher':
936         /// Get the groupmode. It's been added to the wiki object.
937         $groupmode = groups_get_activity_groupmode($wiki);
939         /// If there is a groupmode, get the user's group id.
940         if ($groupmode and $groupid == 0) {
941             $mygroupid = mygroupid($course->id);
942             $groupid = $mygroupid[0]/*mygroupid($course->id)*/;
943         }
945         $wiki_entry->wikiid = $wiki->id;
946         $wiki_entry->course = $wiki->course;
947         $wiki_entry->groupid = $groupid;
948         $wiki_entry->pagename = wiki_page_name($wiki);
949         $wiki_entry->timemodified = time();
950         break;
951     }
952     $wiki_entry->pagename = $wiki_entry->pagename;
954     return $DB->insert_record("wiki_entries", $wiki_entry, true);
957 function wiki_can_add_entry(&$wiki, &$user, &$course, $userid=0, $groupid=0) {
958 /// Returns true or false if the user can add a wiki entry for this wiki.
960     /// Get the groupmode. It's been added to the wiki object.
961     $groupmode = groups_get_activity_groupmode($wiki);
962     $mygroupid = mygroupid($course->id);
964     switch ($wiki->wtype) {
966     case 'student':
967 ///     A student can create their own wiki, if they are a member of that course.
968 ///     A user can create their own wiki at the site level.
969         if ($userid == 0) {
970             return (wiki_is_student($wiki, $user->id) or wiki_is_student($wiki, $user->id));
971         }
972 ///     An editing teacher can create any student wiki, or
973 ///     a non-editing teacher, if not assigned to a group can create any student wiki, or if assigned to a group can
974 ///     create any student wiki in their group.
975         else {
976             return ((($userid == $user->id) and wiki_is_student($wiki, $user->id)) or wiki_is_teacheredit($wiki) or
977                     (wiki_is_teacher($wiki) and (!$groupmode or $mygroupid == 0 or (groups_is_member($mygroupid, $userid)))));
978         }
979         break;
981     case 'group':
982         /// If mode is 'nogroups', then all participants can add wikis.
983         if (wiki_is_teacheredit($wiki, $user->id)) {
984             return true;
985         }
987         if (!$groupmode) {
988             return (wiki_is_student($wiki, $user->id) or wiki_is_teacher($wiki, $user->id));
989         }
990         /// If not requesting a group, must be a member of a group.
991         else if ($groupid == 0) {
992             return ($mygroupid != 0);
993         }
994         /// If requesting a group, must be an editing teacher, a non-editing teacher with no assigned group,
995         /// or a non-editing teacher requesting their group. or a student in group, but wiki is empty.
996         else {
997             return (wiki_is_teacheredit($wiki) or
998                    (wiki_is_teacher($wiki) and ($mygroupid == 0 or @in_array($groupid, $mygroupid))) or
999                    (wiki_is_student($wiki, $user->id) and @in_array($groupid, $mygroupid))
1000                    );
1001         }
1002         break;
1004     case 'teacher':
1005         /// If mode is 'nogroups', then all teachers can add wikis.
1006         if (!$groupmode) {
1007             return wiki_is_teacher($wiki, $user->id);
1008         }
1009         /// If not requesting a group, must be a member of a group.
1010         else if ($groupid == 0) {
1011             return ($mygroupid != 0 and wiki_is_teacher($wiki));
1012         }
1013         /// If there is a group mode, non-editing teachers with an assigned group, can only create wikis
1014         /// in their group. Non-editing teachers with no assigned group and editing teachers can create any wiki.
1015         else {
1016             return (wiki_is_teacheredit($wiki) or
1017                     (wiki_is_teacher($wiki) and ($mygroupid == 0 or @in_array($groupid, $mygroupid))));
1018         }
1019         break;
1020     }
1022     return false;
1025 function wiki_can_edit_entry(&$wiki_entry, &$wiki, &$user, &$course) {
1026 /// Returns true or false if the user can edit this wiki entry.
1028     $can_edit = false;
1029     $groupmode = groups_get_activity_groupmode($wiki);
1030     $mygroupid = mygroupid($course->id);
1032     /// Editing teacher's and admins can edit all wikis, non-editing teachers can edit wikis in their groups,
1033     /// or all wikis if group mode is 'no groups' or they don't belong to a group.
1034     if (wiki_is_teacheredit($wiki, $user->id) or
1035         ((!$groupmode or $mygroupid == 0) and wiki_is_teacher($wiki, $user->id))) {
1036         $can_edit = true;
1037     }
1038     else {
1039         switch ($wiki->wtype) {
1041         /// Only a teacher or the owner of a student wiki can edit it.
1042         case 'student':
1043             $can_edit = (($user->id == $wiki_entry->userid) or
1044                          ($groupmode and wiki_is_teacher($wiki, $user->id) and
1045                           groups_is_member($mygroupid, $wiki_entry->userid)));
1046             break;
1048         case 'group':
1049             /// If there is a groupmode, determine the user's group status.
1050             if ($groupmode) {
1051                 /// If the user is a member of the wiki group, they can edit the wiki.
1052                 $can_edit = groups_is_member($wiki_entry->groupid, $user->id);
1053             }
1054             /// If mode is 'nogroups', then all participants can edit the wiki.
1055             else {
1056                 $can_edit = (wiki_is_student($wiki, $user->id) or wiki_is_teacher($wiki, $user->id));
1057             }
1058             break;
1060         case 'teacher':
1061             /// If there is a groupmode, determine the user's group status.
1062             if ($groupmode) {
1063                 /// If the user is a member of the wiki group, they can edit the wiki.
1064                 $can_edit = (wiki_is_teacher($wiki, $user->id) and groups_is_member($wiki_entry->groupid, $user->id));
1065             }
1066             else {
1067                 $can_edit = wiki_is_teacher($wiki, $user->id);
1068             }
1069             break;
1070         }
1071     }
1072     return $can_edit;
1075 function wiki_user_can_access_student_wiki(&$wiki, $userid, &$course) {
1076     global $USER;
1078     /// Get the groupmode. It's been added to the wiki object.
1079     $groupmode = groups_get_activity_groupmode($wiki);
1080     $usersgroup = mygroupid($course->id);
1081     $isteacher = wiki_is_teacher($wiki, $USER->id);
1083     /// If this user is allowed to access this wiki then return TRUE.
1084     /// *** THIS COULD BE A PROBLEM, IF STUDENTS COULD EVER BE PART OF MORE THAN ONE GROUP ***
1085     /// A user can access a student wiki, if:
1086     ///     - it is their wiki,
1087     ///     - group mode is VISIBLEGROUPS,
1088     ///     - group mode is SEPARATEGROUPS, and the user is a member of the requested user's group,
1089     ///     - they are an editing teacher or administrator,
1090     ///     - they are a non-editing teacher not assigned to a specific group,
1091     ///     - they are a non-editing teacher and group mode is NOGROUPS.
1092     ///     - they are an administrator (mostly for site-level wikis).
1093     if (($userid and ($USER->id == $userid)) or ($groupmode == VISIBLEGROUPS) or
1094         (($groupmode == SEPARATEGROUPS) and groups_is_member($usersgroup, $userid)) or
1095         (wiki_is_teacheredit($wiki, $USER->id)) or
1096         (wiki_is_teacher($wiki, $USER->id) and (!$usersgroup or $groupmode == NOGROUPS))) {
1097         $can_access = true;
1098     }
1099     else {
1100         $can_access = false;
1101     }
1102     return $can_access;
1105 function wiki_user_can_access_group_wiki(&$wiki, $groupid, &$course) {
1106     global $USER;
1108     /// Get the groupmode. It's been added to the wiki object.
1109     $groupmode = groups_get_activity_groupmode($wiki);
1110     $usersgroup = mygroupid($course->id);
1111     $isteacher = wiki_is_teacher($wiki, $USER->id);
1113     /// A user can access a group wiki, if:
1114     ///     - group mode is NOGROUPS,
1115     ///     - group mode is VISIBLEGROUPS,
1116     ///     - group mode is SEPARATEGROUPS, and they are a member of the requested group,
1117     ///     - they are an editing teacher or administrator,
1118     ///     - they are a non-editing teacher not assigned to a specific group.
1119     if (($groupmode == NOGROUPS) or ($groupmode == VISIBLEGROUPS) or
1120         (($groupmode == SEPARATEGROUPS) and @in_array($groupid, $usersgroup)/*($usersgroup == $groupid)*/) or
1121         (wiki_is_teacheredit($wiki, $USER->id)) or
1122         (wiki_is_teacher($wiki, $USER->id) and !$usersgroup)) {
1123         $can_access = true;
1124     }
1125     else {
1126         $can_access = false;
1127     }
1128     return $can_access;
1131 function wiki_user_can_access_teacher_wiki(&$wiki, $groupid, &$course) {
1132     global $USER;
1134     /// Get the groupmode. It's been added to the wiki object.
1135     $groupmode = groups_get_activity_groupmode($wiki);
1137     /// A user can access a teacher wiki, if:
1138     ///     - group mode is NOGROUPS,
1139     ///     - group mode is VISIBLEGROUPS,
1140     ///     - group mode is SEPARATEGROUPS, and they are a member of the requested group,
1141     ///     - they are a teacher or administrator,
1142     if (($groupmode == NOGROUPS) or ($groupmode == VISIBLEGROUPS) or
1143         (($groupmode == SEPARATEGROUPS) and (@in_array($groupid, mygroupid($course->id))/*mygroupid($course->id) == $groupid*/)) or
1144         (wiki_is_teacher($wiki, $USER->id))){
1145         $can_access = true;
1146     }
1147     else {
1148         $can_access = false;
1149     }
1150     return $can_access;
1153 function wiki_get_owner(&$wiki_entry) {
1154     global $DB;
1156     if ($wiki_entry->userid > 0) {
1157         $user = $DB->get_record('user', array('id'=>$wiki_entry->userid));
1158         $owner = fullname($user);
1159     }
1160     else if ($wiki_entry->groupid > 0) {
1161         $owner = groups_get_group_name($wiki_entry->groupid); //TODO:check.
1162     }
1163     else if ($wiki_entry->course > 0) {
1164         $course = $DB->get_record('course', array('id'=>$wiki_entry->course));
1165         $owner = $course->shortname;
1166     }
1167     else {
1168         $owner = '- '.get_string("ownerunknown","wiki").' -';
1169     }
1170     return $owner;
1173 function wiki_print_search_form($cmid, $search="", $userid, $groupid, $return=false) {
1174     global $CFG;
1175     # TODO: Add Group and User !!!
1176     $output = "<form id=\"search\" action=\"$CFG->wwwroot/mod/wiki/view.php\">";
1177     $output .="<fieldset class='invisiblefieldset'>";
1178     $output .= "<span style='font-size:0.6em;'>";
1179     $output .= "<input value=\"".get_string("searchwiki", "wiki").":\" type=\"submit\" />";
1180     $output .= "<input name=\"id\" type=\"hidden\" value=\"$cmid\" />";
1181     $output = $output.($groupid?"<input name=\"groupid\" type=\"hidden\" value=\"$groupid\" />":"");
1182     $output = $output.($userid?"<input name=\"userid\" type=\"hidden\" value=\"$userid\" />":"");
1183     $output .= "<input name=\"q\" type=\"text\" size=\"20\" value=\"".s($search)."\" />".' ';
1184     $output .= "</span>";
1185     $output .= "<input name=\"page\" type=\"hidden\" value=\"SearchPages\" />";
1186     $output .= "</fieldset>";
1187     $output .= "</form>";
1189     if ($return) {
1190         return $output;
1191     }
1192     echo $output;
1195 function wiki_print_wikilinks_block($cmid, $binary=false, $return=false) {
1196 /// Prints a link-list of special wiki-pages
1197    global $CFG, $ewiki_title;
1199    $links=array();
1201    $links["SiteMap"]=get_string("sitemap", "wiki");
1202    $links["PageIndex"]=get_string("pageindex", "wiki");
1203    $links["NewestPages"]=get_string("newestpages", "wiki");
1204    $links["MostVisitedPages"]=get_string("mostvisitedpages", "wiki");
1205    $links["MostOftenChangedPages"]=get_string("mostoftenchangedpages", "wiki");
1206    $links["UpdatedPages"]=get_string("updatedpages", "wiki");
1207    $links["OrphanedPages"]=get_string("orphanedpages", "wiki");
1208    $links["WantedPages"]=get_string("wantedpages", "wiki");
1209    $links["WikiExport"]=get_string("wikiexport", "wiki");
1210    if($binary) {
1211      $links["FileDownload"]=get_string("filedownload", "wiki");
1212    }
1213    popup_form(EWIKI_SCRIPT, $links, "wikilinks", "", get_string("choosewikilinks", "wiki"), "", "", $return);
1216 function wiki_print_page_actions($cmid, $specialpages, $page, $action, $binary=false, $canedit=true) {
1217 /// Displays actions which can be performed on the page
1219   $page=array();
1221   // Edit this Page
1222   if (in_array($action, array("edit", "links", "info", "attachments"))) {
1223     $page["view/$page"]=get_string("viewpage","wiki");
1224   }
1225   if ($canedit && !in_array($page, $specialpages) && $action != "edit") {
1226     $page["edit/$page"]=get_string("editthispage","wiki");
1227   }
1228   if ($action != "links") {
1229     $page["links/$page"]=get_string("backlinks","wiki");
1230   }
1231   if ($canedit && !in_array($page, $specialpages) && $action!="info") {
1232     $page["info/$page"]=get_string("pageinfo","wiki");
1233   }
1234   if($canedit && $binary && !in_array($page, $specialpages) && $action != "attachments") {
1235     $page["attachments/$page"]=get_string("attachments","wiki");
1236   }
1238   popup_form(EWIKI_SCRIPT, $page, "wikiactions", "", get_string("action", "wiki"), "", "", false);
1241 function wiki_print_administration_actions($wiki, $cmid, $userid, $groupid, $page, $noeditor, $course) {
1242 /// Displays actions which can be performed on the page
1244   /// Create the URL
1245   $ewscript = 'admin.php?id='.$cmid;
1246   if (isset($userid) && $userid!=0) $ewscript .= '&amp;userid='.$userid;
1247   if (isset($groupid) && $groupid!=0) $ewscript .= '&amp;groupid='.$groupid;
1248   if (isset($page)) $ewscript .= '&amp;page='.$page;
1249   $ewscript.="&amp;action=";
1252     /// Build that action array according to wiki flags.
1253     $action = array();
1254     $isteacher = wiki_is_teacher($wiki);
1256     if ($wiki->setpageflags or $isteacher) {
1257         $action['setpageflags'] = get_string('setpageflags', 'wiki');
1258     }
1259     if ($wiki->removepages or $isteacher) {
1260         $action['removepages']  = get_string('removepages', 'wiki');
1261     }
1262     if ($wiki->strippages or $isteacher) {
1263         $action['strippages']  = get_string('strippages', 'wiki');
1264     }
1265     if ($wiki->revertchanges or $isteacher) {
1266         $action['revertpages'] = get_string('revertpages', 'wiki');
1267     }
1269   if($noeditor) {
1270     $action["checklinks"]=get_string("checklinks", "wiki");
1271   }
1272   popup_form($ewscript, $action, "wikiadministration", "", get_string("chooseadministration", "wiki"), "", "", false);
1275 function wiki_admin_get_flagarray() {
1276   $ret = array(
1277      EWIKI_DB_F_TEXT => get_string("flagtxt","wiki"),
1278      EWIKI_DB_F_BINARY => get_string("flagbin","wiki"),
1279      EWIKI_DB_F_DISABLED => get_string("flagoff","wiki"),
1280      EWIKI_DB_F_HTML => get_string("flaghtm","wiki"),
1281      EWIKI_DB_F_READONLY => get_string("flagro","wiki"),
1282      EWIKI_DB_F_WRITEABLE => get_string("flagwr","wiki"),
1283   );
1285   return $ret;
1288 ///////// Ewiki Administration. Mostly taken from the ewiki/tools folder and changed
1289 function wiki_admin_setpageflags_list($pageflagstatus) {
1290   $FD = wiki_admin_get_flagarray();
1291   $table = new Object();
1292   $table->head = array(get_string("pagename","wiki"), get_string("flags","wiki"));
1293   if($pageflagstatus) {
1294     $table->head[]=get_string("status","wiki");
1295   }
1297   $result = ewiki_database("GETALL", array("version", "flags"));
1298   while ($row = $result->get()) {
1299     $id = $row["id"];
1300     $data = ewiki_database("GET", $row);
1302     $cell_pagename="";
1303     $cell_flags="";
1304     if ($data["flags"] & EWIKI_DB_F_TEXT) {
1305         $cell_pagename .= '<a href="' . EWIKI_SCRIPT . $id . '">';
1306     } else {
1307         $cell_pagename .= '<a href="' . EWIKI_SCRIPT_BINARY . $id . '">';
1308     }
1309     $cell_pagename .= s($id) . '</a> / '.get_string("version","wiki").": ".$row["version"];
1311     foreach ($FD as $n=>$str) {
1312         $cell_flags .='<input type="checkbox" name="flags['. rawurlencode($id)
1313             . '][' . $n . ']" value="1" '
1314             . (($data["flags"] & $n) ? "checked=\"checked\"" : "")
1315             . ' />'.$str. ' ';
1316     }
1317     if($pageflagstatus) {
1318       $table->data[]=array($cell_pagename, $cell_flags, $pageflagstatus[$id]);
1319     } else {
1320       $table->data[]=array($cell_pagename, $cell_flags);
1321     }
1322   }
1323   return $table;
1326 function wiki_admin_setpageflags($pageflags) {
1327   $FD = wiki_admin_get_flagarray();
1329   $status=array();
1330   if($pageflags) {
1331      foreach($pageflags as $page=>$fa) {
1333         $page = rawurldecode($page);
1335         $flags = 0;
1336         $fstr = "";
1337         foreach($fa as $num=>$isset) {
1338            if ($isset) {
1339               $flags += $num;
1340               $fstr .= ($fstr?",":""). $FD[$num];
1341            }
1342         }
1344         #$status[$page] .= "{$flags}=[{$fstr}]";
1346         $data = ewiki_database("GET", array("id" => $page));
1348         if ($data["flags"] != $flags) {
1349            $data["flags"] = $flags;
1350            $data["author"] = "ewiki-tools, " . ewiki_author();
1351            $data["version"]++;
1352            ewiki_database("WRITE", $data);
1353            $status[$page] =  "<b>".get_string("flagsset","wiki")."</b> ".$status[$page];
1354         }
1355      }
1356   }
1357   return $status;
1361 function wiki_admin_remove_list($listall="") {
1362   /// Table header
1363   $table = new Object();
1364   $table->head = array("&nbsp;", get_string("pagename","wiki"), get_string("errororreason","wiki"));
1366   /// Get all pages
1367   $result = ewiki_database("GETALL", array("version"));
1368   $selected = array();
1370   /// User wants to see all pages
1371   if ($listall) {
1372     while ($row = $result->get()) {
1373       $selected[$row["id"]] = get_string("listall","wiki")."<br />";
1374     }
1375   }
1376   while ($page = $result->get()) {
1377     $id = $page["id"];
1378     $page = ewiki_database("GET", array("id"=>$id));
1379     $flags = $page["flags"];
1380     #print "$id ".strlen(trim(($page["content"])))."<br />";
1382     if (!strlen(trim(($page["content"]))) && !($flags & EWIKI_DB_F_BINARY)) {
1383         @$selected[$id] .= get_string("emptypage","wiki")."<br />";
1384     }
1386     // Check for orphaned pages
1387     $result2 = ewiki_database("SEARCH", array("content" => $id));
1388     $orphanedpage=true;
1389     if ($result2 && $result2->count()) {
1390         while ($row = $result2->get()) {
1391           $checkcontent = ewiki_database("GET", array("id"=>$row["id"]));
1392           $checkcontent = strtolower($checkcontent["content"]);
1394           if(strpos($checkcontent, strtolower($id)) !== false) {
1395             $orphanedpage=false;
1396           }
1398           #echo "rc({$row['id']})==>($id): $check2 <br />";
1399         }
1400     }
1402     /// Some more reasons for Deletion...
1403     if ($orphanedpage && $id!=EWIKI_PAGE_INDEX &&!($flags & EWIKI_DB_F_BINARY)) {
1404         @$selected[$id] .= get_string("orphanedpage","wiki")."<br />";
1405     }
1407     if ($flags & EWIKI_DB_F_DISABLED) {
1408         @$selected[$id] .= get_string("disabledpage","wiki")."<br />";
1409     }
1411     if (($flags & 3) == 3) {
1412         @$selected[$id] .= get_string("errorbinandtxt","wiki")."<br />";
1413     }
1415     if (!($flags & 3)) {
1416         @$selected[$id] .= get_string("errornotype","wiki")."<br />";
1417     }
1419     if ($flags & EWIKI_DB_F_HTML) {
1420         @$selected[$id] .= get_string("errorhtml","wiki")."<br />";
1421     }
1423     if (($flags & EWIKI_DB_F_READONLY) && !($flags & EWIKI_DB_F_BINARY)) {
1424         @$selected[$id] .= get_string("readonly","wiki")."<br />";
1425     }
1427     if (($flags & EWIKI_DB_F_READONLY) && ($flags & EWIKI_DB_F_WRITEABLE)) {
1428         @$selected[$id] .= get_string("errorroandwr","wiki")."<br />";
1429     }
1431     if (strlen($page["content"]) >= 65536) {
1432         @$selected[$id] .= get_string("errorsize","wiki")."<br />";
1433     }
1435     if (strpos($page["refs"], "\n".get_string("deletemewikiword","wiki")."\n")!==false) {
1436         @$selected[$id] .= get_string("deletemewikiwordfound","wiki",get_string("deletemewikiword","wiki"))."<br />";
1437     }
1438   }
1440   foreach ($selected as $id => $reason) {
1441     $table_checkbox='<input type="checkbox" value="'.rawurlencode($id).'" name="pagestodelete[]" />';
1443     #-- link & id
1444     if (strpos($id, EWIKI_IDF_INTERNAL) === false) {
1445         $table_page='<a href="' . ewiki_script("", $id) . '">';
1446     } else {
1447         $table_page='<a href="' . ewiki_script_binary("", $id) . '">';
1448     }
1449     $table_page .= s($id) . '</a>';
1451     #-- print reason
1452     $table_reason=$reason;
1454     $table->data[]=array($table_checkbox, $table_page, $table_reason);
1455   }
1457   return $table;
1460 /// This function actually removes the pages
1461 function wiki_admin_remove($pagestodelete, $course, $wiki, $userid, $groupid) {
1462   $ret="";
1463   foreach ($pagestodelete as $id) {
1465     $id = rawurldecode($id);
1467     $data = ewiki_database("GET", array("id"=>$id));
1468     for ($version=1; $version<=$data["version"]; $version++) {
1469         ewiki_database("DELETE", array("id"=>$id, "version"=>$version));
1470         if($data["flags"] & EWIKI_DB_F_BINARY) {
1471           $filepath=moodle_binary_get_path($id, $data["meta"], $course, $wiki, $userid, $groupid);
1472           @unlink("$filepath");
1473         }
1474     }
1476   }
1477   return $ret;
1480 function wiki_admin_strip_list($pagestostrip="",$version="",$err="") {
1481   /// Table header
1482   $table = new Object();
1483   $table->head = array("&nbsp;", get_string("pagename","wiki"), get_string("deleteversions","wiki"));
1485   $vc=ewiki_database("COUNTVERSIONS", array());
1486   $result = ewiki_database("GETALL",array());
1487   $i=0;
1488   while ($row = $result->get()) {
1489      $id = $row["id"];
1490      if($vc[$id]>1) {
1491         $error="";
1492         if($err[$id]) {
1493           $error=" ".join(", ",$err[$id]);
1494         }
1495         $checked="";
1496         if($pagestostrip=="" || $pagestostrip[$i]) {
1497           $checked=" checked=\"checked\"";
1498         }
1499         if($version=="") {
1500           $versiondefault="1-".($row["version"]-1);
1501         } else {
1502           $versiondefault=$version[$i];
1503         }
1504         $table->data[]=array('<input type="checkbox" value="'.rawurlencode($id).'" name="pagestostrip['.$i.']" '.$checked.' />',
1505                         '<A HREF="'.EWIKI_SCRIPT.$id.'">'.s($id).'</A> / '.get_string("version","wiki").": ".$row["version"],
1506                         '<input name="version['.$i.']" value="'.$versiondefault.'" size="7" />'.$error);
1508       }
1509       $i++;
1510   }
1511   return $table;
1514 function wiki_admin_strip_versions($pagestostrip, $version, &$err) {
1515   $ret=array();
1516   foreach ($pagestostrip as $key => $id_ue) {
1518     $id = rawurldecode($id_ue);
1519     if (preg_match('/^(\d+)[-\s._:]+(\d+)$/', trim($version[$key]), $uu)) {
1520       $versA = $uu[1];
1521       $versZ = $uu[2];
1523       // Let the last Version in the database
1524       $checkdata = ewiki_database("GET", array("id" => $id));
1525       if($versZ>=$checkdata["version"]) {
1526             $err[$id][] = get_string("versionrangetoobig","wiki");
1527       } else {
1528         if($versA<=$versZ) {
1529           for ($v=$versA; $v<=$versZ; $v++) {
1530               $ret[$id][]=$v;
1531           }
1532         } else {
1533           $err[$id][]=get_string("wrongversionrange","wiki",$version[$key]);
1534         }
1535       }
1536     }
1537     else {
1538       $err[$id][]=get_string("wrongversionrange","wiki",$version[$key]);
1539     }
1540   }
1541   return $ret;
1544 function wiki_admin_strip($pagestostrip) {
1545   /// Purges old page-versions
1546   foreach($pagestostrip as $id => $versions) {
1547     foreach($versions as $version) {
1548       ewiki_database("DELETE", array("id"=>$id, "version"=>$version));
1549     }
1550   }
1553 function wiki_admin_checklinks_list() {
1554   $ret=array();
1555   $result = ewiki_database("GETALL",array());
1556   while ($row = $result->get()) {
1557     if(!($row["flags"] & EWIKI_DB_F_BINARY)) {
1558       $index=s($row["id"]);
1559       $ret[$index] = $row["id"];
1560     }
1561   }
1562   return $ret;
1565 function wiki_admin_checklinks($pagetocheck) {
1566   /// Checks http:// Links
1567   $ret="";
1568   if($pagetocheck) {
1569      $get = ewiki_database("GET", array("id" => $pagetocheck));
1570      $content = $get["content"];
1572      preg_match_all('_(http.?://[^\s"\'<>#,;]+[^\s"\'<>#,;.])_', $content, $links);
1573      $badlinks = array();
1574      if(!$links[1]) {
1575        $ret = get_string("nolinksfound","wiki")."<br /><br />";
1576      } else {
1577        foreach ($links[1] as $href) {
1578           #print "[ $href ]";
1579           #$d = @implode("", @file($href));
1580           $d="";
1581           if($checkfd = @fopen($href, 'r')) {
1582             fclose($checkfd);
1583             $d="OK";
1584           }
1585           if (empty($d) || !strlen(trim($d)) || stristr("not found", $d) || stristr("error 404", $d)) {
1586              $ret.="[".get_string("linkdead","wiki")."] $href <br />\n";
1587              $badlinks[] = $href;
1588           } else {
1589              $ret.="[".get_string("linkok","wiki")."] $href <br />\n";
1590           }
1591        }
1592      }
1594      /// Remove old Notices
1595      $content = eregi_replace(' µµ__~\['.get_string("offline","wiki").'\]__µµ ','', $content);
1597      #-- replace dead links
1598      foreach ($badlinks as $href) {
1599         $content = preg_replace("\377^(.*)($href)\377m", '$1 µµ__~['.get_string("offline","wiki").']__µµ $2', $content);
1600      }
1602      #-- compare against db content
1603      if ($content != $get["content"]) {
1604         $get["content"] = $content;
1605         $get["version"]++;
1606         $get["author"] = ewiki_author("ewiki_checklinks");
1607         $get["lastmodified"] = time();
1609         ewiki_database("WRITE", $get);
1610      }
1611   }
1612   return $ret;
1615 function wiki_admin_revert($proceed, $authorfieldpattern, $changesfield, $howtooperate, $deleteversions) {
1616   $ret="";
1617   #-- params
1618   $m_time = $changesfield * 3600;
1619   $depth = $deleteversions - 1;
1620   $depth = ($depth>0?$depth:0);
1622   #-- walk through
1623   $result = ewiki_database("GETALL", array("id", "author", "lastmodified"));
1624   while ($row = $result->get()) {
1625     $id = $row["id"];
1626     #-- which versions to check
1627     $verZ = $row["version"];
1628     if ($howtooperate=="lastonly") {
1629       $verA = $verZ;
1630     }
1631     else {
1632       $verA = $verZ-$depth;
1633       if ($verA <= 0) {
1634           $verA = 1;
1635       }
1636     }
1638     for ($ver=$verA; $ver<=$verZ; $ver++) {
1639       #-- load current $ver database entry
1640       if ($verA != $verZ) {
1641           $row = ewiki_database("GET", array("id"=>$id, "version"=>$ver));
1642       }
1644       #-- match
1645       if (stristr($row["author"], $authorfieldpattern) && ($row["lastmodified"] + $m_time > time())) {
1646         $ret .= "$id (".get_string("versionstodelete","wiki").": ";
1647         #-- delete multiple versions
1648         if ($howtooperate=="allsince") {
1649           while ($ver<=$verZ) {
1650               $ret .= " $ver";
1651               if ($proceed) {
1652                 ewiki_database("DELETE", array("id"=>$id, "version"=>$ver));
1653               }
1654               $ver++;
1655           }
1656         }
1657         #-- or just the affected one
1658         else {
1659           $ret .= " $ver";
1660           if ($proceed) {
1661             ewiki_database("DELETE", $row);
1662           }
1663         }
1664         $ret .= ")<br />";
1665         break;
1666       }
1667     } #-- for($ver)
1668   } #-- while($row)
1669   return $ret;
1673 function wiki_get_view_actions() {
1674     return array('view','view all');
1677 function wiki_get_post_actions() {
1678     return array('hack');
1682 /**
1683  * Obtains an editing lock on a wiki page.
1684  * @param int $wikiid ID of wiki object.
1685  * @param string $pagename Name of page.
1686  * @return array Two-element array with a boolean true (if lock has been obtained)
1687  *   or false (if lock was held by somebody else). If lock was held by someone else,
1688  *   the values of the wiki_locks entry are held in the second element; if lock was
1689  *   held by current user then the the second element has a member ->id only.
1690  */
1691 function wiki_obtain_lock($wikiid,$pagename) {
1692     global $USER, $DB;
1694     // Check for lock
1695     $alreadyownlock=false;
1696     if($lock=$DB->get_record('wiki_locks', array('pagename'=>$pagename,'wikiid'=>$wikiid))) {
1697         // Consider the page locked if the lock has been confirmed within WIKI_LOCK_PERSISTENCE seconds
1698         if($lock->lockedby==$USER->id) {
1699             // Cool, it's our lock, do nothing except remember it in session
1700             $lockid=$lock->id;
1701             $alreadyownlock=true;
1702         } else if(time()-$lock->lockedseen < WIKI_LOCK_PERSISTENCE) {
1703             return array(false,$lock);
1704         } else {
1705             // Not locked any more. Get rid of the old lock record.
1706             if(!$DB->delete_records('wiki_locks', array('pagename'=>$pagename,'wikiid'=>$wikiid))) {
1707                 print_error('cannotdeletelockrecored', 'wiki');
1708             }
1709         }
1710     }
1712     // Add lock
1713     if(!$alreadyownlock) {
1714         // Lock page
1715         $newlock=new stdClass;
1716         $newlock->lockedby=$USER->id;
1717         $newlock->lockedsince=time();
1718         $newlock->lockedseen=$newlock->lockedsince;
1719         $newlock->wikiid=$wikiid;
1720         $newlock->pagename=$pagename;
1721         if(!$lockid=$DB->insert_record('wiki_locks',$newlock)) {
1722             print_error('cannotinsertlockrecored', 'wiki');
1723         }
1724     }
1726     // Store lock information in session so we can clear it later
1727     if(!array_key_exists(SESSION_WIKI_LOCKS,$_SESSION)) {
1728         $_SESSION[SESSION_WIKI_LOCKS]=array();
1729     }
1730     $_SESSION[SESSION_WIKI_LOCKS][$wikiid.'_'.$pagename]=$lockid;
1731     $lockdata=new StdClass;
1732     $lockdata->id=$lockid;
1733     return array(true,$lockdata);
1736 /**
1737  * If the user has an editing lock, releases it. Has no effect otherwise.
1738  * Note that it doesn't matter if this isn't called (as happens if their
1739  * browser crashes or something) since locks time out anyway. This is just
1740  * to avoid confusion of the 'what? it says I'm editing that page but I'm
1741  * not, I just saved it!' variety.
1742  * @param int $wikiid ID of wiki object.
1743  * @param string $pagename Name of page.
1744  */
1745 function wiki_release_lock($wikiid,$pagename) {
1746     global $DB;
1748     if(!array_key_exists(SESSION_WIKI_LOCKS,$_SESSION)) {
1749         // No locks at all in session
1750         return;
1751     }
1753     $key=$wikiid.'_'.$pagename;
1755     if(array_key_exists($key,$_SESSION[SESSION_WIKI_LOCKS])) {
1756         $lockid=$_SESSION[SESSION_WIKI_LOCKS][$key];
1757         unset($_SESSION[SESSION_WIKI_LOCKS][$key]);
1758         if (!$DB->delete_records('wiki_locks', array('id'=>$lockid))) {
1759             print_error('cannotdeletelockrecored', 'wiki');
1760         }
1761     }
1764 /**
1765  * Returns all other caps used in module
1766  */
1767 function wiki_get_extra_capabilities() {
1768     return array('moodle/site:accessallgroups', 'moodle/site:viewfullnames');
1771 /**
1772  * @param string $feature FEATURE_xx constant for requested feature
1773  * @return mixed True if module supports feature, null if doesn't know
1774  */
1775 function wiki_supports($feature) {
1776     switch($feature) {
1777         case FEATURE_GROUPS:                  return true;
1778         case FEATURE_GROUPINGS:               return true;
1779         case FEATURE_GROUPMEMBERSONLY:        return true;
1780         case FEATURE_MODEDIT_INTRO_EDITOR:    return true;
1781         case FEATURE_COMPLETION_TRACKS_VIEWS: return true;
1782         case FEATURE_GRADE_HAS_GRADE:         return false;
1783         case FEATURE_GRADE_OUTCOMES:          return true;
1785         default: return null;
1786     }