]> git.mjollnir.org Git - moodle.git/commitdiff
MDL-16075 File storage conversion of Glossary
authorskodak <skodak>
Sun, 17 Aug 2008 21:27:43 +0000 (21:27 +0000)
committerskodak <skodak>
Sun, 17 Aug 2008 21:27:43 +0000 (21:27 +0000)
15 files changed:
mod/glossary/db/upgrade.php
mod/glossary/deleteentry.php
mod/glossary/edit.php
mod/glossary/edit_form.php
mod/glossary/exportentry.php
mod/glossary/formats/TEMPLATE/TEMPLATE_format.php
mod/glossary/formats/continuous/continuous_format.php
mod/glossary/formats/dictionary/dictionary_format.php
mod/glossary/formats/encyclopedia/encyclopedia_format.php
mod/glossary/formats/faq/faq_format.php
mod/glossary/formats/fullwithauthor/fullwithauthor_format.php
mod/glossary/formats/fullwithoutauthor/fullwithoutauthor_format.php
mod/glossary/lib.php
mod/glossary/version.php
mod/glossary/view.php

index 876148fca38b1799c2ee5da15fd6005eb8d6ed9f..270c2cd337f22b199e5f5cda26133d7031e2a26d 100644 (file)
@@ -28,6 +28,83 @@ function xmldb_glossary_upgrade($oldversion) {
 
 //===== 1.9.0 upgrade line ======//
 
+    if ($result && $oldversion < 2008081700) {
+
+        /////////////////////////////////////
+        /// new file storage upgrade code ///
+        /////////////////////////////////////
+
+        $fs = get_file_storage();
+
+        $empty = $DB->sql_empty(); // silly oracle empty string handling workaround
+
+        $sqlfrom = "FROM {glossary_entries} ge
+                    JOIN {glossary} g ON g.id = ge.glossaryid
+                    JOIN {modules} m ON m.name = 'glossary'
+                    JOIN {course_modules} cm ON (cm.module = m.id AND cm.instance = g.id)
+                   WHERE ge.attachment <> '$empty' AND ge.attachment <> '1'
+                ORDER BY g.course, g.id";
+
+        $count = $DB->count_records_sql("SELECT COUNT('x') $sqlfrom");
+
+        if ($rs = $DB->get_recordset_sql("SELECT ge.id, ge.userid, ge.attachment, ge.glossaryid, ge.sourceglossaryid, g.course, cm.id AS cmid $sqlfrom")) {
+
+            $pbar = new progress_bar('migrateglossaryfiles', 500, true);
+
+            $olddebug = $DB->get_debug();
+            $DB->set_debug(false); // lower debug level, there might be very many files
+            $i = 0;
+            foreach ($rs as $entry) {
+                $i++;
+                upgrade_set_timeout(60); // set up timeout, may also abort execution
+                $pbar->update($i, $count, "Migrating glossary entries - $i/$count.");
+
+                $filepath = "$CFG->dataroot/$entry->course/$CFG->moddata/glossary/$entry->glossaryid/$entry->id/$entry->attachment";
+                if (!is_readable($filepath)) {
+                    //eh - try the second possible location
+                    $filepath2 = $filepath;
+                    $filepath = "$CFG->dataroot/$entry->course/$CFG->moddata/glossary/$entry->sourceglossaryid/$entry->id/$entry->attachment";
+                    
+                }
+                if (!is_readable($filepath)) {
+                    //file missing??
+                    notify("File not readable, skipping: $filepath2 and $filepath");
+                    $entry->attachment = '';
+                    $DB->update_record('glossary_entries', $entry);
+                    continue;
+                }
+                $context = get_context_instance(CONTEXT_MODULE, $entry->cmid);
+
+                $filearea = 'glossary_attachment';
+                $filename = clean_param($entry->attachment, PARAM_FILE);
+                if ($filename === '') {
+                    notify("Unsupported entry filename, skipping: ".$filepath);
+                    $entry->attachment = '';
+                    $DB->update_record('glossary_entries', $entry);
+                    continue;
+                }
+                if (!$fs->file_exists($context->id, $filearea, $entry->id, '/', $filename)) {
+                    $file_record = array('contextid'=>$context->id, 'filearea'=>$filearea, 'itemid'=>$entry->id, 'filepath'=>'/', 'filename'=>$filename, 'userid'=>$entry->userid);
+                    if ($fs->create_file_from_pathname($file_record, $filepath)) {
+                        $entry->attachment = '1';
+                        if ($DB->update_record('glossary_entries', $entry)) {
+                            unlink($filepath);
+                        }
+                    }
+                }
+
+                // remove dirs if empty
+                @rmdir("$CFG->dataroot/$entry->course/$CFG->moddata/glossary/$entry->glossaryid/$entry->id");
+                @rmdir("$CFG->dataroot/$entry->course/$CFG->moddata/glossary/$entry->glossaryid");
+                @rmdir("$CFG->dataroot/$entry->course/$CFG->moddata/glossary");
+            }
+            $DB->set_debug($olddebug); // reset debug level
+            $rs->close();
+        }
+
+        upgrade_mod_savepoint($result, 2008081700, 'glossary');
+    }
+
     return $result;
 }
 
index 035ead082e0140b0759203049c66f1e5e4c7dfac..0ed6e15d466c243846732857ef6353a880930925 100644 (file)
@@ -3,17 +3,16 @@
     require_once("../../config.php");
     require_once("lib.php");
 
-    $id      = required_param('id', PARAM_INT);          // course module ID
-    $confirm = optional_param('confirm', 0, PARAM_INT);  // commit the operation?
-    $entry   = optional_param('entry', 0, PARAM_INT);    // entry id
+    $id       = required_param('id', PARAM_INT);          // course module ID
+    $confirm  = optional_param('confirm', 0, PARAM_INT);  // commit the operation?
+    $entry    = optional_param('entry', 0, PARAM_INT);    // entry id
+    $prevmode = required_param('prevmode', PARAM_ALPHA);
+    $hook     = optional_param('hook', '', PARAM_CLEAN);
 
-    $prevmode = required_param('prevmode');
-    $hook = optional_param('hook', '', PARAM_CLEAN);
-
-    $strglossary = get_string("modulename", "glossary");
+    $strglossary   = get_string("modulename", "glossary");
     $strglossaries = get_string("modulenameplural", "glossary");
-    $stredit = get_string("edit");
-    $entrydeleted = get_string("entrydeleted","glossary");
+    $stredit       = get_string("edit");
+    $entrydeleted  = get_string("entrydeleted","glossary");
 
 
     if (! $cm = get_coursemodule_from_id('glossary', $id)) {
@@ -30,8 +29,8 @@
 
     require_login($course->id, false, $cm);
     $context = get_context_instance(CONTEXT_MODULE, $cm->id);
-    $manageentries = has_capability('mod/glossary:manageentries', $context); 
-    
+    $manageentries = has_capability('mod/glossary:manageentries', $context);
+
     if (! $glossary = $DB->get_record("glossary", array("id"=>$cm->instance))) {
         print_error('invalidid', 'glossary');
     }
@@ -40,9 +39,6 @@
     $strareyousuredelete = get_string("areyousuredelete","glossary");
 
     $navigation = build_navigation('', $cm);
-    print_header_simple(format_string($glossary->name), "", $navigation,
-                  "", "", true, update_module_button($cm->id, $course->id, $strglossary),
-                  navmenu($course, $cm));
 
     if (($entry->userid != $USER->id) and !$manageentries) { // guest id is never matched, no need for special check here
         print_error('nopermissiontodelentry');
 
 /// If data submitted, then process and store.
 
-    if ($confirm) { // the operation was confirmed.
+    if ($confirm and confirm_sesskey()) { // the operation was confirmed.
         // if it is an imported entry, just delete the relation
 
-        if ( $entry->sourceglossaryid ) {
-            $dbentry = new stdClass;
-            $dbentry->id = $entry->id;
-            $dbentry->glossaryid = $entry->sourceglossaryid;
-            $dbentry->sourceglossaryid = 0;
-            if (! $DB->update_record('glossary_entries', $dbentry)) {
+        if ($entry->sourceglossaryid) {
+            if (!$newcm = get_coursemodule_from_instance('glossary', $entry->sourceglossaryid)) {
+                print_error('invalidcoursemodule');
+            }
+            $newcontext = get_context_instance(CONTEXT_MODULE, $newcm->id);
+
+            $entry->glossaryid       = $entry->sourceglossaryid;
+            $entry->sourceglossaryid = 0;
+            if (!$DB->update_record('glossary_entries', $entry)) {
                 print_error('cantupdateglossary', 'glossary');
             }
 
-        } else {
-            if ( $entry->attachment ) {
-                glossary_delete_old_attachments($entry);
+            // move attachments too
+            $fs = get_file_storage();
+
+            if ($oldfiles = $fs->get_area_files($context->id, 'glossary_attachment', $entry->id)) {
+                foreach ($oldfiles as $oldfile) {
+                    $file_record = new object();
+                    $file_record->contextid = $newcontext->id;
+                    $fs->create_file_from_storedfile($file_record, $oldfile);
+                }
+                $fs->delete_area_files($context->id, 'glossary_attachment', $entry->id);
+                $entry->attachment = '1';
+            } else {
+                $entry->attachment = '0';
             }
+            $DB->update_record('glossary_entries', $entry);
+
+        } else {
+            $fs = get_file_storage();
+            $fs->delete_area_files($context->id, 'glossary_attachment', $entry->id);
             $DB->delete_records("glossary_comments", array("entryid"=>$entry->id));
             $DB->delete_records("glossary_alias", array("entryid"=>$entry->id));
             $DB->delete_records("glossary_ratings", array("entryid"=>$entry->id));
         }
 
         add_to_log($course->id, "glossary", "delete entry", "view.php?id=$cm->id&amp;mode=$prevmode&amp;hook=$hook", $entry->id,$cm->id);
-        redirect("view.php?id=$cm->id&amp;mode=$prevmode&amp;hook=$hook", $entrydeleted);
+        redirect("view.php?id=$cm->id&amp;mode=$prevmode&amp;hook=$hook");
 
     } else {        // the operation has not been confirmed yet so ask the user to do so
-
-        notice_yesno("<b>".format_string($entry->concept)."</b><p>$strareyousuredelete</p>",
-                      "deleteentry.php?id=$cm->id&amp;mode=delete&amp;confirm=1&amp;entry=".s($entry->id)."&amp;prevmode=$prevmode&amp;hook=$hook",
-                      "view.php?id=$cm->id&amp;mode=$prevmode&amp;hook=$hook");
-
+        print_header_simple(format_string($glossary->name), "", $navigation,
+                      "", "", true, update_module_button($cm->id, $course->id, $strglossary),
+                      navmenu($course, $cm));
+        $areyousure = "<b>".format_string($entry->concept)."</b><p>$strareyousuredelete</p>";
+        $linkyes    = 'deleteentry.php';
+        $linkno     = 'view.php';
+        $optionsyes = array('id'=>$cm->id, 'entry'=>$entry->id, 'confirm'=>1, 'sesskey'=>sesskey(), 'prevmode'=>$prevmode, 'hook'=>$hook);
+        $optionsno  = array('id'=>$cm->id, 'mode'=>$prevmode, 'hook'=>$hook);
+
+        notice_yesno($areyousure, $linkyes, $linkno, $optionsyes, $optionsno, 'post', 'get');
+
+        print_footer($course);
     }
-
-    print_footer($course);
-
 ?>
index 3f2a4e56777fcafc4cbbe914fdaca5c8836f831f..7450360b3cbab06cb163c67e42244c34c74ab9bf 100644 (file)
@@ -6,214 +6,180 @@ require_once('edit_form.php');
 
 global $CFG, $USER;
 
-$id = required_param('id', PARAM_INT);                // Course Module ID
-$e  = optional_param('e', 0, PARAM_INT);              // EntryID
-$confirm = optional_param('confirm',0, PARAM_INT);    // proceed. Edit the edtry
+$cmid = required_param('cmid', PARAM_INT);            // Course Module ID
+$id   = optional_param('id', 0, PARAM_INT);           // EntryID
 
-$mode = optional_param('mode', '', PARAM_ALPHA);      // categories if by category?
-$hook = optional_param('hook', '', PARAM_ALPHANUM);   // CategoryID
-
-if (! $cm = get_coursemodule_from_id('glossary', $id)) {
+if (!$cm = get_coursemodule_from_id('glossary', $cmid)) {
     print_error('invalidcoursemodule');
 }
 
-$context = get_context_instance(CONTEXT_MODULE, $cm->id);
-
-if (! $course = $DB->get_record("course", array("id"=>$cm->course))) {
+if (!$course = $DB->get_record('course', array('id'=>$cm->course))) {
     print_error('coursemisconf');
 }
 
 require_login($course->id, false, $cm);
 
-if ( isguest() ) {
-    print_error('guestnoedit', 'glossary', $_SERVER["HTTP_REFERER"]);
+$context = get_context_instance(CONTEXT_MODULE, $cm->id);
+
+if (isguestuser()) {
+    print_error('guestnoedit', 'glossary', "$CFG->wwwroot/mod/glossary/view.php?id=$cmid");
 }
 
-if (! $glossary = $DB->get_record("glossary", array("id"=>$cm->instance))) {
+if (!$glossary = $DB->get_record('glossary', array('id'=>$cm->instance))) {
     print_error('invalidid', 'glossary');
 }
 
+$mform = new mod_glossary_entry_form(null, compact('cm', 'glossary'));
 
-if ($e) { // if entry is specified
-    if (!$entry  = $DB->get_record("glossary_entries", array("id"=>$e))) {
+if ($id) { // if entry is specified
+    if (!$entry = $DB->get_record('glossary_entries', array('id'=>$id, 'glossaryid'=>$glossary->id))) {
         print_error('invalidentry');
     }
+
     $ineditperiod = ((time() - $entry->timecreated <  $CFG->maxeditingtime) || $glossary->editalways);
     if (!has_capability('mod/glossary:manageentries', $context) and !($entry->userid == $USER->id and ($ineditperiod and has_capability('mod/glossary:write', $context)))) {
-        //expired edit time is the most probable cause here
-        print_error('erredittimeexpired', 'glossary', 'view.php?id=$cm->id&amp;mode=entry&amp;hook=$e');
+        if ($USER->id != $fromdb->userid) {
+            print_error('errcannoteditothers', 'glossary', "view.php?id=$cm->id&amp;mode=entry&amp;hook=$id");
+        } elseif (!$ineditperiod) {
+            print_error('erredittimeexpired', 'glossary', "view.php?id=$cm->id&amp;mode=entry&amp;hook=$id");
+        }
     }
+
+    //prepare extra data
+    trusttext_prepare_edit($entry->definition, $entry->format, can_use_html_editor(), $context);
+    if ($aliases = $DB->get_records_menu("glossary_alias", array("entryid"=>$id), '', 'id, alias')) {
+        $entry->aliases = implode("\n", $aliases) . "\n";
+    }
+    if ($categoriesarr = $DB->get_records_menu("glossary_entries_categories", array('entryid'=>$id), '', 'id, categoryid')) {
+        // TODO: this fetches cats from both main and secondary glossary :-(
+        $entry->categories = array_values($categoriesarr);
+    }
+    $entry->cmid = $cm->id;
+
 } else { // new entry
     require_capability('mod/glossary:write', $context);
+    $entry = new object();
+    $entry->cmid = $cm->id;
 }
 
-$mform = new mod_glossary_entry_form(null, compact('cm', 'glossary', 'hook', 'mode', 'e', 'context'));
+// set form initial data
+$mform->set_data($entry);
+
+
 if ($mform->is_cancelled()){
-    if ($e){
-        redirect("view.php?id=$cm->id&amp;mode=entry&amp;hook=$e");
+    if ($id){
+        redirect("view.php?id=$cm->id&amp;mode=entry&amp;hook=$id");
     } else {
         redirect("view.php?id=$cm->id");
     }
 
-} elseif ($fromform = $mform->get_data()) {
-    trusttext_after_edit($fromform->definition, $context);
+} else if ($data = $mform->get_data()) {
+    trusttext_after_edit($data->definition, $context);
 
-    if ( !isset($fromform->usedynalink) ) {
-        $fromform->usedynalink = 0;
-    }
-    if ( !isset($fromform->casesensitive) ) {
-        $fromform->casesensitive = 0;
-    }
-    if ( !isset($fromform->fullmatch) ) {
-        $fromform->fullmatch = 0;
-    }
     $timenow = time();
 
-    $todb = new object();
-    $todb->course = $glossary->course;
-    $todb->glossaryid = $glossary->id;
-
-    $todb->concept = trim($fromform->concept);
-    $todb->definition = $fromform->definition;
-    $todb->format = $fromform->format;
-    $todb->usedynalink = $fromform->usedynalink;
-    $todb->casesensitive = $fromform->casesensitive;
-    $todb->fullmatch = $fromform->fullmatch;
-    $todb->timemodified = $timenow;
-    $todb->approved = 0;
-    $todb->aliases = "";
-    if ( $glossary->defaultapproval or has_capability('mod/glossary:approve', $context) ) {
-        $todb->approved = 1;
+    if (empty($entry->id)) {
+        $entry->glossaryid       = $glossary->id;
+        $entry->timecreated      = $timenow;
+        $entry->userid           = $USER->id;
+        $entry->timecreated      = $timenow;
+        $entry->sourceglossaryid = 0;
+        $entry->teacherentry     = has_capability('mod/glossary:manageentries', $context);
     }
 
-    if ($e) {
-        $todb->id = $e;
-        $dir = glossary_file_area_name($todb);
-        if ($mform->save_files($dir) and $newfilename = $mform->get_new_filename()) {
-            $todb->attachment = $newfilename;
+    $entry->concept       = trim($data->concept);
+    $entry->definition    = $data->definition;
+    $entry->format        = $data->format;
+    $entry->timemodified  = $timenow;
+    $entry->approved      = 0;
+    $entry->usedynalink   = isset($data->usedynalink) ?   $data->usedynalink : 0;
+    $entry->casesensitive = isset($data->casesensitive) ? $data->casesensitive : 0;
+    $entry->fullmatch     = isset($data->fullmatch) ?     $data->fullmatch : 0;
+
+    if ($glossary->defaultapproval or has_capability('mod/glossary:approve', $context)) {
+        $entry->approved = 1;
+    }
+
+    if (empty($entry->id)) {
+        //new entry
+        if ($entry->id = $DB->insert_record('glossary_entries', $entry)) {
+            add_to_log($course->id, "glossary", "add entry",
+                       "view.php?id=$cm->id&amp;mode=entry&amp;hook=$enty->id", $entry->id, $cm->id);
+        } else {
+            print_error('cantinsertent', 'glossary');
         }
+        //refetch complete entry
+        $entry = $DB->get_record('glossary_entries', array('id'=>$entry->id));
 
-        if ($DB->update_record('glossary_entries', $todb)) {
+    } else {
+        //existing entry
+        if ($DB->update_record('glossary_entries', $entry)) {
             add_to_log($course->id, "glossary", "update entry",
-                       "view.php?id=$cm->id&amp;mode=entry&amp;hook=$todb->id",
-                       $todb->id, $cm->id);
+                       "view.php?id=$cm->id&amp;mode=entry&amp;hook=$entry->id",
+                       $entry->id, $cm->id);
         } else {
             print_error('cantupdateglossary', 'glossary');
         }
-    } else {
+    }
 
-        $todb->userid = $USER->id;
-        $todb->timecreated = $timenow;
-        $todb->sourceglossaryid = 0;
-        $todb->teacherentry = has_capability('mod/glossary:manageentries', $context);
+    // save attachment
+    $filename = $mform->get_new_filename('attachment');
 
+    if ($filename !== false) {
+        $filearea = 'glossary_attachment';
+        $fs = get_file_storage();
 
-        if ($todb->id = $DB->insert_record("glossary_entries", $todb)) {
-            $e = $todb->id;
-            $dir = glossary_file_area_name($todb);
-            if ($mform->save_files($dir) and $newfilename = $mform->get_new_filename()) {
-                $DB->set_field("glossary_entries", "attachment", $newfilename, array("id"=>$todb->id));
-            }
-            add_to_log($course->id, "glossary", "add entry",
-                       "view.php?id=$cm->id&amp;mode=entry&amp;hook=$todb->id", $todb->id,$cm->id);
+        $fs->delete_area_files($context->id, $filearea, $entry->id);
+
+        if ($mform->save_stored_file('attachment', $context->id, $filearea, $entry->id, '/', $filename, true, $USER->id)) {
+            $entry->attachment = '1';
         } else {
-            print_error('cantinsertent', 'glossary');
+            $entry->attachment = '';
         }
-
+        $DB->update_record('glossary_entries', $entry);
     }
 
-    $DB->delete_records("glossary_entries_categories", array("entryid"=>$e));
-    $DB->delete_records("glossary_alias", array("entryid"=>$e));
-
-    if (empty($fromform->notcategorised) && isset($fromform->categories)) {
-        $newcategory->entryid = $e;
-        foreach ($fromform->categories as $category) {
-            if ( $category > 0 ) {
-                $newcategory->categoryid = $category;
-                $DB->insert_record("glossary_entries_categories", $newcategory, false);
-            } else {
-                break;
-            }
-        }
-    }
-    if ( isset($fromform->aliases) ) {
-        if ( $aliases = explode("\n", $fromform->aliases) ) {
-            foreach ($aliases as $alias) {
-                $alias = trim($alias);
-                if ($alias) {
-                    $newalias = new object();
-                    $newalias->entryid = $e;
-                    $newalias->alias = $alias;
-                    $DB->insert_record("glossary_alias", $newalias, false);
-                }
-            }
+    // update entry categories
+    $DB->delete_records('glossary_entries_categories', array('entryid'=>$entry->id));
+    // TODO: this deletes cats from both both main and secondary glossary :-(
+    if (!empty($data->categories) and array_search(0, $data->categories) === false) {
+        foreach ($data->categories as $catid) {
+            $newcategory = new object();
+            $newcategory->entryid    = $entry->id;
+            $newcategory->categoryid = $catid;
+            $DB->insert_record('glossary_entries_categories', $newcategory, false);
         }
     }
-    redirect("view.php?id=$cm->id&amp;mode=entry&amp;hook=$todb->id");
-
-} else {
-    if ($e) {
-        $fromdb = $DB->get_record("glossary_entries", array("id"=>$e));
 
-        $toform = new object();
-
-        if ($categoriesarr = $DB->get_records_menu("glossary_entries_categories", array("entryid"=>$e), '', 'id, categoryid')){
-            $toform->categories = array_values($categoriesarr);
-        } else {
-            $toform->categories = array(0);
-        }
-        $toform->concept = $fromdb->concept;
-        $toform->definition = $fromdb->definition;
-        $toform->format = $fromdb->format;
-        trusttext_prepare_edit($toform->definition, $toform->format, can_use_html_editor(), $context);
-        $toform->approved = $glossary->defaultapproval or has_capability('mod/glossary:approve', $context);
-        $toform->usedynalink = $fromdb->usedynalink;
-        $toform->casesensitive = $fromdb->casesensitive;
-        $toform->fullmatch = $fromdb->fullmatch;
-        $toform->aliases = '';
-        $ineditperiod = ((time() - $fromdb->timecreated <  $CFG->maxeditingtime) || $glossary->editalways);
-        if ((!$ineditperiod  || $USER->id != $fromdb->userid) and !has_capability('mod/glossary:manageentries', $context)) {
-            if ( $USER->id != $fromdb->userid ) {
-                print_error('errcannoteditothers', 'glossary');
-            } elseif (!$ineditperiod) {
-                print_error('erredittimeexpired', 'glossary');
+    // update aliases
+    $DB->delete_records('glossary_alias', array('entryid'=>$entry->id));
+    $aliases = trim($data->aliases);
+    if ($aliases !== '') {
+        $aliases = explode("\n", $aliases);
+        foreach ($aliases as $alias) {
+            $alias = trim($alias);
+            if ($alias !== '') {
+                $newalias = new object();
+                $newalias->entryid = $entry->id;
+                $newalias->alias   = $alias;
+                $DB->insert_record('glossary_alias', $newalias, false);
             }
-            die;
         }
-
-        if ( $aliases = $DB->get_records_menu("glossary_alias", array("entryid"=>$e), '', 'id, alias') ) {
-            $toform->aliases = implode("\n", $aliases) . "\n";
-        }
-        $mform->set_data($toform);
     }
+
+    redirect("view.php?id=$cm->id&amp;mode=entry&amp;hook=$entry->id");
 }
 
-$stredit = empty($e) ? get_string('addentry', 'glossary') : get_string("edit");
+$stredit = empty($entry->id) ? get_string('addentry', 'glossary') : get_string('edit');
+
 $navigation = build_navigation($stredit, $cm);
 print_header_simple(format_string($glossary->name), "", $navigation, "",
               "", true, "", navmenu($course, $cm));
 
 print_heading(format_string($glossary->name));
 
-/// Info box
-
-///if ( $glossary->intro ) {
-///    print_simple_box(format_text($glossary->intro), 'center', '70%', '', 5, 'generalbox', 'intro');
-///}
-
-/// Tabbed browsing sections
-///$tab = GLOSSARY_ADDENTRY_VIEW;
-///include("tabs.php");
-
-if (!$e) {
-    require_capability('mod/glossary:write', $context);
-}
-
 $mform->display();
 
-///glossary_print_tabbed_table_end();
-
-
 print_footer($course);
 
 ?>
index 1bb971c8c596b9c8540d3487c928a4406ecb34fc..224f5f03e2d098ab33cd8aa394f1385e663f4323 100644 (file)
@@ -4,15 +4,11 @@ require_once ($CFG->dirroot.'/lib/formslib.php');
 class mod_glossary_entry_form extends moodleform {
 
     function definition() {
+        global $CFG, $DB;
 
-        global $CFG, $COURSE, $DB;
-        $mform    =& $this->_form;
-
-        $glossary =& $this->_customdata['glossary'];
-        $mode     =& $this->_customdata['mode'];
-        $cm       =& $this->_customdata['cm'];
-        $hook     =& $this->_customdata['hook'];
-        $e        =& $this->_customdata['e'];
+        $mform    = $this->_form;
+        $glossary = $this->_customdata['glossary'];
+        $cm       = $this->_customdata['cm'];
 
 //-------------------------------------------------------------------------------
         $mform->addElement('header', 'general', get_string('general', 'form'));
@@ -28,67 +24,46 @@ class mod_glossary_entry_form extends moodleform {
 
         $mform->addElement('format');
 
-        $categories = array();
         if ($categories = $DB->get_records_menu('glossary_categories', array('glossaryid'=>$glossary->id), 'name ASC', 'id, name')){
             $categories = array(0 => get_string('notcategorised', 'glossary')) + $categories;
-        } else {
-            $categories = array(0 => get_string('notcategorised', 'glossary'));
+            $categoriesEl = $mform->addElement('select', 'categories', get_string('categories', 'glossary'), $categories);
+            $categoriesEl->setMultiple(true);
+            $categoriesEl->setSize(5);
         }
 
-        $categoriesEl =& $mform->addElement('select', 'categories', get_string('categories', 'glossary'), $categories);
-        $categoriesEl->setMultiple(true);
-        $categoriesEl->setSize(5);
-
         $mform->addElement('textarea', 'aliases', get_string('aliases', 'glossary'), 'rows="2" cols="40"');
         $mform->setType('aliases', PARAM_TEXT);
         $mform->setHelpButton('aliases', array('aliases2', strip_tags(get_string('aliases', 'glossary')), 'glossary'));
 
-        $this->set_upload_manager(new upload_manager('attachment', true, false, $COURSE, false, 0, true, true, false));
         $mform->addElement('file', 'attachment', get_string('attachment', 'forum'));
         $mform->setHelpButton('attachment', array('attachment', get_string('attachment', 'glossary'), 'glossary'));
 
-        if (isset($CFG->glossary_linkentries)) {
-            $usedynalink = $CFG->glossary_linkentries;
-        } else {
-            $usedynalink = 0;
-        }
-        if (isset($CFG->glossary_casesensitive)) {
-            $casesensitive = $CFG->glossary_casesensitive;
-        } else {
-            $casesensitive = 0;
-        }
-        if (isset($CFG->glossary_fullmatch)) {
-            $fullmatch = $CFG->glossary_fullmatch;
-        } else {
-            $fullmatch = 0;
-        }
-        if ( !$glossary->usedynalink ) {
-            $mform->addElement('hidden', 'usedynalink', $usedynalink);
-            $mform->addElement('hidden', 'casesensitive', $casesensitive);
-            $mform->addElement('hidden', 'fullmatch', $fullmatch);
+        if (!$glossary->usedynalink) {
+            $mform->addElement('hidden', 'usedynalink',   $CFG->glossary_linkentries);
+            $mform->addElement('hidden', 'casesensitive', $CFG->glossary_casesensitive);
+            $mform->addElement('hidden', 'fullmatch',     $CFG->glossary_fullmatch);
+
         } else {
 //-------------------------------------------------------------------------------
             $mform->addElement('header', 'linkinghdr', get_string('linking', 'glossary'));
 
             $mform->addElement('checkbox', 'usedynalink', get_string('entryusedynalink', 'glossary'));
             $mform->setHelpButton('usedynalink', array('usedynalinkentry', strip_tags(get_string('usedynalink', 'glossary')), 'glossary'));
-            $mform->setDefault('usedynalink', $usedynalink);
+            $mform->setDefault('usedynalink', $CFG->glossary_linkentries);
 
             $mform->addElement('checkbox', 'casesensitive', get_string('casesensitive', 'glossary'));
             $mform->setHelpButton('casesensitive', array('casesensitive', strip_tags(get_string('casesensitive', 'glossary')), 'glossary'));
             $mform->disabledIf('casesensitive', 'usedynalink');
-            $mform->setDefault('casesensitive', $casesensitive);
+            $mform->setDefault('casesensitive', $CFG->glossary_casesensitive);
 
             $mform->addElement('checkbox', 'fullmatch', get_string('fullmatch', 'glossary'));
             $mform->setHelpButton('fullmatch', array('fullmatch', strip_tags(get_string('fullmatch', 'glossary')), 'glossary'));
             $mform->disabledIf('fullmatch', 'usedynalink');
-            $mform->setDefault('fullmatch', $fullmatch);
+            $mform->setDefault('fullmatch', $CFG->glossary_fullmatch);
         }
 
-        $mform->addElement('hidden', 'e', $e);
-        $mform->addElement('hidden', 'id', $cm->id);
-        $mform->addElement('hidden', 'mode', $mode);
-        $mform->addElement('hidden', 'hook', $hook);
+        $mform->addElement('hidden', 'id');
+        $mform->addElement('hidden', 'cmid');
 
 //-------------------------------------------------------------------------------
         $this->add_action_buttons();
@@ -96,30 +71,33 @@ class mod_glossary_entry_form extends moodleform {
 
     function validation($data, $files) {
         global $CFG, $USER, $DB;
-
         $errors = parent::validation($data, $files);
-        $e = $this->_customdata['e'];
+
         $glossary = $this->_customdata['glossary'];
-        $context = $this->_customdata['context'];
+        $cm       = $this->_customdata['cm'];
+        $context  = get_context_instance(CONTEXT_MODULE, $cm->id);
+
+        $id = (int)$data['id'];
         $data['concept'] = trim($data['concept']);
-        if ($e) {
+
+        if ($id) {
             //We are updating an entry, so we compare current session user with
             //existing entry user to avoid some potential problems if secureforms=off
             //Perhaps too much security? Anyway thanks to skodak (Bug 1823)
-            $old = $DB->get_record('glossary_entries', array('id'=>$e));
+            $old = $DB->get_record('glossary_entries', array('id'=>$id));
             $ineditperiod = ((time() - $old->timecreated <  $CFG->maxeditingtime) || $glossary->editalways);
-            if ( (!$ineditperiod  || $USER->id != $old->userid) and !has_capability('mod/glossary:manageentries', $context)) {
-                if ( $USER->id != $old->userid ) {
+            if ((!$ineditperiod || $USER->id != $old->userid) and !has_capability('mod/glossary:manageentries', $context)) {
+                if ($USER->id != $old->userid) {
                     $errors['concept'] = get_string('errcannoteditothers', 'glossary');
                 } elseif (!$ineditperiod) {
                     $errors['concept'] = get_string('erredittimeexpired', 'glossary');
                 }
             }
-            if ( !$glossary->allowduplicatedentries ) {
-                if ($dupentries = $DB->get_records('glossary_entries', array('lower(concept)'=>moodle_strtolower($data['concept'])))) {
+            if (!$glossary->allowduplicatedentries) {
+                if ($dupentries = $DB->get_records('glossary_entries', array('LOWER(concept)'=>moodle_strtolower($data['concept'])))) {
                     foreach ($dupentries as $curentry) {
-                        if ( $glossary->id == $curentry->glossaryid ) {
-                           if ( $curentry->id != $e ) {
+                        if ($glossary->id == $curentry->glossaryid) {
+                           if ($curentry->id != $id) {
                                $errors['concept'] = get_string('errconceptalreadyexists', 'glossary');
                                break;
                            }
@@ -129,14 +107,14 @@ class mod_glossary_entry_form extends moodleform {
             }
 
         } else {
-            if ( !$glossary->allowduplicatedentries ) {
-                if ($dupentries = $DB->get_record('glossary_entries', array('lower(concept)'=>moodle_strtolower($data['concept']), 'glossaryid'=>$glossary->id))) {
+            if (!$glossary->allowduplicatedentries) {
+                if ($dupentries = $DB->get_record('glossary_entries', array('LOWER(concept)'=>moodle_strtolower($data['concept']), 'glossaryid'=>$glossary->id))) {
                     $errors['concept'] = get_string('errconceptalreadyexists', 'glossary');
                 }
             }
         }
+
         return $errors;
     }
-
 }
 ?>
index 3293d3d578f4108506ecd0745d3e5417b6b95f53..2302d10c2a5916a08390d7eefe554ef3b30f644b 100644 (file)
     require_once('../../config.php');
     require_once('lib.php');
 
-    $id    = required_param('id', PARAM_INT);           // course module ID
-    $entry = required_param('entry', PARAM_INT);     // Entry ID
-    $confirm = optional_param('confirm', 0, PARAM_INT); // confirmation
+    $id       = required_param('id', PARAM_INT);          // Entry ID
+    $confirm  = optional_param('confirm', 0, PARAM_BOOL); // export confirmation
+    $prevmode = required_param('prevmode', PARAM_ALPHA);
+    $hook     = optional_param('hook', '', PARAM_CLEAN);
 
-    $hook = optional_param('hook', '', PARAM_ALPHANUM);
-    $mode = optional_param('mode', '', PARAM_ALPHA);
-        
-    global $USER, $CFG;
-
-    $PermissionGranted = 1;
+    if (!$entry = $DB->get_record('glossary_entries', array('id'=>$id))) {
+        print_error('invalidentry');
+    }
 
-    $cm = get_coursemodule_from_id('glossary', $id);
-    if ( ! $cm ) {
-        $PermissionGranted = 0;
-    } else {
-        $mainglossary = $DB->get_record('glossary', array('course'=>$cm->course, 'mainglossary'=>1));
-        if ( ! $mainglossary ) {
-            $PermissionGranted = 0;
+    if ($entry->sourceglossaryid) {
+        //already exported
+        if (!$cm = get_coursemodule_from_id('glossary', $entry->sourceglossaryid)) {
+            print_error('invalidcoursemodule');
         }
+        redirect('view.php?id='.$cm->id.'&amp;mode=entry&amp;hook='.$entry->id);
+    }
+
+    if (!$cm = get_coursemodule_from_instance('glossary', $entry->glossaryid)) {
+        print_error('invalidcoursemodule');
     }
-    
+
+    if (!$glossary = $DB->get_record('glossary', array('id'=>$cm->instance))) {
+        print_error('invalidid', 'glossary');
+    }
+
+    if (!$course = $DB->get_record('course', array('id'=>$cm->course))) {
+        print_error('coursemisconf');
+    }
+
+    require_course_login($course->id, true, $cm);
     $context = get_context_instance(CONTEXT_MODULE, $cm->id);
     require_capability('mod/glossary:export', $context);
 
-    if (! $course = $DB->get_record('course', array('id'=>$cm->course))) {
-        print_error('coursemisconf');
+    $returnurl = "view.php?id=$cm->id&amp;mode=$prevmode&amp;hook=".urlencode($hook);
+
+    if (!$mainglossary = $DB->get_record('glossary', array('course'=>$cm->course, 'mainglossary'=>1))) {
+        //main glossary not present
+        redirect($returnurl);
     }
 
-    if (! $glossary = $DB->get_record('glossary', array('id'=>$cm->instance))) {
-        print_error('invalidid', 'glossary');
+    if (!$maincm = get_coursemodule_from_instance('glossary', $mainglossary->id)) {
+        print_error('invalidcoursemodule');
+    }
+
+    $context     = get_context_instance(CONTEXT_MODULE, $cm->id);
+    $maincontext = get_context_instance(CONTEXT_MODULE, $maincm->id);
+
+    if (!$course = $DB->get_record('course', array('id'=>$cm->course))) {
+        print_error('coursemisconf');
     }
 
-    $strglossaries   = get_string('modulenameplural', 'glossary');
+
+    $strglossaries     = get_string('modulenameplural', 'glossary');
     $entryalreadyexist = get_string('entryalreadyexist','glossary');
-    $entryexported = get_string('entryexported','glossary');
+    $entryexported     = get_string('entryexported','glossary');
 
     $navigation = build_navigation('', $cm);
-    print_header_simple(format_string($glossary->name), '', $navigation, '', '', true, '', navmenu($course, $cm));
-
-    if ( $PermissionGranted ) {
-        $entry = $DB->get_record('glossary_entries', array('id'=>$entry));
-
-        if ( !$confirm ) {
-            echo '<div class="boxaligncenter">';
-            $areyousure = get_string('areyousureexport','glossary');
-            notice_yesno ('<h2>'.format_string($entry->concept).'</h2><p align="center">'.$areyousure.'<br /><b>'.format_string($mainglossary->name).'</b>?',
-                'exportentry.php?id='.$id.'&amp;mode='.$mode.'&amp;hook='.$hook.'&amp;entry='.$entry->id.'&amp;confirm=1',
-                'view.php?id='.$cm->id.'&amp;mode='.$mode.'&amp;hook='.$hook);
-            echo '</div>';
-        } else {
-            if ( ! $mainglossary->allowduplicatedentries ) {
-                $dupentry = $DB->get_record('glossary_entries', array('glossaryid'=>$mainglossary->id, 'lower(concept)'=>moodle_strtolower($entry->concept)));
-                if ( $dupentry ) {
-                    $PermissionGranted = 0;
-                }
-            }
-            if ( $PermissionGranted ) {
-
-                $dbentry = new stdClass;
-                $dbentry->id = $entry->id;
-                $dbentry->glossaryid       = $mainglossary->id;
-                $dbentry->sourceglossaryid = $glossary->id;
-                
-                if (! $DB->update_record('glossary_entries', $dbentry)) {
-                    print_error('cantexportentry', 'glossary');
-                } else {
-                    print_simple_box_start('center', '60%');
-                    echo '<p align="center"><font size="3">'.$entryexported.'</font></p></font>';
-
-                    print_continue('view.php?id='.$cm->id.'&amp;mode=entry&amp;hook='.$entry->id);
-                    print_simple_box_end();
-
-                    print_footer();
-
-                    redirect('view.php?id='.$cm->id.'&amp;mode=entry&amp;hook='.$entry->id);
-                    die;
-                }
-            } else {
-                print_simple_box_start('center', '60%', '#FFBBBB');
-                echo '<p align="center"><font size="3">'.$entryalreadyexist.'</font></p></font>';
-                echo '<p align="center">';
-
-                print_continue('view.php?id='.$cm->id.'&amp;mode=entry&amp;hook='.$entry->id);
-
-                print_simple_box_end();
-            }
+
+    if (!$mainglossary->allowduplicatedentries) {
+        if ($DB->get_record('glossary_entries', array('glossaryid'=>$mainglossary->id, 'lower(concept)'=>moodle_strtolower($entry->concept)))) {
+            print_header_simple(format_string($glossary->name), '', $navigation, '', '', true, '', navmenu($course, $cm));
+            nootify(get_string('errconceptalreadyexists', 'glossary'));
+            print_continue($returnurl);
+            print_simple_box_end();
+            print_footer();
+            die;
         }
+    }
+
+    if (!data_submitted() or !$confirm or !confirm_sesskey()) {
+        print_header_simple(format_string($glossary->name), '', $navigation, '', '', true, '', navmenu($course, $cm));
+        echo '<div class="boxaligncenter">';
+        $areyousure = '<h2>'.format_string($entry->concept).'</h2><p align="center">'.get_string('areyousureexport','glossary').'<br /><b>'.format_string($mainglossary->name).'</b>?';
+        $linkyes    = 'exportentry.php';
+        $linkno     = 'view.php';
+        $optionsyes = array('id'=>$entry->id, 'confirm'=>1, 'sesskey'=>sesskey(), 'prevmode'=>$prevmode, 'hook'=>$hook);
+        $optionsno  = array('id'=>$cm->id, 'mode'=>$prevmode, 'hook'=>$hook);
+
+        notice_yesno($areyousure, $linkyes, $linkno, $optionsyes, $optionsno, 'post', 'get');
+        echo '</div>';
+        print_footer();
+        die;
+
     } else {
-            print_simple_box_start('center', '60%', '#FFBBBB');
-            notice('A weird error was found while trying to export this entry. Operation cancelled.');
+        $entry->glossaryid       = $mainglossary->id;
+        $entry->sourceglossaryid = $glossary->id;
 
-            print_continue('view.php?id='.$cm->id.'&amp;mode=entry&amp;hook='.$entry->id);
+        if (!$DB->update_record('glossary_entries', $entry)) {
+            print_error('cantexportentry', 'glossary');
+        }
 
-            print_simple_box_end();
-    }
+        // move attachments too
+        $fs = get_file_storage();
 
-    print_footer();
+        if ($oldfiles = $fs->get_area_files($context->id, 'glossary_attachment', $entry->id)) {
+            foreach ($oldfiles as $oldfile) {
+                $file_record = new object();
+                $file_record->contextid = $maincontext->id;
+                $fs->create_file_from_storedfile($file_record, $oldfile);
+            }
+            $fs->delete_area_files($context->id, 'glossary_attachment', $entry->id);
+            $entry->attachment = '1';
+        } else {
+            $entry->attachment = '0';
+        }
+        $DB->update_record('glossary_entries', $entry);
+
+        redirect ($returnurl);
+    }
 ?>
index e593d9c17b7597dff9033e79466918e8649af982..5581e7d6b9b720f66e4ce3d9b5ff617847ff9fc5 100755 (executable)
@@ -57,7 +57,7 @@ function glossary_show_entry_TEMPLATE($course, $cm, $glossary, $entry, $mode='',
         //----Define if the attachment must be showed into a 100% width table
         $attachmentinsidetable = true; //Values: true, false (default true)
         //Call the function
-        glossary_print_entry_attachment($entry,$attachmentformat,$attachmentalign,$attachmentinsidetable);
+        glossary_print_entry_attachment($entry, $cm, $attachmentformat, $attachmentalign, $attachmentinsidetable);
 
         //Line separator to show this template fine. :-)
         echo "<br />\n";
index f87d0fc008f9374be0acfbed936f98da7c39665e..1184cefdbcf2f0112452db88749397bbd0ebcd0d 100644 (file)
@@ -8,7 +8,7 @@ function glossary_show_entry_continuous($course, $cm, $glossary, $entry, $mode='
     echo '<tr valign="top">';
     echo '<td class="entry">';
     glossary_print_entry_approval($cm, $entry, $mode);
-    glossary_print_entry_attachment($entry,'html','right');
+    glossary_print_entry_attachment($entry, $cm, 'html', 'right');
     echo '<div class="concept">';
     glossary_print_entry_concept($entry);
     echo ':</div> ';
index e24c2f661d65b8efe9abe984cdf17154aaa91cad..d671555ddef9989e351c993dec24aad237eb5168 100644 (file)
@@ -8,7 +8,7 @@ function glossary_show_entry_dictionary($course, $cm, $glossary, $entry, $mode='
     echo '<tr valign="top">';
     echo '<td class="entry">';
     glossary_print_entry_approval($cm, $entry, $mode);
-    glossary_print_entry_attachment($entry,'html','right');
+    glossary_print_entry_attachment($entry, $cm, 'html', 'right');
     echo '<div class="concept">';
     glossary_print_entry_concept($entry);
     echo ':</div> ';
index b40834b2425ff9e26e9af1ccff3166da4a7cbf88..831643c2aba5b0052db02dd701a68982e88a0b16 100644 (file)
@@ -46,7 +46,7 @@ function glossary_show_entry_encyclopedia($course, $cm, $glossary, $entry, $mode
             } else {
                 $align = 'left';
             }
-            glossary_print_entry_attachment($entry,'',$align,false);
+            glossary_print_entry_attachment($entry, $cm, null,$align,false);
         }
         glossary_print_entry_definition($entry);
 
index 0780a5802add5824178b024f8ae6379a83c2cbc0..ee6b7b481e2b95e61b1bb5c7393f94ba8238a2b3 100644 (file)
@@ -21,7 +21,7 @@ function glossary_show_entry_faq($course, $cm, $glossary, $entry, $mode="", $hoo
         echo '<td class="entryattachment">';
 
         glossary_print_entry_approval($cm, $entry, $mode);
-        glossary_print_entry_attachment($entry,'html','right');
+        glossary_print_entry_attachment($entry, $cm, 'html', 'right');
         echo '</td>';
 
         echo '</tr>';
index cc2289c8e7bcfe0000799101be882a1c5ba73fa1..67af5078ce2d0cbd05ee2f32a5361b1b6a99433d 100644 (file)
@@ -32,7 +32,7 @@ function glossary_show_entry_fullwithauthor($course, $cm, $glossary, $entry, $mo
         echo '<td class="entryattachment">';
 
         glossary_print_entry_approval($cm, $entry, $mode);
-        glossary_print_entry_attachment($entry,'html','right');
+        glossary_print_entry_attachment($entry, $cm, 'html', 'right');
         echo '</td>';
 
         echo '</tr>';
index 06534b2d44a1e2fb6a2135bfd97f0ac2ffa58729..5f29a2d0b0808550b08104fd083ab19b9b73c3b0 100644 (file)
@@ -21,7 +21,7 @@ function glossary_show_entry_fullwithoutauthor($course, $cm, $glossary, $entry,
         echo '<td class="entryattachment">';
 
         glossary_print_entry_approval($cm, $entry, $mode);
-        glossary_print_entry_attachment($entry,'html','right');
+        glossary_print_entry_attachment($entry, $cm, 'html', 'right');
         echo '</td>';
 
         echo '</tr>';
index 48681cbd9cc9724644007a9fb8aad3ba77aaccb2..017bcbe183c91e8e9cfa42e5846444b080da5412 100644 (file)
@@ -3,8 +3,6 @@
 /// Library of functions and constants for module glossary
 /// (replace glossary with the name of your module and delete this line)
 
-require_once($CFG->libdir.'/filelib.php');
-
 define("GLOSSARY_SHOW_ALL_CATEGORIES", 0);
 define("GLOSSARY_SHOW_NOT_CATEGORISED", -1);
 
@@ -105,59 +103,85 @@ function glossary_update_instance($glossary) {
     return $return;
 }
 
-
+/**
+ * Given an ID of an instance of this module,
+ * this function will permanently delete the instance
+ * and any data that depends on it.
+ * @param int $id glossary id
+ * @return bool success
+ */
 function glossary_delete_instance($id) {
     global $DB;
-/// Given an ID of an instance of this module,
-/// this function will permanently delete the instance
-/// and any data that depends on it.
 
-    if (! $glossary = $DB->get_record("glossary", array("id"=>"$id"))) {
+    if (!$glossary = $DB->get_record('glossary', array('id'=>$id))) {
         return false;
     }
 
-    $result = true;
+    if (!$cm = get_coursemodule_from_instance('glossary', $id)) {
+        return false;
+    }
 
-    # Delete any dependent records here #
+    if (!$context = get_context_instance(CONTEXT_MODULE, $cm->id)) {
+        return false;
+    }
 
-    if (! $DB->delete_records("glossary", array("id"=>$glossary->id))) {
-        $result = false;
-    } else {
-        if ($categories = $DB->get_records("glossary_categories", array("glossaryid"=>$glossary->id))) {
-            $cats = "";
-            foreach ( $categories as $cat ) {
-                $cats .= "$cat->id,";
-            }
-            $cats = substr($cats,0,-1);
-            if ($cats) {
-                $DB->delete_records_select("glossary_entries_categories", "categoryid in ($cats)");
-                $DB->delete_records("glossary_categories", array("glossaryid"=>$glossary->id));
-            }
-        }
-        if ( $entries = $DB->get_records("glossary_entries", array("glossaryid"=>$glossary->id))) {
-            $ents = "";
-            foreach ( $entries as $entry ) {
-                if ( $entry->sourceglossaryid ) {
-                    $entry->glossaryid = $entry->sourceglossaryid;
-                    $entry->sourceglossaryid = 0;
-                    $DB->update_record("glossary_entries",$entry);
+    $fs = get_file_storage();
+
+    if ($glossary->mainglossary) {
+        // unexport entries
+        $sql = "SELECT ge.id, ge.sourceglossaryid, cm.id AS sourcecmid
+                  FROM {glossary_entries} ge
+                  JOIN {modules} m ON m.name = 'glossary'
+                  JOIN {course_modules} cm ON (cm.module = m.id AND cm.instance = ge.sourceglossaryid)
+                 WHERE ge.glossaryid = ? AND ge.sourceglossaryid > 0";
+
+        if ($exported = $DB->get_records_sql($sql, array($id))) {
+            foreach ($exported as $entry) {
+                $entry->glossaryid = $entry->sourceglossaryid;
+                $entry->sourceglossaryid = 0;
+                $newcontext = get_context_instance(CONTEXT_MODULE, $entry->sourcecmid);
+                if ($oldfiles = $fs->get_area_files($context->id, 'glossary_attachment', $entry->id)) {
+                    foreach ($oldfiles as $oldfile) {
+                        $file_record = new object();
+                        $file_record->contextid = $newcontext->id;
+                        $fs->create_file_from_storedfile($file_record, $oldfile);
+                    }
+                    $fs->delete_area_files($context->id, 'glossary_attachment', $entry->id);
+                    $entry->attachment = '1';
                 } else {
-                    $ents .= "$entry->id,";
+                    $entry->attachment = '0';
                 }
-            }
-            $ents = substr($ents,0,-1);
-            if ($ents) {
-                $DB->delete_records_select("glossary_comments", "entryid in ($ents)");
-                $DB->delete_records_select("glossary_alias", "entryid in ($ents)");
-                $DB->delete_records_select("glossary_ratings", "entryid in ($ents)");
+                $DB->update_record('glossary_entries', $entry);
             }
         }
-        glossary_delete_attachments($glossary);
-        $DB->delete_records("glossary_entries", array("glossaryid"=>$glossary->id));
+    } else {
+        // move exported entries to main glossary
+        $sql = "UPDATE {glossary_entries}
+                   SET sourceglossaryid = 0
+                 WHERE sourceglossaryid = ?";
+        $DB->execute($sql, array($id));
     }
+
+    // Delete any dependent records
+    $entry_select = "SELECT id FROM {glossary_entries} WHERE glossaryid = ?";
+    $DB->delete_records_select('glossary_comments', "entryid IN ($entry_select)", array($id));
+    $DB->delete_records_select('glossary_alias',    "entryid IN ($entry_select)", array($id));
+    $DB->delete_records_select('glossary_ratings',  "entryid IN ($entry_select)", array($id));
+
+    $category_select = "SELECT id FROM {glossary_categories} WHERE glossaryid = ?";
+    $DB->delete_records_select('glossary_entries_categories', "categoryid IN ($category_select)", array($id));
+    $DB->delete_records('glossary_categories', array('glossaryid'=>$id));
+
+    // delete attachments
+    if ($attachments = $DB->get_records('glossary_entries', array('glossaryid'=>$id, 'attachment'=>'1'), '', 'id')) {
+        foreach ($attachments as $entryid=>$unused) {
+            $fs->delete_area_files($context->id, 'glossary_attachment', $entryid);
+        }
+    }
+
     glossary_grade_item_delete($glossary);
 
-    return $result;
+    return $DB->delete_records('glossary', array('id'=>$id));
 }
 
 function glossary_user_outline($course, $user, $mod, $glossary) {
@@ -851,7 +875,7 @@ function glossary_print_entry_icons($course, $cm, $glossary, $entry, $mode='',$h
             $mainglossary = $DB->get_record('glossary', array('mainglossary'=>1,'course'=>$course->id));
             if ( $mainglossary ) {  // if there is a main glossary defined, allow to export the current entry
                 $output = true;
-                $return .= ' <a title="'.get_string('exporttomainglossary','glossary') . '" href="exportentry.php?id='.$cm->id.'&amp;entry='.$entry->id.'&amp;mode='.$mode.'&amp;hook='.$hook.'"><img src="export.gif" class="iconsmall" alt="'.get_string('exporttomainglossary','glossary').$altsuffix.'" /></a>';
+                $return .= ' <a title="'.get_string('exporttomainglossary','glossary') . '" href="exportentry.php?id='.$entry->id.'&amp;prevmode='.$mode.'&amp;hook='.urlencode($hook).'"><img src="export.gif" class="iconsmall" alt="'.get_string('exporttomainglossary','glossary').$altsuffix.'" /></a>';
             }
         }
 
@@ -867,11 +891,11 @@ function glossary_print_entry_icons($course, $cm, $glossary, $entry, $mode='',$h
         $ineditperiod = ((time() - $entry->timecreated <  $CFG->maxeditingtime) || $glossary->editalways);
         if ( !$importedentry and (has_capability('mod/glossary:manageentries', $context) or ($entry->userid == $USER->id and ($ineditperiod and has_capability('mod/glossary:write', $context))))) {
             $output = true;
-            $return .= " <a title=\"" . get_string("delete") . "\" href=\"deleteentry.php?id=$cm->id&amp;mode=delete&amp;entry=$entry->id&amp;prevmode=$mode&amp;hook=$hook\"><img src=\"";
+            $return .= " <a title=\"" . get_string("delete") . "\" href=\"deleteentry.php?id=$cm->id&amp;mode=delete&amp;entry=$entry->id&amp;prevmode=$mode&amp;hook=".urlencode($hook)."\"><img src=\"";
             $return .= $icon;
             $return .= "\" class=\"iconsmall\" alt=\"" . get_string("delete") .$altsuffix."\" /></a> ";
 
-            $return .= " <a title=\"" . get_string("edit") . "\" href=\"edit.php?id=$cm->id&amp;e=$entry->id&amp;mode=$mode&amp;hook=$hook\"><img src=\"$CFG->pixpath/t/edit.gif\" class=\"iconsmall\" alt=\"" . get_string("edit") .$altsuffix. "\" /></a>";
+            $return .= " <a title=\"" . get_string("edit") . "\" href=\"edit.php?cmid=$cm->id&amp;id=$entry->id&amp;mode=$mode&amp;hook=".urlencode($hook)."\"><img src=\"$CFG->pixpath/t/edit.gif\" class=\"iconsmall\" alt=\"" . get_string("edit") .$altsuffix. "\" /></a>";
         } elseif ( $importedentry ) {
             $return .= " <font size=\"-1\">" . get_string("exportedentry","glossary") . "</font>";
         }
@@ -953,19 +977,15 @@ function  glossary_print_entry_lower_section($course, $cm, $glossary, $entry, $m
     return $return;
 }
 
-function glossary_print_entry_attachment($entry,$format=NULL,$align="right",$insidetable=true) {
+function glossary_print_entry_attachment($entry, $cm, $format=NULL, $align="right", $insidetable=true) {
 ///   valid format values: html  : Return the HTML link for the attachment as an icon
 ///                        text  : Return the HTML link for tha attachment as text
 ///                        blank : Print the output to the screen
-    global $DB;
-
     if ($entry->attachment) {
-          $glossary = $DB->get_record("glossary", array("id"=>$entry->glossaryid));
-          $entry->course = $glossary->course; //used inside print_attachment
           if ($insidetable) {
               echo "<table border=\"0\" width=\"100%\" align=\"$align\"><tr><td align=\"$align\" nowrap=\"nowrap\">\n";
           }
-          echo glossary_print_attachments($entry,$format,$align);
+          echo glossary_print_attachments($entry, $cm, $format, $align);
           if ($insidetable) {
               echo "</td></tr></table>\n";
           }
@@ -1085,194 +1105,129 @@ function glossary_search_entries($searchterms, $glossary, $extended) {
     return glossary_search($course,$searchterms,$extended,$glossary);
 }
 
-function glossary_file_area_name($entry) {
+/**
+ * if return=html, then return a html string.
+ * if return=text, then return a text-only string.
+ * otherwise, print HTML for non-images, and return image HTML
+ *     if attachment is an image, $align set its aligment.
+ * @param object $entry
+ * @param object $cm
+ * @param string $type html, txt, empty
+ * @param string $align left or right
+ * @return image string or nothing depending on $type param
+ */
+function glossary_print_attachments($entry, $cm, $type=NULL, $align="left") {
     global $CFG, $DB;
-//  Creates a directory file name, suitable for make_upload_directory()
 
-    // I'm doing this workaround for make it works for delete_instance also
-    //  (when called from delete_instance, glossary is already deleted so
-    //   getting the course from mdl_glossary does not work)
-    $module = $DB->get_record("modules", array("name"=>"glossary"));
-    $cm = $DB->get_record("course_modules", array("module"=>$module->id, "instance"=>$entry->glossaryid));
-    return "$cm->course/$CFG->moddata/glossary/$entry->glossaryid/$entry->id";
-}
-
-function glossary_file_area($entry) {
-    return make_upload_directory( glossary_file_area_name($entry) );
-}
-
-function glossary_main_file_area($glossary) {
-    $modarea = glossary_mod_file_area($glossary);
-    return "$modarea/$glossary->id";
-}
-
-function glossary_mod_file_area($glossary) {
-    global $CFG;
-
-    return make_upload_directory( "$glossary->course/$CFG->moddata/glossary" );
-}
-
-function glossary_delete_old_attachments($entry, $exception="") {
-// Deletes all the user files in the attachments area for a entry
-// EXCEPT for any file named $exception
-
-    if ($basedir = glossary_file_area($entry)) {
-        if ($files = get_directory_list($basedir)) {
-            foreach ($files as $file) {
-                if ($file != $exception) {
-                    unlink("$basedir/$file");
-//                    notify("Existing file '$file' has been deleted!");
-                }
-            }
-        }
-        if (!$exception) {  // Delete directory as well, if empty
-            rmdir("$basedir");
-        }
+    if (!$context = get_context_instance(CONTEXT_MODULE, $cm->id)) {
+        return '';
     }
-}
-function glossary_delete_attachments($glossary) {
-    global $DB;
-// Deletes all the user files in the attachments area for the glossary
-    if ( $entries = $DB->get_records("glossary_entries", array("glossaryid"=>$glossary->id))) {
-        $deleted = 0;
-        foreach ($entries as $entry) {
-            if ( $entry->attachment ) {
-                if ($basedir = glossary_file_area($entry)) {
-                    if ($files = get_directory_list($basedir)) {
-                        foreach ($files as $file) {
-                            unlink("$basedir/$file");
-                        }
-                    }
-                    rmdir("$basedir");
-                    $deleted++;
-                }
-            }
-        }
-        if ( $deleted ) {
-            $attachmentdir = glossary_main_file_area($glossary);
-            $glossarydir = glossary_mod_file_area($glossary);
 
-            rmdir("$attachmentdir");
-            if (!$files = get_directory_list($glossarydir) ) {
-                rmdir( "$glossarydir" );
-            }
+    if ($entry->sourceglossaryid == $cm->instance) {
+        if (!$maincm = get_coursemodule_from_instance('glossary', $entry->glossaryid)) {
+            return '';
         }
-    }
-}
+        $filecontext = get_context_instance(CONTEXT_MODULE, $maincm->id);
 
-function glossary_copy_attachments($entry, $newentry) {
-/// Given a entry object that is being copied to glossaryid,
-/// this function checks that entry
-/// for attachments, and if any are found, these are
-/// copied to the new glossary directory.
-    global $CFG, $DB;
+    } else {
+        $filecontext = $context;
+    }
 
-    $return = true;
+    $strattachment = get_string('attachment', 'glossary');
 
-    if ($entries = $DB->get_records_select("glossary_entries", "id = ? AND attachment <> ''", array($entry->id))) {
-        foreach ($entries as $curentry) {
-            $oldentry = new object();
-            $oldentry->id = $entry->id;
-            $oldentry->course = $entry->course;
-            $oldentry->glossaryid = $curentry->glossaryid;
-            $oldentrydir = "$CFG->dataroot/".glossary_file_area_name($oldentry);
-            if (is_dir($oldentrydir)) {
+    $fs = get_file_storage();
+    $browser = get_file_browser();
 
-                $newentrydir = glossary_file_area($newentry);
-                if (! copy("$oldentrydir/$newentry->attachment", "$newentrydir/$newentry->attachment")) {
-                    $return = false;
-                }
-            }
-        }
-     }
-    return $return;
-}
+    $imagereturn = '';
+    $output = '';
 
-function glossary_move_attachments($entry, $glossaryid) {
-/// Given a entry object that is being moved to glossaryid,
-/// this function checks that entry
-/// for attachments, and if any are found, these are
-/// moved to the new glossary directory.
+    if ($files = $fs->get_area_files($filecontext->id, 'glossary_attachment', $entry->id, "timemodified", false)) {
+        foreach ($files as $file) {
+            $filename = $file->get_filename();
+            $mimetype = $file->get_mimetype();
+            $icon = mimeinfo_from_type('icon', $mimetype);
+            $iconimage = '<img src="'.$CFG->pixpath.'/f/'.$icon.'" class="icon" alt="'.$icon.'" />';
+            $path = $browser->encodepath($CFG->wwwroot.'/pluginfile.php', '/'.$context->id.'/glossary_attachment/'.$entry->id.'/'.$filename);
 
-    global $CFG, $DB;
-
-    require_once($CFG->dirroot.'/lib/uploadlib.php');
+            if ($type == 'html') {
+                $output .= "<a href=\"$path\">$iconimage</a> ";
+                $output .= "<a href=\"$path\">".s($filename)."</a>";
+                $output .= "<br />";
 
-    $return = true;
+            } else if ($type == 'text') {
+                $output .= "$strattachment ".s($filename).":\n$path\n";
 
-    if ($entries = $DB->get_records_select("glossary_entries", "glossaryid = ? AND attachment <> ''", array($entry->id))) {
-        foreach ($entries as $entry) {
-            $oldentry = new object();
-            $oldentry->course = $entry->course;
-            $oldentry->glossaryid = $entry->glossaryid;
-            $oldentrydir = "$CFG->dataroot/".glossary_file_area_name($oldentry);
-            if (is_dir($oldentrydir)) {
-                $newentry = $oldentry;
-                $newentry->glossaryid = $glossaryid;
-                $newentrydir = "$CFG->dataroot/".glossary_file_area_name($newentry);
-                $files = get_directory_list($oldentrydir); // get it before we rename it.
-                if (! @rename($oldentrydir, $newentrydir)) {
-                    $return = false;
-                }
-                foreach ($files as $file) {
-                    // this is not tested as I can't find anywhere that calls this function, grepping the source.
-                    clam_change_log($oldentrydir.'/'.$file,$newentrydir.'/'.$file);
+            } else {
+                if (in_array($mimetype, array('image/gif', 'image/jpeg', 'image/png'))) {
+                    // Image attachments don't get printed as links
+                    $imagereturn .= "<br /><img src=\"$path\" alt=\"\" />";
+                } else {
+                    $output .= "<a href=\"$path\">$iconimage</a> ";
+                    $output .= filter_text("<a href=\"$path\">".s($filename)."</a>");
+                    $output .= '<br />';
                 }
             }
         }
     }
-    return $return;
+
+    if ($type) {
+        return $output;
+    } else {
+        echo $output;
+        return $imagereturn;
+    }
 }
 
-function glossary_print_attachments($entry, $return=NULL, $align="left") {
-// if return=html, then return a html string.
-// if return=text, then return a text-only string.
-// otherwise, print HTML for non-images, and return image HTML
-//     if attachment is an image, $align set its aligment.
-    global $CFG;
+/**
+ * Serves the glossary attachments. Implements needed access control ;-)
+ */
+function glossary_pluginfile($course, $cminfo, $context, $filearea, $args) {
+    global $CFG, $DB;
 
-    $newentry = $entry;
-    if ( $newentry->sourceglossaryid ) {
-        $newentry->glossaryid = $newentry->sourceglossaryid;
+    if ($filearea !== 'glossary_attachment') {
+        return false;
     }
 
-    $filearea = glossary_file_area_name($newentry);
+    if (!$cminfo->uservisible) {
+        return false;
+    }
 
-    $imagereturn = "";
-    $output = "";
+    $entryid = (int)array_shift($args);
 
-    if ($basedir = glossary_file_area($newentry)) {
-        if ($files = get_directory_list($basedir)) {
-            $strattachment = get_string("attachment", "glossary");
-            foreach ($files as $file) {
-                $icon = mimeinfo("icon", $file);
-                $ffurl = get_file_url("$filearea/$file");
-                $image = "<img src=\"$CFG->pixpath/f/$icon\" class=\"icon\" alt=\"\" />";
+    if (!$entry = $DB->get_record('glossary_entries', array('id'=>$entryid))) {
+        return false;
+    }
 
-                if ($return == "html") {
-                    $output .= "<a href=\"$ffurl\">$image</a> ";
-                    $output .= "<a href=\"$ffurl\">$file</a><br />";
+    if (!$glossary = $DB->get_record('glossary', array('id'=>$cminfo->instance))) {
+        return false;
+    }
 
-                } else if ($return == "text") {
-                    $output .= "$strattachment $file:\n$ffurl\n";
+    if ($glossary->defaultapproval and !$entry->approved and !has_capability('mod/glossary:approve', $context)) {
+        return false;
+    }
 
-                } else {
-                    if ($icon == "image.gif") {    // Image attachments don't get printed as links
-                        $imagereturn .= "<img src=\"$ffurl\" align=\"$align\" alt=\"\" />";
-                    } else {
-                        echo "<a href=\"$ffurl\">$image</a> ";
-                        echo "<a href=\"$ffurl\">$file</a><br />";
-                    }
-                }
-            }
+    if ($entry->glossaryid == $cminfo->instance) {
+        $filecontext = $context;
+
+    } else if ($entry->sourceglossaryid == $cminfo->instance) {
+        if (!$maincm = get_coursemodule_from_instance('glossary', $entry->glossaryid)) {
+            print_error('invalidcoursemodule');
         }
+        $filecontext = get_context_instance(CONTEXT_MODULE, $maincm->id);
+
+    } else {
+        return false;
     }
 
-    if ($return) {
-        return $output;
+    $fs = get_file_storage();
+    $relativepath = '/'.implode('/', $args);
+    $fullpath = $filecontext->id.$filearea.$entryid.$relativepath;
+    if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
+        return false;
     }
 
-    return $imagereturn;
+    // finally send the file
+    send_stored_file($file, 0, 0, true); // download MUST be forced - security!
 }
 
 function glossary_print_tabbed_table_end() {
@@ -2240,7 +2195,6 @@ function glossary_reset_gradebook($courseid, $type='') {
  */
 function glossary_reset_userdata($data) {
     global $CFG, $DB;
-    require_once($CFG->libdir.'/filelib.php');
 
     $componentstr = get_string('modulenameplural', 'glossary');
     $status = array();
@@ -2256,6 +2210,8 @@ function glossary_reset_userdata($data) {
 
     $params = array($data->courseid);
 
+    $fs = get_file_storage();
+
     // delete entries if requested
     if (!empty($data->reset_glossary_all)
          or (!empty($data->reset_glossary_types) and in_array('main', $data->reset_glossary_types) and in_array('secondary', $data->reset_glossary_types))) {
@@ -2264,9 +2220,14 @@ function glossary_reset_userdata($data) {
         $DB->delete_records_select('glossary_comments', "entryid IN ($allentriessql)", $params);
         $DB->delete_records_select('glossary_entries', "glossaryid IN ($allglossariessql)", $params);
 
+        // now get rid of all attachments
         if ($glossaries = $DB->get_records_sql($allglossariessql, $params)) {
             foreach ($glossaries as $glossaryid=>$unused) {
-                fulldelete($CFG->dataroot."/$data->courseid/moddata/glossary/$glossaryid");
+                if (!$cm = get_coursemodule_from_instance('glossary', $glossaryid)) {
+                    continue;
+                }
+                $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+                $fs->delete_area_files($context->id, 'glossary_attachment');
             }
         }
 
@@ -2291,7 +2252,11 @@ function glossary_reset_userdata($data) {
 
             if ($glossaries = $DB->get_records_sql($mainglossariessql, $params)) {
                 foreach ($glossaries as $glossaryid=>$unused) {
-                    fulldelete("$CFG->dataroot/$data->courseid/moddata/glossary/$glossaryid");
+                    if (!$cm = get_coursemodule_from_instance('glossary', $glossaryid)) {
+                        continue;
+                    }
+                    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+                    $fs->delete_area_files($context->id, 'glossary_attachment');
                 }
             }
 
@@ -2313,7 +2278,11 @@ function glossary_reset_userdata($data) {
 
             if ($glossaries = $DB->get_records_sql($secondaryglossariessql, $params)) {
                 foreach ($glossaries as $glossaryid=>$unused) {
-                    fulldelete("$CFG->dataroot/$data->courseid/moddata/glossary/$glossaryid");
+                    if (!$cm = get_coursemodule_from_instance('glossary', $glossaryid)) {
+                        continue;
+                    }
+                    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+                    $fs->delete_area_files($context->id, 'glossary_attachment');
                 }
             }
 
@@ -2343,8 +2312,11 @@ function glossary_reset_userdata($data) {
                     $DB->delete_records('glossary_ratings', array('entryid'=>$entry->id));
                     $DB->delete_records('glossary_comments', array('entryid'=>$entry->id));
                     $DB->delete_records('glossary_entries', array('id'=>$entry->id));
-                    fulldelete("$CFG->dataroot/$data->courseid/moddata/glossary/$entry->glossaryid");
-                    $notenrolled[$entry->userid] = true;
+
+                    if ($cm = get_coursemodule_from_instance('glossary', $entry->glossaryid)) {
+                        $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+                        $fs->delete_area_files($context->id, 'glossary_attachment', $entry->id);
+                    }
                 }
             }
             $rs->close();
index 6f62395d488cfde0f77e2c5d9528d6164823b114..61f17050716a4abf8f158d5b160cce4e448296e9 100644 (file)
@@ -5,8 +5,8 @@
 ///  This fragment is called by moodle_needs_upgrading() and /admin/index.php
 /////////////////////////////////////////////////////////////////////////////////
 
-$module->version  = 2007101509;
-$module->requires = 2007101509;  // Requires this Moodle version
+$module->version  = 2008081700;
+$module->requires = 2008081600;  // Requires this Moodle version
 $module->cron     = 0;           // Period for cron to check this module (secs)
 
 ?>
index 0641a3c8f6230000c8ba79324216d4cc69a11875..36075d03e4c76e5f6d075b00753d6a1fce5f2a69 100644 (file)
@@ -29,6 +29,7 @@
         if (! $glossary = $DB->get_record("glossary", array("id"=>$cm->instance))) {
             print_error('invalidid', 'glossary');
         }
+
     } else if (!empty($g)) {
         if (! $glossary = $DB->get_record("glossary", array("id"=>$g))) {
             print_error('invalidid', 'glossary');
@@ -52,7 +53,7 @@
 
 /// redirecting if adding a new entry
     if ($tab == GLOSSARY_ADDENTRY_VIEW ) {
-        redirect("edit.php?id=$cm->id&amp;mode=$mode");
+        redirect("edit.php?cmid=$cm->id&amp;mode=$mode");
     }
 
 /// setting the defaut number of entries per page if not set
     /// End glossary controls
 //        print_box_end(); /// glossarycontrol
         echo '</div>';
-        
+
 //        print_box('&nbsp;', 'clearer');
     }
 
         echo '<div class="singlebutton glossaryaddentry">';
         echo "<form id=\"newentryform\" method=\"get\" action=\"$CFG->wwwroot/mod/glossary/edit.php\">";
         echo '<div>';
-        echo "<input type=\"hidden\" name=\"id\" value=\"$cm->id\" />";
-        echo '<input type="submit" value="';
-        print_string('addentry', 'glossary');
-        echo '" />';
+        echo "<input type=\"hidden\" name=\"cmid\" value=\"$cm->id\" />";
+        echo '<input type="submit" value="'.get_string('addentry', 'glossary').'" />';
         echo '</div>';
         echo '</form>';
         echo "</div>\n";
 
     echo '<br />';
 
-    include("tabs.php");
+    require("tabs.php");
 
-    include_once("sql.php");
+    require("sql.php");
 
 /// printing the entries
     $entriesshown = 0;
         }
 
         //Build paging bar
-        $paging = glossary_get_paging_bar($count, $page, $entriesbypage, "view.php?id=$id&amp;mode=$mode&amp;hook=$hook&amp;sortkey=$sortkey&amp;sortorder=$sortorder&amp;fullsearch=$fullsearch&amp;",9999,10,'&nbsp;&nbsp;', $specialtext, -1);
+        $paging = glossary_get_paging_bar($count, $page, $entriesbypage, "view.php?id=$id&amp;mode=$mode&amp;hook=".urlencode($hook)."&amp;sortkey=$sortkey&amp;sortorder=$sortorder&amp;fullsearch=$fullsearch&amp;",9999,10,'&nbsp;&nbsp;', $specialtext, -1);
 
         echo '<div class="paging">';
         echo $paging;