Merge branch 'MDL-18375_master' of git://github.com/markn86/moodle
authorDamyon Wiese <damyon@moodle.com>
Mon, 9 Sep 2013 02:41:12 +0000 (10:41 +0800)
committerDamyon Wiese <damyon@moodle.com>
Mon, 9 Sep 2013 02:41:12 +0000 (10:41 +0800)
48 files changed:
admin/index.php
blocks/rss_client/viewfeed.php
blog/edit.php
blog/renderer.php
course/edit.php
course/edit_form.php
course/editcategory.php
course/externallib.php
course/lib.php
course/modedit.php
course/moodleform_mod.php
course/tests/courselib_test.php
grade/edit/outcome/edit.php
grade/edit/scale/edit.php
group/group.php
install/lang/bs/admin.php [new file with mode: 0644]
install/lang/bs/error.php [new file with mode: 0644]
install/lang/bs/install.php
install/lang/bs/moodle.php [new file with mode: 0644]
install/lang/ckb/langconfig.php
install/lang/cy/error.php
install/lang/cy/install.php
install/lang/en/install.php
install/lang/es_mx/install.php
install/lang/hi/admin.php
install/lang/ja/install.php
install/lang/nl/error.php
install/lang/no/error.php
lib/classes/component.php
lib/filelib.php
lib/filestorage/file_packer.php
lib/filestorage/file_progress.php [new file with mode: 0644]
lib/filestorage/stored_file.php
lib/filestorage/tests/zip_packer_test.php
lib/filestorage/zip_archive.php
lib/filestorage/zip_packer.php
lib/form/editor.php
lib/simplepie/moodle_simplepie.php
lib/upgrade.txt
mod/book/view.php
mod/forum/classes/post_form.php
mod/forum/lib.php
mod/forum/post.php
mod/glossary/edit.php
mod/survey/lang/en/survey.php
mod/survey/lib.php
tag/edit.php
version.php

index 466832c..1f186b6 100644 (file)
@@ -66,6 +66,16 @@ if (empty($_GET['cache']) and empty($_POST['cache']) and empty($_GET['sesskey'])
 }
 
 require('../config.php');
+
+// Invalidate the cache of version.php in any circumstances to help core_component
+// detecting if the version has changed and component cache should be reset.
+if (function_exists('opcache_invalidate')) {
+    opcache_invalidate($CFG->dirroot . '/version.php', true);
+}
+// Make sure the component cache gets rebuilt if necessary, any method that
+// indirectly calls the protected init() method is good here.
+core_component::get_core_subsystems();
+
 require_once($CFG->libdir.'/adminlib.php');    // various admin-only functions
 require_once($CFG->libdir.'/upgradelib.php');  // general upgrade/install related functions
 require_once($CFG->libdir.'/pluginlib.php');   // available updates notifications
index 1c287d7..26451d6 100644 (file)
@@ -84,15 +84,16 @@ if (!empty($rssrecord->preferredtitle)) {
     $feedtitle =  $rss->get_title();
 }
 echo '<table align="center" width="50%" cellspacing="1">'."\n";
-echo '<tr><td colspan="2"><strong>'. $feedtitle .'</strong></td></tr>'."\n";
+echo '<tr><td colspan="2"><strong>'. s($feedtitle) .'</strong></td></tr>'."\n";
 foreach ($rss->get_items() as $item) {
     echo '<tr><td valign="middle">'."\n";
-    echo '<a href="'. $item->get_link() .'" target="_blank"><strong>'. $item->get_title();
+    echo '<a href="'.$item->get_link().'" target="_blank"><strong>';
+    echo s($item->get_title());
     echo '</strong></a>'."\n";
     echo '</td>'."\n";
     echo '</tr>'."\n";
     echo '<tr><td colspan="2"><small>';
-    echo $item->get_description() .'</small></td></tr>'."\n";
+    echo format_text($item->get_description(), FORMAT_HTML) .'</small></td></tr>'."\n";
 }
 echo '</table>'."\n";
 
index 2c36763..5c06993 100644 (file)
@@ -162,7 +162,8 @@ if (!empty($entry->id)) {
 }
 
 require_once('edit_form.php');
-$summaryoptions = array('subdirs'=>false, 'maxfiles'=> 99, 'maxbytes'=>$CFG->maxbytes, 'trusttext'=>true, 'context'=>$sitecontext);
+$summaryoptions = array('maxfiles'=> 99, 'maxbytes'=>$CFG->maxbytes, 'trusttext'=>true, 'context'=>$sitecontext,
+    'subdirs'=>file_area_contains_subdirs($sitecontext, 'blog', 'post', $entry->id));
 $attachmentoptions = array('subdirs'=>false, 'maxfiles'=> 99, 'maxbytes'=>$CFG->maxbytes);
 
 $blogeditform = new blog_edit_form(null, compact('entry', 'summaryoptions', 'attachmentoptions', 'sitecontext', 'courseid', 'modid'));
index b605016..af1724d 100644 (file)
@@ -119,11 +119,14 @@ class core_blog_renderer extends plugin_renderer_base {
         // Body.
         $o .= format_text($entry->summary, $entry->summaryformat, array('overflowdiv' => true));
 
-        // Uniquehash is used as a link to an external blog.
         if (!empty($entry->uniquehash)) {
-            $o .= $this->output->container_start('externalblog');
-            $o .= html_writer::link($entry->uniquehash, get_string('linktooriginalentry', 'blog'));
-            $o .= $this->output->container_end();
+            // Uniquehash is used as a link to an external blog.
+            $url = clean_param($entry->uniquehash, PARAM_URL);
+            if (!empty($url)) {
+                $o .= $this->output->container_start('externalblog');
+                $o .= html_writer::link($url, get_string('linktooriginalentry', 'blog'));
+                $o .= $this->output->container_end();
+            }
         }
 
         // Links to tags.
index c549cc1..1021c23 100644 (file)
@@ -70,6 +70,7 @@ $overviewfilesoptions = course_overviewfiles_options($course);
 if (!empty($course)) {
     //add context for editor
     $editoroptions['context'] = $coursecontext;
+    $editoroptions['subdirs'] = file_area_contains_subdirs($coursecontext, 'course', 'summary', 0);
     $course = file_prepare_standard_editor($course, 'summary', $editoroptions, $coursecontext, 'course', 'summary', 0);
     if ($overviewfilesoptions) {
         file_prepare_standard_filemanager($course, 'overviewfiles', $overviewfilesoptions, $coursecontext, 'course', 'overviewfiles', 0);
@@ -84,6 +85,7 @@ if (!empty($course)) {
 } else {
     //editor should respect category context if course context is not set.
     $editoroptions['context'] = $catcontext;
+    $editoroptions['subdirs'] = 0;
     $course = file_prepare_standard_editor($course, 'summary', $editoroptions, null, 'course', 'summary', null);
     if ($overviewfilesoptions) {
         file_prepare_standard_filemanager($course, 'overviewfiles', $overviewfilesoptions, null, 'course', 'overviewfiles', 0);
index fff5e6a..2dcbce2 100644 (file)
@@ -346,19 +346,23 @@ class course_edit_form extends moodleform {
      * @return array the errors that were found
      */
     function validation($data, $files) {
-        global $DB, $CFG;
+        global $DB;
 
         $errors = parent::validation($data, $files);
-        if ($foundcourses = $DB->get_records('course', array('shortname'=>$data['shortname']))) {
-            if (!empty($data['id'])) {
-                unset($foundcourses[$data['id']]);
+
+        // Add field validation check for duplicate shortname.
+        if ($course = $DB->get_record('course', array('shortname' => $data['shortname']), '*', IGNORE_MULTIPLE)) {
+            if (empty($data['id']) || $course->id != $data['id']) {
+                $errors['shortname'] = get_string('shortnametaken', '', $course->fullname);
             }
-            if (!empty($foundcourses)) {
-                foreach ($foundcourses as $foundcourse) {
-                    $foundcoursenames[] = $foundcourse->fullname;
+        }
+
+        // Add field validation check for duplicate idnumber.
+        if (!empty($data['idnumber']) && (empty($data['id']) || $this->course->idnumber != $data['idnumber'])) {
+            if ($course = $DB->get_record('course', array('idnumber' => $data['idnumber']), '*', IGNORE_MULTIPLE)) {
+                if (empty($data['id']) || $course->id != $data['id']) {
+                    $errors['idnumber'] = get_string('courseidnumbertaken', 'error', $course->fullname);
                 }
-                $foundcoursenamestring = implode(',', $foundcoursenames);
-                $errors['shortname']= get_string('shortnametaken', '', $foundcoursenamestring);
             }
         }
 
index a2de1f1..05a5777 100644 (file)
@@ -77,7 +77,8 @@ $editoroptions = array(
     'maxfiles'  => EDITOR_UNLIMITED_FILES,
     'maxbytes'  => $CFG->maxbytes,
     'trusttext' => true,
-    'context'   => $editorcontext
+    'context'   => $editorcontext,
+    'subdirs'   => file_area_contains_subdirs($editorcontext, 'coursecat', 'description', $itemid),
 );
 $category = file_prepare_standard_editor($category, 'description', $editoroptions, $editorcontext, 'coursecat', 'description', $itemid);
 
index 26742db..2d61c28 100644 (file)
@@ -717,20 +717,14 @@ class core_course_external extends external_api {
                     require_capability('moodle/course:changefullname', $context);
                 }
 
-                // Check if the shortname already exist and user have capability.
+                // Check if the user can change shortname.
                 if (array_key_exists('shortname', $course) && ($oldcourse->shortname != $course['shortname'])) {
                     require_capability('moodle/course:changeshortname', $context);
-                    if ($DB->record_exists('course', array('shortname' => $course['shortname']))) {
-                        throw new moodle_exception('shortnametaken', '', '', $course['shortname']);
-                    }
                 }
 
-                // Check if the id number already exist and user have capability.
+                // Check if the user can change the idnumber.
                 if (array_key_exists('idnumber', $course) && ($oldcourse->idnumber != $course['idnumber'])) {
                     require_capability('moodle/course:changeidnumber', $context);
-                    if ($DB->record_exists('course', array('idnumber' => $course['idnumber']))) {
-                        throw new moodle_exception('courseidnumbertaken', '', '', $course['idnumber']);
-                    }
                 }
 
                 // Check if user can change summary.
index 5cfa240..af7854c 100644 (file)
@@ -2368,6 +2368,20 @@ function update_course($data, $editoroptions = NULL) {
         $data = file_postupdate_standard_filemanager($data, 'overviewfiles', $overviewfilesoptions, $context, 'course', 'overviewfiles', 0);
     }
 
+    // Check we don't have a duplicate shortname.
+    if (!empty($data->shortname) && $oldcourse->shortname != $data->shortname) {
+        if ($DB->record_exists('course', array('shortname' => $data->shortname))) {
+            throw new moodle_exception('shortnametaken', '', '', $data->shortname);
+        }
+    }
+
+    // Check we don't have a duplicate idnumber.
+    if (!empty($data->idnumber) && $oldcourse->idnumber != $data->idnumber) {
+        if ($DB->record_exists('course', array('idnumber' => $data->idnumber))) {
+            throw new moodle_exception('courseidnumbertaken', '', '', $data->idnumber);
+        }
+    }
+
     if (!isset($data->category) or empty($data->category)) {
         // prevent nulls and 0 in category field
         unset($data->category);
index 8cfe0a0..db70a9f 100644 (file)
@@ -78,7 +78,7 @@ if (!empty($add)) {
 
     if (plugin_supports('mod', $data->modulename, FEATURE_MOD_INTRO, true)) {
         $draftid_editor = file_get_submitted_draft_itemid('introeditor');
-        file_prepare_draft_area($draftid_editor, null, null, null, null);
+        file_prepare_draft_area($draftid_editor, null, null, null, null, array('subdirs'=>true));
         $data->introeditor = array('text'=>'', 'format'=>FORMAT_HTML, 'itemid'=>$draftid_editor); // TODO: add better default
     }
 
index 97724aa..8a7aa14 100644 (file)
@@ -821,7 +821,7 @@ abstract class moodleform_mod extends moodleform {
         $label = is_null($customlabel) ? get_string('moduleintro') : $customlabel;
 
         $mform->addElement('editor', 'introeditor', $label, array('rows' => 10), array('maxfiles' => EDITOR_UNLIMITED_FILES,
-            'noclean' => true, 'context' => $this->context));
+            'noclean' => true, 'context' => $this->context, 'subdirs' => true));
         $mform->setType('introeditor', PARAM_RAW); // no XSS prevention here, users must be trusted
         if ($required) {
             $mform->addRule('introeditor', get_string('required'), 'required', null, 'client');
index 4c42b9f..85bcac3 100644 (file)
@@ -656,6 +656,53 @@ class core_course_courselib_testcase extends advanced_testcase {
         $this->assertEquals(range(0, $course->numsections + 1), $sectionscreated);
     }
 
+    public function test_update_course() {
+        global $DB;
+
+        $this->resetAfterTest();
+
+        $defaultcategory = $DB->get_field_select('course_categories', 'MIN(id)', 'parent = 0');
+
+        $course = new stdClass();
+        $course->fullname = 'Apu loves Unit Təsts';
+        $course->shortname = 'test1';
+        $course->idnumber = '1';
+        $course->summary = 'Awesome!';
+        $course->summaryformat = FORMAT_PLAIN;
+        $course->format = 'topics';
+        $course->newsitems = 0;
+        $course->numsections = 5;
+        $course->category = $defaultcategory;
+
+        $created = create_course($course);
+        // Ensure the checks only work on idnumber/shortname that are not already ours.
+        update_course($created);
+
+        $course->shortname = 'test2';
+        $course->idnumber = '2';
+
+        $created2 = create_course($course);
+
+        // Test duplicate idnumber.
+        $created2->idnumber = '1';
+        try {
+            update_course($created2);
+            $this->fail('Expected exception when trying to update a course with duplicate idnumber');
+        } catch (moodle_exception $e) {
+            $this->assertEquals(get_string('courseidnumbertaken', 'error', $created2->idnumber), $e->getMessage());
+        }
+
+        // Test duplicate shortname.
+        $created2->idnumber = '2';
+        $created2->shortname = 'test1';
+        try {
+            update_course($created2);
+            $this->fail('Expected exception when trying to update a course with a duplicate shortname');
+        } catch (moodle_exception $e) {
+            $this->assertEquals(get_string('shortnametaken', 'error', $created2->shortname), $e->getMessage());
+        }
+    }
+
     public function test_course_add_cm_to_section() {
         global $DB;
         $this->resetAfterTest(true);
index 2d2c670..48164e2 100644 (file)
@@ -111,8 +111,10 @@ $editoroptions = array(
 );
 
 if (!empty($outcome_rec->id)) {
+    $editoroptions['subdirs'] = file_area_contains_subdirs($systemcontext, 'grade', 'outcome', $outcome_rec->id);
     $outcome_rec = file_prepare_standard_editor($outcome_rec, 'description', $editoroptions, $systemcontext, 'grade', 'outcome', $outcome_rec->id);
 } else {
+    $editoroptions['subdirs'] = false;
     $outcome_rec = file_prepare_standard_editor($outcome_rec, 'description', $editoroptions, $systemcontext, 'grade', 'outcome', null);
 }
 
index 9374a9f..04373b1 100644 (file)
@@ -104,8 +104,10 @@ $editoroptions = array(
 );
 
 if (!empty($scale_rec->id)) {
+    $editoroptions['subdirs'] = file_area_contains_subdirs($systemcontext, 'grade', 'scale', $scale_rec->id);
     $scale_rec = file_prepare_standard_editor($scale_rec, 'description', $editoroptions, $systemcontext, 'grade', 'scale', $scale_rec->id);
 } else {
+    $editoroptions['subdirs'] = false;
     $scale_rec = file_prepare_standard_editor($scale_rec, 'description', $editoroptions, $systemcontext, 'grade', 'scale', null);
 }
 $mform = new edit_scale_form(null, compact('gpr', 'editoroptions'));
index 4e0d8b0..b6aa753 100644 (file)
@@ -79,8 +79,10 @@ $returnurl = $CFG->wwwroot.'/group/index.php?id='.$course->id.'&group='.$id;
 // Prepare the description editor: We do support files for group descriptions
 $editoroptions = array('maxfiles'=>EDITOR_UNLIMITED_FILES, 'maxbytes'=>$course->maxbytes, 'trust'=>false, 'context'=>$context, 'noclean'=>true);
 if (!empty($group->id)) {
+    $editoroptions['subdirs'] = file_area_contains_subdirs($context, 'group', 'description', $group->id);
     $group = file_prepare_standard_editor($group, 'description', $editoroptions, $context, 'group', 'description', $group->id);
 } else {
+    $editoroptions['subdirs'] = false;
     $group = file_prepare_standard_editor($group, 'description', $editoroptions, $context, 'group', 'description', null);
 }
 
diff --git a/install/lang/bs/admin.php b/install/lang/bs/admin.php
new file mode 100644 (file)
index 0000000..af7796d
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Automatically generated strings for Moodle installer
+ *
+ * Do not edit this file manually! It contains just a subset of strings
+ * needed during the very first steps of installation. This file was
+ * generated automatically by export-installer.php (which is part of AMOS
+ * {@link http://docs.moodle.org/dev/Languages/AMOS}) using the
+ * list of strings defined in /install/stringnames.txt.
+ *
+ * @package   installer
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+$string['clianswerno'] = 'n';
+$string['cliansweryes'] = 'y';
+$string['cliincorrectvalueerror'] = 'Greška, neispravna vrijednost "{$a->value}" za "{$a->option}"';
+$string['cliincorrectvalueretry'] = 'Neispravna vrijednost, molim pokušajte ponovo';
+$string['clitypevalue'] = 'otkucaj vrijednost';
+$string['clitypevaluedefault'] = 'otkucaj vrijednost, pritisni "Enter" da biste upotrebili zadanu vrijednost ({$a})';
+$string['cliunknowoption'] = 'Neprepoznate opcije:
+{$a}
+Molimo iskoristite opciju za pomoć.';
+$string['cliyesnoprompt'] = 'otkucaj y (znači DA) ili n (znači NE)';
+$string['environmentrequireinstall'] = 'mora biti instaliran i omogućen';
+$string['environmentrequireversion'] = 'neophodna verzija je {$a->needed} a Vi trenutno koristite verziju {$a->current}';
diff --git a/install/lang/bs/error.php b/install/lang/bs/error.php
new file mode 100644 (file)
index 0000000..b7db900
--- /dev/null
@@ -0,0 +1,48 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Automatically generated strings for Moodle installer
+ *
+ * Do not edit this file manually! It contains just a subset of strings
+ * needed during the very first steps of installation. This file was
+ * generated automatically by export-installer.php (which is part of AMOS
+ * {@link http://docs.moodle.org/dev/Languages/AMOS}) using the
+ * list of strings defined in /install/stringnames.txt.
+ *
+ * @package   installer
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+$string['cannotcreatelangdir'] = 'Nije moguće kreirati direktorij jezika';
+$string['cannotcreatetempdir'] = 'Nije moguće kreirati privremeni direktorij';
+$string['cannotdownloadcomponents'] = 'Nije moguće preuzeti komponente.';
+$string['cannotdownloadzipfile'] = 'Nije moguće preuzeti arhivu';
+$string['cannotfindcomponent'] = 'Nije moguće pronaći komponentu.';
+$string['cannotsavemd5file'] = 'Nije moguće sačuvati md5 datoteku.';
+$string['cannotsavezipfile'] = 'Nije moguće sačuvati ZIP arhivu.';
+$string['cannotunzipfile'] = 'Nije moguće raspakovati ZIP datoteku.';
+$string['componentisuptodate'] = 'Komponenta je dostupna u svojoj najnovijoj verziji';
+$string['downloadedfilecheckfailed'] = 'Nije uspjela provjera preuzete datoteke';
+$string['invalidmd5'] = 'Neispravna md5 datoteka';
+$string['missingrequiredfield'] = 'Nedostaje neko obavezno polje';
+$string['remotedownloaderror'] = 'Preuzimanje komponente na Vaš server nije uspjelo. Provjerite podešavanja proksi servera. PHP cURL ekstenzija se preporučuje.<br /><br />Morate da preuzmete <a href="{$a->url}">{$a->url}</a> datoteku ručno, kopirate je u direktorij "{$a->dest}" na svom sereveru i tamo je raspakovati.';
+$string['wrongdestpath'] = 'Pogrešna odredišna putanja';
+$string['wrongsourcebase'] = 'Pogrešna baza izvornog URL-a';
+$string['wrongzipfilename'] = 'Pogrešan naziv arhive';
index 9ea56b6..23fc129 100644 (file)
 defined('MOODLE_INTERNAL') || die();
 
 $string['admindirname'] = 'Administratorski direktorij';
+$string['availablelangs'] = 'Popis dostupnih jezika';
+$string['chooselanguagehead'] = 'Izaberite jezik';
+$string['chooselanguagesub'] = 'Molimo izaberite jezik koji će se koristiti tokom instalacije. Ovaj jezik će, također, biti korišten na nivou stranice kao zadani, mada to naknadno može biti promijenjeno.';
+$string['clialreadyconfigured'] = 'Datoteka config.php već postoji. Molimo, koristite admin/cli/install_database.php ako želite da instalirate ovu stranicu.';
+$string['clialreadyinstalled'] = 'Datoteka config.php već postoji. Upotrebite komandu admin/cli/upgrade.php ako želite da nadogradite ovu stranicu.';
+$string['cliinstallheader'] = 'Moodle {$a} program za instaliranje iz komandne linije';
+$string['databasehost'] = 'Server baze podataka';
+$string['databasename'] = 'Ime baze podataka';
+$string['databasetypehead'] = 'Izaberite driver baze podataka';
 $string['dataroot'] = 'Direktorij podataka';
+$string['datarootpermission'] = 'Ovlaštenja nad direktorijom podataka';
 $string['dbprefix'] = 'Lista prefiksa';
-$string['dirroot'] = 'Direktorij Moodla';
+$string['dirroot'] = 'Moodle direktorij';
+$string['environmenthead'] = 'Provjeravanje Vašeg okruženja...';
+$string['environmentsub2'] = 'Svaka verzija Moodlea ima minimum zahtjeva po pitanju odgovarajuće PHP verzije i nekoliko obaveznih PHP ekstenzija. Puna provjera okruženja se vrši prije svakog instaliranja ili ažuriranja postojeće verzije. Ukoliko ne znate kako da instalirate novu verziju ili omogućite PHP ekstenzije kontaktirajte Vašeg server administratora.';
+$string['errorsinenvironment'] = 'Provjera okruženja nije prošla!';
 $string['installation'] = 'Instalacija';
-$string['memorylimithelp'] = '<p>PHP ograničenje memorije za Vaš server je trenutno podešeno na {$a}.</p>
-
-<p>Ovo možda prouzrokuje Moodlu da kasnije ima problema sa memorijom, posebno ako imate mnogo dozvoljenih modula i /ili mnogo korisnika.</p>
-
-<p>Preporučujemo Vam da konfigurišete PHP sa  visokim ograničenjem ako je moguće, kao 40M. Čineći ovo tamo je nekoliko načina pa možete pokušati: </p><ol>
-<li>Ako ste, opet kompajlisati PHP sa <i>--dostupnim-memorijskim-ograničenjem</i>. Ovo će dozvoliti Moodle da postavi memorijsko ograničenje sam za sebe.</li>
-<li>Ako imate pristup na Vašu php.ini datoteku, možete promijeniti <b>memorijsko_ograničenje</b> podešavanje u nešto kao ovo 40M. Ako nemate pristup možete pitati svog administratora da to uradi za Vas.</li>
-<li>Na nekim PHP serverima možete kreirati  a.ht pristupnu datoteku u Moodle direktoriju koji se sadrži na ovoj liniji:<br /><blockquote>php_vrijednost memorijskog_ograničenja 40M</blockquote></li>
-<br />Kakogod, na istom serveru ovo izbjegavajte <b>sve</b> PHP stranice za rad (vidjet ćete grešku prilkom pregleda stranice) ćete na njima morati izbrisati .htpristupnu datoteku. </li></ol>';
+$string['langdownloaderror'] = 'Nažalost, jezik "{$a}" se ne može preuzeti. Proces instaliranja biće nastavljen na engleskom jeziku.';
+$string['memorylimithelp'] = '<p>PHP ograničenje memorije za Vaš server je trenutno podešeno na {$a}.</p> <p>Ovo podešavanje može kasnije da prouzrokuje da Moodle ima problema sa memorijom, posebno ako imate mnogo aktiviranih modula i/ili mnogo korisnika.</p> <p>Preporučujemo da konfigurišete PHP sa višim ograničenjem ako je moguće, recimo 40M. Postoji nekoliko načina na koje to može da se to uradi:</p><ol> <li>Ako možete, rekompajlirajte PHP sa <i>--enable-memory-limit</i>. Ovo će omogućiti Moodle sistemu da sam postavi memorijsko ograničenje.</li> <li>Ako imate pristup svojoj php.ini datoteci, možete promijeniti vrijednost za <b>memory_limit</b> na, recimo, 40M. Ako nemate pristup toj datoteci možete pitati svog administratora da to uradi umjesto Vas.</li> <li>Na nekim PHP serverima možete da kreirate .htaccess datoteku u Moodle direktoriju koja sadrži red: <blockquote><div>php_value memory_limit 40M</div></blockquote> <p>Međutim, na nekim serverima to će spriječiti prikazivanje <b>svih</b> PHP stranica (vidjećete poruku o grešci kada budete gledali stranice), pa ćete sa tih servera morati da uklonite .htaccess datoteku.</p></li> </ol>';
+$string['paths'] = 'Putanje';
+$string['pathserrcreatedataroot'] = 'Instalaciona procedura ne može da kreira direktorij baze podataka ({$a->dataroot}).';
+$string['pathshead'] = 'Potvrdi putanje';
+$string['pathsrodataroot'] = 'U direktorij za podatke nije moguć upis';
+$string['pathsroparentdataroot'] = 'Nije moguć upis u nadređeni direktorij ({$a->parent}). Instalacioni program ne može da kreira direktorij za podatke ({$a->dataroot}).';
+$string['pathssubadmindir'] = 'Vrlo mali broj web servera koristi /admin kao specijalni URL za pristup raznim podešavanjima (kontrolni panel i sl.). Nažalost, to dovodi do konflikta sa standardnom lokacijom za administratorske stranice u Moodleu. Ovaj problem možete riješiti tako što ćete promijeniti ime administratorskog direktoriju u Vašoj instalaciji, i ovdje upisati to novo ime. Na primjer <em>moodleadmin</em>. Ovo podešavanje će prepraviti administratorske linkove u Moodle sistemu.';
+$string['pathssubdataroot'] = 'Potreban Vam je prostor gdje će Moodle čuvati postavljene datoteke. Ovaj direktorij treba da bude podešen tako da se može čitati i u njega upisivati od strane korisnika web servera (obično \'nobody\' ili \'apache\'), ali istovremeno mora biti dostupan direktno preko weba. Ukoliko ovaj direktorij ne postoji Moodle će pokušati da ga kreira tokom instalacije.';
+$string['pathssubdirroot'] = 'Puna putanja do direktotija za instaliranje Moodlea.';
+$string['pathssubwwwroot'] = 'Puna web adresa putem koje će se pristupati Moodleu. Nije moguće pristupati Moodleu koristeći više adresa. Ako Vaša stranica ima više javnih adresa onda na svima morate da podesite permanentne redirekcije osim na ovoj. Ako je Vaša stranica dostupna sa interneta ali i iz intranet okruženja ovdje upotrijebite javnu adresu i podesite DNS tako da i intranet korisnici mogu da koriste javnu adresu. Ako je adresa netačna promijenite URL u svom web čitaču da biste ponovo pokrenuli instalaciju sa drugačijom vrijednošću.';
+$string['pathsunsecuredataroot'] = 'Dataroot lokacija nije bezbjedna';
+$string['pathswrongadmindir'] = 'Admin direktorij ne postoji';
+$string['phpextension'] = '{$a} PHP ekstenѕija';
 $string['phpversion'] = 'PHP verzija';
-$string['phpversionhelp'] = '<p>Moodle zahtijeva najmanju PHP verziju 4.1.0.</p>
-<p>Trenutno pokrećete verziju {$a}</p>
-<p>Možete nadograditi PHP ili premjestiti na glavnu sa novijom verzijom PHP!</p>';
+$string['phpversionhelp'] = '<p>Moodle zahtijeva najmanje PHP verziju 4.3.0 ili 5.1.0 (5.0.x ima brojne uočene probleme).</p> <p>Trenutno koristite verziju {$a}</p> <p>Morate nadograditi PHP ili premjestiti Moodle na web server sa novijom verzijom PHP-a!</br> (U slučaju verzije 5.0.x možete, također, da se vratite na 4.4.x verziju)</p>';
+$string['welcomep10'] = '{$a->installername} ({$a->installerversion})';
+$string['welcomep20'] = 'Ovu stranicu vidite zato što ste uspješno instalirali i pokrenuli <strong>{$a->packname} {$a->packversion}</strong> paket na svom serveru. Čestitamo!';
+$string['welcomep30'] = 'Ovo izdanje <strong>{$a->installername}</strong> uključuje aplikacije za kreiranje okruženja u kojem će <strong>Moodle</strong> uspješno funkcionisati, konkretno:';
+$string['welcomep40'] = 'Ovaj paket obuhvata i <strong>Moodle {$a->moodlerelease} ({$a->moodleversion})</strong>.';
+$string['welcomep50'] = 'Korištenje svih aplikacija ovog paketa je uređeno njihovim licencama. Kompletan<strong>{$a->installername}</strong> paket je <a href="http://www.opensource.org/docs/definition_plain.html">otvorenog koda</a> i distribuira se pod <a href="http://www.gnu.org/copyleft/gpl.html">GPL</a> licencom.';
+$string['welcomep60'] = 'Naredne stranice će vas provesti kroz nekoliko jednostavnih koraka tokom kojih ćete konfigurisati i podesiti <strong>Moodle</strong> na svom računaru. Možete prihvatiti zadano podešavanja ili ih, opciono, prilagoditi vlastitim potrebama.';
+$string['welcomep70'] = 'Kliknite na dugme za nastavak da biste dalje podešavali <strong>Moodle</strong>.';
 $string['wwwroot'] = 'Web adresa';
diff --git a/install/lang/bs/moodle.php b/install/lang/bs/moodle.php
new file mode 100644 (file)
index 0000000..d503e4a
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Automatically generated strings for Moodle installer
+ *
+ * Do not edit this file manually! It contains just a subset of strings
+ * needed during the very first steps of installation. This file was
+ * generated automatically by export-installer.php (which is part of AMOS
+ * {@link http://docs.moodle.org/dev/Languages/AMOS}) using the
+ * list of strings defined in /install/stringnames.txt.
+ *
+ * @package   installer
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+$string['language'] = 'Jezik';
+$string['next'] = 'Sljedeći';
+$string['previous'] = 'Prethodni';
+$string['reload'] = 'Učitaj ponovo';
index 759ffd9..042b17c 100644 (file)
@@ -30,4 +30,5 @@
 
 defined('MOODLE_INTERNAL') || die();
 
+$string['thisdirection'] = 'rtl';
 $string['thislanguage'] = 'سۆرانی';
index b97501c..20afcce 100644 (file)
@@ -30,6 +30,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
+$string['cannotcreatedboninstall'] = '<p>Methu creu y gronfa ddata.</p> <p>Dydy’r gronfa ddata benodedig ddim yn bodoli a does gan y defnyddiwr dan sylw ddim hawl i greu cronfa ddata.</p> <p>Dylai gweinyddwr y safle wirio ffurfweddu cronfeydd data.</p>';
 $string['cannotcreatelangdir'] = 'Does dim modd creu cyfeiriadur iaith';
 $string['cannotcreatetempdir'] = 'Does dim modd creu cyfeiriadur dros dro';
 $string['cannotdownloadcomponents'] = 'Does dim modd llwytho cydrannau i lawr';
@@ -39,10 +40,11 @@ $string['cannotsavemd5file'] = 'Does dim modd cadw ffeil md5';
 $string['cannotsavezipfile'] = 'Does dim modd cadw ffeil ZIP';
 $string['cannotunzipfile'] = 'Does dim modd dadzipio\'r ffeil';
 $string['componentisuptodate'] = 'Mae\'r gydran wedi\'i diweddaru';
+$string['dmlexceptiononinstall'] = '<p>Roed gwall cronfa ddata [{$a->errorcode}].<br />{$a->debuginfo}</p>';
 $string['downloadedfilecheckfailed'] = 'Heb lwyddo i wirio\'r ffeil a lwythwyd i lawr';
-$string['invalidmd5'] = 'md5 annilys';
+$string['invalidmd5'] = 'Roedd y newidyn gwirio yn anghywir - rhowch gynnig arall arni';
 $string['missingrequiredfield'] = 'Mae maes gofynnol ar goll';
 $string['remotedownloaderror'] = 'Wedi methu llwytho cydran ar eich gweinydd, gwiriwch osodiadau\'r dirprwy, argymhellir yr estyniad PHP cURL yn gryf.<br /><br />Mae\'n rhaid i chi lwytho\'r ffeil <a href="{$a->url}">{$a->url}</a> eich hun, ei chopïo i "{$a->dest}" ar eich gweinydd, a\'i dad-zipio yno.';
-$string['wrongdestpath'] = 'Llwybr cyrchfan anghywir.';
-$string['wrongsourcebase'] = 'Bôn URL ffynhonnell anghywir.';
-$string['wrongzipfilename'] = 'Enw ffeil ZIP anghywir.';
+$string['wrongdestpath'] = 'Llwybr cyrchfan anghywir';
+$string['wrongsourcebase'] = 'Bôn URL ffynhonnell anghywir';
+$string['wrongzipfilename'] = 'Enw ffeil ZIP anghywir';
index c9bce3c..16b978d 100644 (file)
 
 defined('MOODLE_INTERNAL') || die();
 
-$string['admindirname'] = 'Cyfeiriadur y Gweinyddwr';
+$string['admindirname'] = 'Cyfeiriadur y gweinyddwr';
 $string['availablelangs'] = 'Y pecynnau iaith sydd ar gael';
 $string['chooselanguagehead'] = 'Dewis iaith';
-$string['chooselanguagesub'] = 'Dewiswch iaith ar gyfer y broses osod YN UNIG. Gallwch ddewis yr iaith ar gyfer y safle ac ar gyfer defnyddwyr yn nes ymlaen ar sgrin arall.';
+$string['chooselanguagesub'] = 'Dewiswch iaith ar gyfer y broses osod. Bydd yr iaith hon yn cael ei defnyddio fel yr iaith ddiofyn ar gyfer y safle, ond gellir ei newid yn nes ymlaen.';
+$string['clialreadyconfigured'] = 'Mae\'r ffeil config.php yn bodoli eisoes, defnyddiwch admin/cli/install_database.php os ydych chi am osod y safle hwn.';
+$string['clialreadyinstalled'] = 'Mae\'r ffeil config.php yn bodoli eisoes, defnyddiwch admin/cli/upgrade.php os ydych chi am uwchraddio eich safle.';
 $string['cliinstallheader'] = 'Rhaglen gosod llinell gorchymyn Moodle {$a}';
 $string['databasehost'] = 'Gwesteiwr y gronfa ddata';
 $string['databasename'] = 'Enw\'r gronfa ddata';
 $string['databasetypehead'] = 'Dewis gyrrwr ar gyfer y gronfa ddata';
-$string['dataroot'] = 'Cyfeiriadur Data';
+$string['dataroot'] = 'Cyfeiriadur data';
 $string['datarootpermission'] = 'Hawliau ar gyfer cyfeiriaduron data';
 $string['dbprefix'] = 'Llythrennau Blaen Tablau';
 $string['dirroot'] = 'Cyfeiriadur Moodle';
index f1d5f2a..bd664c1 100644 (file)
@@ -31,7 +31,7 @@
 defined('MOODLE_INTERNAL') || die();
 
 $string['admindirname'] = 'Admin directory';
-$string['availablelangs'] = 'List of available languages';
+$string['availablelangs'] = 'Available language packs';
 $string['chooselanguagehead'] = 'Choose a language';
 $string['chooselanguagesub'] = 'Please choose a language for the installation. This language will also be used as the default language for the site, though it may be changed later.';
 $string['clialreadyconfigured'] = 'File config.php already exists, please use admin/cli/install_database.php if you want to install this site.';
index f129f7e..6cec6af 100644 (file)
@@ -31,7 +31,7 @@
 defined('MOODLE_INTERNAL') || die();
 
 $string['admindirname'] = 'Directorio Admin';
-$string['availablelangs'] = 'Lista de idiomas disponibles';
+$string['availablelangs'] = 'Paquetes de idiomas disponibles';
 $string['chooselanguagehead'] = 'Seleccionar idioma';
 $string['chooselanguagesub'] = 'Por favor, seleccione un idioma para el proceso de instalación. Este idioma se usará también como idioma por defecto del sitio, si bien puede cambiarse más adelante.';
 $string['clialreadyconfigured'] = 'El archivo config.php ya existe, por favor use admin/cli/install_database.php si desea instalar este sitio';
index 7f314dd..3406062 100644 (file)
@@ -32,3 +32,4 @@ defined('MOODLE_INTERNAL') || die();
 
 $string['clianswerno'] = 'एन';
 $string['cliansweryes'] = 'वाई';
+$string['clitypevalue'] = 'टाइप मूल्य';
index dce0b84..70ecf47 100644 (file)
@@ -31,7 +31,7 @@
 defined('MOODLE_INTERNAL') || die();
 
 $string['admindirname'] = 'Adminディレクトリ';
-$string['availablelangs'] = '利用可能な言語一覧';
+$string['availablelangs'] = '利用可能な言語パック';
 $string['chooselanguagehead'] = '言語を選択してください。';
 $string['chooselanguagesub'] = 'インストールのみに使用する言語を選択してください。この言語は、サイトのデフォルト言語としても使用されます。サイト言語は、後で変更することが可能です。';
 $string['clialreadyconfigured'] = 'ファイルconfig.phpは、すでに登録されています。このサイトをインストールしたい場合、admin/cli/install_database.phpを使用してください。';
index 7ab2737..3688080 100644 (file)
@@ -30,6 +30,9 @@
 
 defined('MOODLE_INTERNAL') || die();
 
+$string['cannotcreatedboninstall'] = '<p>Kan databank niet maken.</p>
+<p>De opgegeven databank bestaat niet en de opgegeven gebruiker heeft onvoldoende rechten om de databank te maken.</p>
+<p>De site-beheerder moet de databankconfiguratie controleren.</p>';
 $string['cannotcreatelangdir'] = 'Kan lang map niet maken';
 $string['cannotcreatetempdir'] = 'Kan tijdelijke map niet maken.';
 $string['cannotdownloadcomponents'] = 'Kan componenten niet downloaden.';
@@ -39,6 +42,7 @@ $string['cannotsavemd5file'] = 'Kan md5-bestand niet bewaren.';
 $string['cannotsavezipfile'] = 'Kan ZIP-bestand niet bewaren.';
 $string['cannotunzipfile'] = 'Kon bestand niet unzippen';
 $string['componentisuptodate'] = 'Component is up-to-date';
+$string['dmlexceptiononinstall'] = '<p>Databankfout [{$a->errorcode}].<br />{$a->debuginfo}</p>';
 $string['downloadedfilecheckfailed'] = 'Controle van het gedownloade bestand mislukt';
 $string['invalidmd5'] = 'De controlevariable was fout - probeer nog eens';
 $string['missingrequiredfield'] = 'Vereist veld ontbreekt';
index 26b9927..11940b7 100644 (file)
@@ -30,6 +30,9 @@
 
 defined('MOODLE_INTERNAL') || die();
 
+$string['cannotcreatedboninstall'] = '<p>Kan ikke opprette databasen.</p>
+<p>Den angitte databasen eksisterer ikke og oppgitt bruker har ikke rettigheter til å opprette databasen.</p>
+<p>Portaladministratoren må derfor verifisere databaseoppsettet.</p>';
 $string['cannotcreatelangdir'] = 'Kan ikke opprette mappen \'lang\'.';
 $string['cannotcreatetempdir'] = 'Kan ikke opprette mappen \'temp';
 $string['cannotdownloadcomponents'] = 'Kan ikke laste ned komponentene.';
@@ -39,6 +42,7 @@ $string['cannotsavemd5file'] = 'Kan ikke lagre md5-fil.';
 $string['cannotsavezipfile'] = 'Kan ikke lagre ZIP-fil.';
 $string['cannotunzipfile'] = 'Kan ikke pakke opp filen.';
 $string['componentisuptodate'] = 'Komponenten er oppdatert';
+$string['dmlexceptiononinstall'] = '<p>Det oppstod en databasefeil [{$a->errorcode}].<br />{$a->debuginfo}</p>';
 $string['downloadedfilecheckfailed'] = 'Sjekk av nedlastet fil mislykkes.';
 $string['invalidmd5'] = 'Ugyldig md5, prøv igjen';
 $string['missingrequiredfield'] = 'Noen påkrevde felt mangler';
index 7e63b28..aa1a433 100644 (file)
@@ -43,6 +43,8 @@ class core_component {
     protected static $classmap = null;
     /** @var null list of some known files that can be included. */
     protected static $filemap = null;
+    /** @var int|float core version. */
+    protected static $version = null;
     /** @var array list of the files to map. */
     protected static $filestomap = array('lib.php', 'settings.php');
 
@@ -133,8 +135,11 @@ class core_component {
                 include($cachefile);
                 if (!is_array($cache)) {
                     // Something is very wrong.
-                } else if (!isset($cache['plugintypes']) or !isset($cache['plugins']) or !isset($cache['subsystems']) or !isset($cache['classmap'])) {
+                } else if (!isset($cache['version'])) {
                     // Something is very wrong.
+                } else if ((float) $cache['version'] !== (float) self::fetch_core_version()) {
+                    // Outdated cache. We trigger an error log to track an eventual repetitive failure of float comparison.
+                    error_log('Resetting core_component cache after core upgrade to version ' . self::fetch_core_version());
                 } else if ($cache['plugintypes']['mod'] !== "$CFG->dirroot/mod") {
                     // $CFG->dirroot was changed.
                 } else {
@@ -227,6 +232,7 @@ class core_component {
             'plugins'     => self::$plugins,
             'classmap'    => self::$classmap,
             'filemap'     => self::$filemap,
+            'version'     => self::$version,
         );
 
         return '<?php
@@ -249,6 +255,23 @@ $cache = '.var_export($cache, true).';
 
         self::fill_classmap_cache();
         self::fill_filemap_cache();
+        self::fetch_core_version();
+    }
+
+    /**
+     * Get the core version.
+     *
+     * In order for this to work properly, opcache should be reset beforehand.
+     *
+     * @return float core version.
+     */
+    protected static function fetch_core_version() {
+        global $CFG;
+        if (self::$version === null) {
+            require($CFG->dirroot . '/version.php');
+            self::$version = $version;
+        }
+        return self::$version;
     }
 
     /**
@@ -871,9 +894,7 @@ $cache = '.var_export($cache, true).';
         $versions = array();
 
         // Main version first.
-        $version = null;
-        include($CFG->dirroot.'/version.php');
-        $versions['core'] = $version;
+        $versions['core'] = self::fetch_core_version();
 
         // The problem here is tha the component cache might be stable,
         // we want this to work also on frontpage without resetting the component cache.
index efe335a..2260e4a 100644 (file)
@@ -80,6 +80,31 @@ function file_encode_url($urlbase, $path, $forcedownload=false, $https=false) {
     return $return;
 }
 
+/**
+ * Detects if area contains subdirs,
+ * this is intended for file areas that are attached to content
+ * migrated from 1.x where subdirs were allowed everywhere.
+ *
+ * @param context $context
+ * @param string $component
+ * @param string $filearea
+ * @param string $itemid
+ * @return bool
+ */
+function file_area_contains_subdirs(context $context, $component, $filearea, $itemid) {
+    global $DB;
+
+    if (!isset($itemid)) {
+        // Not initialised yet.
+        return false;
+    }
+
+    // Detect if any directories are already present, this is necessary for content upgraded from 1.x.
+    $select = "contextid = :contextid AND component = :component AND filearea = :filearea AND itemid = :itemid AND filepath <> '/' AND filename = '.'";
+    $params = array('contextid'=>$context->id, 'component'=>$component, 'filearea'=>$filearea, 'itemid'=>$itemid);
+    return $DB->record_exists_select('files', $select, $params);
+}
+
 /**
  * Prepares 'editor' formslib element from data in database
  *
index 3fbfb62..29cb8d8 100644 (file)
@@ -32,7 +32,6 @@ defined('MOODLE_INTERNAL') || die();
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 abstract class file_packer {
-
     /**
      * Archive files and store the result in file storage.
      *
@@ -45,9 +44,12 @@ abstract class file_packer {
      * @param string $filename file name
      * @param int $userid user ID
      * @param bool $ignoreinvalidfiles true means ignore missing or invalid files, false means abort on any error
+     * @param file_progress $progress Progress indicator callback or null if not required
      * @return stored_file|bool false if error stored_file instance if ok
      */
-    public abstract function archive_to_storage(array $files, $contextid, $component, $filearea, $itemid, $filepath, $filename, $userid = NULL, $ignoreinvalidfiles=true);
+    public abstract function archive_to_storage(array $files, $contextid,
+            $component, $filearea, $itemid, $filepath, $filename,
+            $userid = NULL, $ignoreinvalidfiles=true, file_progress $progress = null);
 
     /**
      * Archive files and store the result in os file.
@@ -55,9 +57,11 @@ abstract class file_packer {
      * @param array $files array with zip paths as keys (archivepath=>ospathname or archivepath=>stored_file)
      * @param string $archivefile path to target zip file
      * @param bool $ignoreinvalidfiles true means ignore missing or invalid files, false means abort on any error
+     * @param file_progress $progress Progress indicator callback or null if not required
      * @return bool true if file created, false if not
      */
-    public abstract function archive_to_pathname(array $files, $archivefile, $ignoreinvalidfiles=true);
+    public abstract function archive_to_pathname(array $files, $archivefile,
+            $ignoreinvalidfiles=true, file_progress $progress = null);
 
     /**
      * Extract file to given file path (real OS filesystem), existing files are overwritten.
@@ -65,9 +69,11 @@ abstract class file_packer {
      * @param stored_file|string $archivefile full pathname of zip file or stored_file instance
      * @param string $pathname target directory
      * @param array $onlyfiles only extract files present in the array
+     * @param file_progress $progress Progress indicator callback or null if not required
      * @return array|bool list of processed files; false if error
      */
-    public abstract function extract_to_pathname($archivefile, $pathname, array $onlyfiles = NULL);
+    public abstract function extract_to_pathname($archivefile, $pathname,
+            array $onlyfiles = NULL, file_progress $progress = null);
 
     /**
      * Extract file to given file path (real OS filesystem), existing files are overwritten.
@@ -79,9 +85,12 @@ abstract class file_packer {
      * @param int $itemid item ID
      * @param string $pathbase file path
      * @param int $userid user ID
+     * @param file_progress $progress Progress indicator callback or null if not required
      * @return array|bool list of processed files; false if error
      */
-    public abstract function extract_to_storage($archivefile, $contextid, $component, $filearea, $itemid, $pathbase, $userid = NULL);
+    public abstract function extract_to_storage($archivefile, $contextid,
+            $component, $filearea, $itemid, $pathbase, $userid = NULL,
+            file_progress $progress = null);
 
     /**
      * Returns array of info about all files in archive.
diff --git a/lib/filestorage/file_progress.php b/lib/filestorage/file_progress.php
new file mode 100644 (file)
index 0000000..23ae8c9
--- /dev/null
@@ -0,0 +1,53 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Simple interface for receiving progress during long-running file
+ * operations.
+ *
+ * In some cases progress can be reported precisely. In other cases,
+ * progress is indeterminate which means that the progress function is called
+ * periodically but without information on completion.
+ *
+ * @package core_files
+ * @copyright 2013 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+interface file_progress {
+    /**
+     * @var int Constant used for indeterminate progress.
+     */
+    const INDETERMINATE = -1;
+
+    /**
+     * Called during a file processing operation that reports progress.
+     *
+     * This function will be called periodically during the operation, assuming
+     * it is successful.
+     *
+     * If numbers (rather than INDETERMINATE) are provided, then:
+     * - The $progress value will either be the same as last call, or increased
+     *   by some value (not necessarily 1).
+     * - The $progress value will be less than or equal to the $max value.
+     *
+     * There is no guarantee that this function will be called for every value
+     * in the range, or that it will be called with $progress == $max.
+     *
+     * @param int $progress Current progress, or INDETERMINATE if unknown
+     * @param int $max Max progress, or INDETERMINATE if unknown
+     */
+    public function progress($progress = self::INDETERMINATE, $max = self::INDETERMINATE);
+}
index fbce9af..d56aa52 100644 (file)
@@ -25,6 +25,8 @@
 
 defined('MOODLE_INTERNAL') || die();
 
+require_once($CFG->dirroot . '/lib/filestorage/file_progress.php');
+
 /**
  * Class representing local files stored in a sha1 file pool.
  *
@@ -480,11 +482,13 @@ class stored_file {
      *
      * @param file_packer $packer file packer instance
      * @param string $pathname target directory
+     * @param file_progress $progress Progress indicator callback or null if not required
      * @return array|bool list of processed files; false if error
      */
-    public function extract_to_pathname(file_packer $packer, $pathname) {
+    public function extract_to_pathname(file_packer $packer, $pathname,
+            file_progress $progress = null) {
         $archivefile = $this->get_content_file_location();
-        return $packer->extract_to_pathname($archivefile, $pathname);
+        return $packer->extract_to_pathname($archivefile, $pathname, null, $progress);
     }
 
     /**
@@ -497,11 +501,14 @@ class stored_file {
      * @param int $itemid item ID
      * @param string $pathbase path base
      * @param int $userid user ID
+     * @param file_progress $progress Progress indicator callback or null if not required
      * @return array|bool list of processed files; false if error
      */
-    public function extract_to_storage(file_packer $packer, $contextid, $component, $filearea, $itemid, $pathbase, $userid = NULL) {
+    public function extract_to_storage(file_packer $packer, $contextid,
+            $component, $filearea, $itemid, $pathbase, $userid = null, file_progress $progress = null) {
         $archivefile = $this->get_content_file_location();
-        return $packer->extract_to_storage($archivefile, $contextid, $component, $filearea, $itemid, $pathbase);
+        return $packer->extract_to_storage($archivefile, $contextid,
+                $component, $filearea, $itemid, $pathbase, $userid, $progress);
     }
 
     /**
index 3182709..da203d4 100644 (file)
 
 defined('MOODLE_INTERNAL') || die();
 
+global $CFG;
+require_once($CFG->libdir . '/filestorage/file_progress.php');
 
-class core_files_zip_packer_testcase extends advanced_testcase {
+class core_files_zip_packer_testcase extends advanced_testcase implements file_progress {
     protected $testfile;
     protected $files;
 
+    /**
+     * @var array Progress information passed to the progress reporter
+     */
+    protected $progress;
+
     protected function setUp() {
         parent::setUp();
 
@@ -415,4 +422,92 @@ class core_files_zip_packer_testcase extends advanced_testcase {
 
         unlink($archive);
     }
+
+    /**
+     * Tests the progress reporting.
+     */
+    public function test_file_progress() {
+        global $CFG;
+
+        // Set up.
+        $this->resetAfterTest(true);
+        $packer = get_file_packer('application/zip');
+        $archive = "$CFG->tempdir/archive.zip";
+        $context = context_system::instance();
+
+        // Archive to pathname.
+        $this->progress = array();
+        $result = $packer->archive_to_pathname($this->files, $archive, true, $this);
+        $this->assertTrue($result);
+        // Should send progress at least once per file.
+        $this->assertTrue(count($this->progress) >= count($this->files));
+        // Each progress will be indeterminate.
+        $this->assertEquals(
+                array(file_progress::INDETERMINATE, file_progress::INDETERMINATE),
+                $this->progress[0]);
+
+        // Archive to storage.
+        $this->progress = array();
+        $archivefile = $packer->archive_to_storage($this->files, $context->id,
+                'phpunit', 'test', 0, '/', 'archive.zip', null, true, $this);
+        $this->assertInstanceOf('stored_file', $archivefile);
+        $this->assertTrue(count($this->progress) >= count($this->files));
+        $this->assertEquals(
+                array(file_progress::INDETERMINATE, file_progress::INDETERMINATE),
+                $this->progress[0]);
+
+        // Extract to pathname.
+        $this->progress = array();
+        $target = "$CFG->tempdir/test/";
+        check_dir_exists($target);
+        $result = $packer->extract_to_pathname($archive, $target, null, $this);
+        remove_dir($target);
+        $this->assertEquals(count($this->files), count($result));
+        $this->assertTrue(count($this->progress) >= count($this->files));
+        $this->check_progress_toward_max();
+
+        // Extract to storage (from storage).
+        $this->progress = array();
+        $result = $packer->extract_to_storage($archivefile, $context->id,
+                'phpunit', 'target', 0, '/', null, $this);
+        $this->assertEquals(count($this->files), count($result));
+        $this->assertTrue(count($this->progress) >= count($this->files));
+        $this->check_progress_toward_max();
+
+        // Extract to storage (from path).
+        $this->progress = array();
+        $result = $packer->extract_to_storage($archive, $context->id,
+                'phpunit', 'target', 0, '/', null, $this);
+        $this->assertEquals(count($this->files), count($result));
+        $this->assertTrue(count($this->progress) >= count($this->files));
+        $this->check_progress_toward_max();
+
+        // Wipe created disk file.
+        unlink($archive);
+    }
+
+    /**
+     * Checks that progress reported is numeric rather than indeterminate,
+     * and follows the progress reporting rules.
+     */
+    private function check_progress_toward_max() {
+        $lastvalue = -1;
+        foreach ($this->progress as $progressitem) {
+            list($value, $max) = $progressitem;
+            $this->assertNotEquals(file_progress::INDETERMINATE, $max);
+            $this->assertTrue($value <= $max);
+            $this->assertTrue($value >= $lastvalue);
+            $lastvalue = $value;
+        }
+    }
+
+    /**
+     * Handles file_progress interface.
+     *
+     * @param int $progress
+     * @param int $max
+     */
+    public function progress($progress = file_progress::INDETERMINATE, $max = file_progress::INDETERMINATE) {
+        $this->progress[] = array($progress, $max);
+    }
 }
index 1ef485e..8a995a1 100644 (file)
@@ -341,6 +341,20 @@ class zip_archive extends file_archive {
         return count($this->list_files());
     }
 
+    /**
+     * Returns approximate number of files in archive. This may be a slight
+     * overestimate.
+     *
+     * @return int|bool Estimated number of files, or false if not opened
+     */
+    public function estimated_count() {
+        if (!isset($this->za)) {
+            return false;
+        }
+
+        return $this->za->numFiles;
+    }
+
     /**
      * Add file into archive.
      *
index 2f5bfc3..dcd9025 100644 (file)
@@ -50,9 +50,12 @@ class zip_packer extends file_packer {
      * @param string $filename file name
      * @param int $userid user ID
      * @param bool $ignoreinvalidfiles true means ignore missing or invalid files, false means abort on any error
+     * @param file_progress $progress Progress indicator callback or null if not required
      * @return stored_file|bool false if error stored_file instance if ok
      */
-    public function archive_to_storage(array $files, $contextid, $component, $filearea, $itemid, $filepath, $filename, $userid = NULL, $ignoreinvalidfiles=true) {
+    public function archive_to_storage(array $files, $contextid,
+            $component, $filearea, $itemid, $filepath, $filename,
+            $userid = NULL, $ignoreinvalidfiles=true, file_progress $progress = null) {
         global $CFG;
 
         $fs = get_file_storage();
@@ -60,7 +63,7 @@ class zip_packer extends file_packer {
         check_dir_exists($CFG->tempdir.'/zip');
         $tmpfile = tempnam($CFG->tempdir.'/zip', 'zipstor');
 
-        if ($result = $this->archive_to_pathname($files, $tmpfile, $ignoreinvalidfiles)) {
+        if ($result = $this->archive_to_pathname($files, $tmpfile, $ignoreinvalidfiles, $progress)) {
             if ($file = $fs->get_file($contextid, $component, $filearea, $itemid, $filepath, $filename)) {
                 if (!$file->delete()) {
                     @unlink($tmpfile);
@@ -89,9 +92,11 @@ class zip_packer extends file_packer {
      * @param array $files array with zip paths as keys (archivepath=>ospathname or archivepath=>stored_file or archivepath=>array('content_as_string'))
      * @param string $archivefile path to target zip file
      * @param bool $ignoreinvalidfiles true means ignore missing or invalid files, false means abort on any error
+     * @param file_progress $progress Progress indicator callback or null if not required
      * @return bool true if file created, false if not
      */
-    public function archive_to_pathname(array $files, $archivefile, $ignoreinvalidfiles=true) {
+    public function archive_to_pathname(array $files, $archivefile,
+            $ignoreinvalidfiles=true, file_progress $progress = null) {
         $ziparch = new zip_archive();
         if (!$ziparch->open($archivefile, file_archive::OVERWRITE)) {
             return false;
@@ -101,6 +106,11 @@ class zip_packer extends file_packer {
         foreach ($files as $archivepath => $file) {
             $archivepath = trim($archivepath, '/');
 
+            // Record progress each time around this loop.
+            if ($progress) {
+                $progress->progress();
+            }
+
             if (is_null($file)) {
                 // Directories have null as content.
                 if (!$ziparch->add_directory($archivepath.'/')) {
@@ -160,9 +170,10 @@ class zip_packer extends file_packer {
      * @param zip_archive $ziparch zip archive instance
      * @param string $archivepath file path to archive
      * @param stored_file $file stored_file object
+     * @param file_progress $progress Progress indicator callback or null if not required
      * @return bool success
      */
-    private function archive_stored($ziparch, $archivepath, $file) {
+    private function archive_stored($ziparch, $archivepath, $file, file_progress $progress = null) {
         $result = $file->archive_file($ziparch, $archivepath);
         if (!$result) {
             return false;
@@ -177,6 +188,11 @@ class zip_packer extends file_packer {
         $files = $fs->get_directory_files($file->get_contextid(), $file->get_component(), $file->get_filearea(), $file->get_itemid(),
                                           $file->get_filepath(), true, true);
         foreach ($files as $file) {
+            // Record progress for each file.
+            if ($progress) {
+                $progress->progress();
+            }
+
             $path = $file->get_filepath();
             $path = substr($path, $baselength);
             $path = $archivepath.'/'.$path;
@@ -196,9 +212,16 @@ class zip_packer extends file_packer {
      * @param zip_archive $ziparch zip archive instance
      * @param string $archivepath file path to archive
      * @param string $file path name of the file
+     * @param file_progress $progress Progress indicator callback or null if not required
      * @return bool success
      */
-    private function archive_pathname($ziparch, $archivepath, $file) {
+    private function archive_pathname($ziparch, $archivepath, $file,
+            file_progress $progress = null) {
+        // Record progress each time this function is called.
+        if ($progress) {
+            $progress->progress();
+        }
+
         if (!file_exists($file)) {
             return false;
         }
@@ -234,13 +257,15 @@ class zip_packer extends file_packer {
      * @param string $pathname target directory
      * @param array $onlyfiles only extract files present in the array. The path to files MUST NOT
      *              start with a /. Example: array('myfile.txt', 'directory/anotherfile.txt')
+     * @param file_progress $progress Progress indicator callback or null if not required
      * @return bool|array list of processed files; false if error
      */
-    public function extract_to_pathname($archivefile, $pathname, array $onlyfiles = null) {
+    public function extract_to_pathname($archivefile, $pathname,
+            array $onlyfiles = null, file_progress $progress = null) {
         global $CFG;
 
         if (!is_string($archivefile)) {
-            return $archivefile->extract_to_pathname($this, $pathname);
+            return $archivefile->extract_to_pathname($this, $pathname, $progress);
         }
 
         $processed = array();
@@ -254,7 +279,19 @@ class zip_packer extends file_packer {
             return false;
         }
 
+        // Get the number of files (approx).
+        if ($progress) {
+            $approxmax = $ziparch->estimated_count();
+            $done = 0;
+        }
+
         foreach ($ziparch as $info) {
+            // Notify progress.
+            if ($progress) {
+                $progress->progress($done, $approxmax);
+                $done++;
+            }
+
             $size = $info->size;
             $name = $info->pathname;
 
@@ -337,13 +374,17 @@ class zip_packer extends file_packer {
      * @param int $itemid item ID
      * @param string $pathbase file path
      * @param int $userid user ID
+     * @param file_progress $progress Progress indicator callback or null if not required
      * @return array|bool list of processed files; false if error
      */
-    public function extract_to_storage($archivefile, $contextid, $component, $filearea, $itemid, $pathbase, $userid = NULL) {
+    public function extract_to_storage($archivefile, $contextid,
+            $component, $filearea, $itemid, $pathbase, $userid = NULL,
+            file_progress $progress = null) {
         global $CFG;
 
         if (!is_string($archivefile)) {
-            return $archivefile->extract_to_storage($this, $contextid, $component, $filearea, $itemid, $pathbase, $userid);
+            return $archivefile->extract_to_storage($this, $contextid, $component,
+                    $filearea, $itemid, $pathbase, $userid, $progress);
         }
 
         check_dir_exists($CFG->tempdir.'/zip');
@@ -359,7 +400,19 @@ class zip_packer extends file_packer {
             return false;
         }
 
+        // Get the number of files (approx).
+        if ($progress) {
+            $approxmax = $ziparch->estimated_count();
+            $done = 0;
+        }
+
         foreach ($ziparch as $info) {
+            // Notify progress.
+            if ($progress) {
+                $progress->progress($done, $approxmax);
+                $done++;
+            }
+
             $size = $info->size;
             $name = $info->pathname;
 
index 22fbbf3..87d888d 100644 (file)
@@ -91,6 +91,9 @@ class MoodleQuickForm_editor extends HTML_QuickForm_element {
         $this->_options['trusted'] = trusttext_trusted($this->_options['context']);
         parent::HTML_QuickForm_element($elementName, $elementLabel, $attributes);
 
+        // Note: for some reason the code using this setting does not like bools.
+        $this->_options['subdirs'] = (int)($this->_options['subdirs'] == 1);
+
         editors_head_setup();
     }
 
@@ -205,7 +208,7 @@ class MoodleQuickForm_editor extends HTML_QuickForm_element {
      * @param bool $allow true if sub directory can be created.
      */
     function setSubdirs($allow) {
-        $this->_options['subdirs'] = $allow;
+        $this->_options['subdirs'] = (int)($allow == 1);
     }
 
     /**
index 769cacb..777ee23 100644 (file)
@@ -198,6 +198,7 @@ class moodle_simplepie_sanitize extends SimplePie_Sanitize {
             if ($absolute !== false) {
                 $data = $absolute;
             }
+            $data = clean_param($data, PARAM_URL);
         }
 
         if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI)) {
index e58fe6d..a27a129 100644 (file)
@@ -22,6 +22,9 @@ information provided here is intended especially for developers.
 * Use behat_selectors::get_allowed_text_selectors() and behat_selectors::get_allowed_selectors() instead of
   behat_command::$allowedtextselectors and behat_command::$allowedselectors
 * Subplugins are supported in admin tools and local plugins.
+* file_packer/zip_packer API has been modified so that key functions support a new file_progress interface
+  to report progress during long operations. Related to this, zip_archive now supports an estimated_count()
+  function that returns an approximate number of entries in the zip faster than the count() function.
 
 DEPRECATIONS:
 Various previously deprecated functions have now been altered to throw DEBUG_DEVELOPER debugging notices
index cf9ed55..9a604d2 100644 (file)
@@ -191,7 +191,7 @@ if (!$book->customtitles) {
     }
 }
 $chaptertext = file_rewrite_pluginfile_urls($chapter->content, 'pluginfile.php', $context->id, 'mod_book', 'chapter', $chapter->id);
-echo format_text($chaptertext, $chapter->contentformat, array('noclean'=>true, 'context'=>$context));
+echo format_text($chaptertext, $chapter->contentformat, array('noclean'=>true, 'overflowdiv'=>true, 'context'=>$context));
 
 echo $OUTPUT->box_end();
 
index 6840446..d768647 100644 (file)
@@ -57,9 +57,11 @@ class mod_forum_post_form extends moodleform {
     /**
      * Returns the options array to use in forum text editor
      *
+     * @param context_module $context
+     * @param int $postid post id, use null when adding new post
      * @return array
      */
-    public static function editor_options() {
+    public static function editor_options(context_module $context, $postid) {
         global $COURSE, $PAGE, $CFG;
         // TODO: add max files and max size support
         $maxbytes = get_user_max_upload_file_size($PAGE->context, $CFG->maxbytes, $COURSE->maxbytes);
@@ -67,7 +69,8 @@ class mod_forum_post_form extends moodleform {
             'maxfiles' => EDITOR_UNLIMITED_FILES,
             'maxbytes' => $maxbytes,
             'trusttext'=> true,
-            'return_types'=> FILE_INTERNAL | FILE_EXTERNAL
+            'return_types'=> FILE_INTERNAL | FILE_EXTERNAL,
+            'subdirs' => file_area_contains_subdirs($context, 'mod_forum', 'post', $postid)
         );
     }
 
@@ -106,7 +109,7 @@ class mod_forum_post_form extends moodleform {
         $mform->addRule('subject', get_string('required'), 'required', null, 'client');
         $mform->addRule('subject', get_string('maximumchars', '', 255), 'maxlength', 255, 'client');
 
-        $mform->addElement('editor', 'message', get_string('message', 'forum'), null, self::editor_options());
+        $mform->addElement('editor', 'message', get_string('message', 'forum'), null, self::editor_options($modcontext, (empty($post->id) ? null : $post->id)));
         $mform->setType('message', PARAM_RAW);
         $mform->addRule('message', get_string('required'), 'required', null, 'client');
 
index be0a2ea..41e9be7 100644 (file)
@@ -4370,7 +4370,7 @@ function forum_add_new_post($post, $mform, &$message) {
 
     $post->id = $DB->insert_record("forum_posts", $post);
     $post->message = file_save_draft_area_files($post->itemid, $context->id, 'mod_forum', 'post', $post->id,
-            mod_forum_post_form::editor_options(), $post->message);
+            mod_forum_post_form::editor_options($context, null), $post->message);
     $DB->set_field('forum_posts', 'message', $post->message, array('id'=>$post->id));
     forum_add_attachment($post, $forum, $cm, $mform, $message);
 
@@ -4420,7 +4420,7 @@ function forum_update_post($post, $mform, &$message) {
         $discussion->timeend   = $post->timeend;
     }
     $post->message = file_save_draft_area_files($post->itemid, $context->id, 'mod_forum', 'post', $post->id,
-            mod_forum_post_form::editor_options(), $post->message);
+            mod_forum_post_form::editor_options($context, $post->id), $post->message);
     $DB->set_field('forum_posts', 'message', $post->message, array('id'=>$post->id));
 
     $DB->update_record('forum_discussions', $discussion);
@@ -4484,7 +4484,7 @@ function forum_add_discussion($discussion, $mform=null, $unused=null, $userid=nu
     if (!empty($cm->id) && !empty($discussion->itemid)) {   // In "single simple discussions" this may not exist yet
         $context = context_module::instance($cm->id);
         $text = file_save_draft_area_files($discussion->itemid, $context->id, 'mod_forum', 'post', $post->id,
-                mod_forum_post_form::editor_options(), $post->message);
+                mod_forum_post_form::editor_options($context, null), $post->message);
         $DB->set_field('forum_posts', 'message', $text, array('id'=>$post->id));
     }
 
index 3a7bf1b..63342ee 100644 (file)
@@ -557,8 +557,9 @@ if (forum_is_subscribed($USER->id, $forum->id)) {
     $subscribe = !empty($USER->autosubscribe);
 }
 
+$postid = empty($post->id) ? null : $post->id;
 $draftid_editor = file_get_submitted_draft_itemid('message');
-$currenttext = file_prepare_draft_area($draftid_editor, $modcontext->id, 'mod_forum', 'post', empty($post->id) ? null : $post->id, mod_forum_post_form::editor_options(), $post->message);
+$currenttext = file_prepare_draft_area($draftid_editor, $modcontext->id, 'mod_forum', 'post', $postid, mod_forum_post_form::editor_options($modcontext, $postid), $post->message);
 $mform_post->set_data(array(        'attachments'=>$draftitemid,
                                     'general'=>$heading,
                                     'subject'=>$post->subject,
index 00e9343..e77cb44 100644 (file)
@@ -66,7 +66,8 @@ if ($id) { // if entry is specified
 $maxfiles = 99;                // TODO: add some setting
 $maxbytes = $course->maxbytes; // TODO: add some setting
 
-$definitionoptions = array('trusttext'=>true, 'subdirs'=>false, 'maxfiles'=>$maxfiles, 'maxbytes'=>$maxbytes, 'context'=>$context);
+$definitionoptions = array('trusttext'=>true, 'maxfiles'=>$maxfiles, 'maxbytes'=>$maxbytes, 'context'=>$context,
+    'subdirs'=>file_area_contains_subdirs($context, 'mod_glossary', 'entry', $entry->id));
 $attachmentoptions = array('subdirs'=>false, 'maxfiles'=>$maxfiles, 'maxbytes'=>$maxbytes);
 
 $entry = file_prepare_standard_editor($entry, 'definition', $definitionoptions, $context, 'mod_glossary', 'entry', $entry->id);
index a664a9c..893d3ad 100644 (file)
@@ -98,7 +98,7 @@ $string['clicktocontinue'] = 'Click here to continue';
 $string['clicktocontinuecheck'] = 'Click here to check and continue';
 $string['collesaintro'] = 'The purpose of this survey is to help us understand how well the online delivery of this unit enabled you to learn.
 
-Each one of the 24 statements below asks about your experience in this unit.
+Each couple of the 24 statements below asks about your experience in this unit.
 
 There are no \'right\' or \'wrong\' answers; we are interested only in your opinion. Please be assured that your responses will be treated with a high degree of confidentiality, and will not affect your assessment.
 
index a4e3e7b..435ebf8 100644 (file)
@@ -509,8 +509,22 @@ function survey_print_multi($question) {
     $options = explode( ",", $question->options);
     $numoptions = count($options);
 
+    // COLLES Actual (which is having questions of type 1) and COLLES Preferred (type 2)
+    // expect just one answer per question. COLLES Actual and Preferred (type 3) expects
+    // two answers per question. ATTLS (having a single question of type 1) expects one
+    // answer per question. CIQ is not using multiquestions (i.e. a question with subquestions).
+    // Note that the type of subquestions does not really matter, it's the type of the
+    // question itself that determines everything.
     $oneanswer = ($question->type == 1 || $question->type == 2) ? true : false;
 
+    // COLLES Preferred (having questions of type 2) will use the radio elements with the name
+    // like qP1, qP2 etc. COLLES Actual and ATTLS have radios like q1, q2 etc.
+    if ($question->type == 2) {
+        $P = "P";
+    } else {
+        $P = "";
+    }
+
     echo "<tr class=\"smalltext\"><th scope=\"row\">$strresponses</th>";
     echo "<th scope=\"col\" class=\"hresponse\">". get_string('notyetanswered', 'survey'). "</th>";
     while (list ($key, $val) = each ($options)) {
@@ -518,28 +532,21 @@ function survey_print_multi($question) {
     }
     echo "</tr>\n";
 
-    if ($oneanswer) {
-        echo "<tr><th scope=\"col\" colspan=\"7\">$question->intro</th></tr>\n";
-    } else {
-        echo "<tr><th scope=\"col\" colspan=\"7\">$question->intro</th></tr>\n";
-    }
+    echo "<tr><th scope=\"col\" colspan=\"7\">$question->intro</th></tr>\n";
 
     $subquestions = $DB->get_records_list("survey_questions", "id", explode(',', $question->multi));
 
     foreach ($subquestions as $q) {
         $qnum++;
-        $rowclass = survey_question_rowclass($qnum);
+        if ($oneanswer) {
+            $rowclass = survey_question_rowclass($qnum);
+        } else {
+            $rowclass = survey_question_rowclass(round($qnum / 2));
+        }
         if ($q->text) {
             $q->text = get_string($q->text, "survey");
         }
 
-        $oneanswer = ($q->type == 1 || $q->type == 2) ? true : false;
-        if ($q->type == 2) {
-            $P = "P";
-        } else {
-            $P = "";
-        }
-
         echo "<tr class=\"$rowclass rblock\">";
         if ($oneanswer) {
             echo "<th scope=\"row\" class=\"optioncell\">";
@@ -557,15 +564,14 @@ function survey_print_multi($question) {
             $checklist["q$P$q->id"] = 0;
 
         } else {
-            // yu : fix for MDL-7501, possibly need to use user flag as this is quite ugly.
             echo "<th scope=\"row\" class=\"optioncell\">";
             echo "<b class=\"qnumtopcell\">$qnum</b> &nbsp; ";
             $qnum++;
-            echo "<span class=\"preferthat smalltext\">$stripreferthat</span> &nbsp; ";
+            echo "<span class=\"preferthat\">$stripreferthat</span> &nbsp; ";
             echo "<span class=\"option\">$q->text</span></th>\n";
 
             $default = get_accesshide($strdefault);
-            echo '<td class="whitecell"><label for="qP'. $P.$q->id .'"><input type="radio" name="qP'.$P.$q->id. '" id="qP'. $q->id .'" value="0" checked="checked" />'.$default.'</label></td>';
+            echo '<td class="whitecell"><label for="qP'.$q->id.'"><input type="radio" name="qP'.$q->id.'" id="qP'.$q->id.'" value="0" checked="checked" />'.$default.'</label></td>';
 
 
             for ($i=1;$i<=$numoptions;$i++) {
@@ -578,7 +584,7 @@ function survey_print_multi($question) {
             echo "<tr class=\"$rowclass rblock\">";
             echo "<th scope=\"row\" class=\"optioncell\">";
             echo "<b class=\"qnumtopcell\">$qnum</b> &nbsp; ";
-            echo "<span class=\"foundthat smalltext\">$strifoundthat</span> &nbsp; ";
+            echo "<span class=\"foundthat\">$strifoundthat</span> &nbsp; ";
             echo "<span class=\"option\">$q->text</span></th>\n";
 
             $default = get_accesshide($strdefault);
index e0c80f8..2e2b74a 100644 (file)
@@ -76,7 +76,8 @@ $editoroptions = array(
     'maxfiles'  => EDITOR_UNLIMITED_FILES,
     'maxbytes'  => $CFG->maxbytes,
     'trusttext' => false,
-    'context'   => $systemcontext
+    'context'   => $systemcontext,
+    'subdirs'   => file_area_contains_subdirs($systemcontext, 'tag', 'description', $tag->id),
 );
 $tag = file_prepare_standard_editor($tag, 'description', $editoroptions, $systemcontext, 'tag', 'description', $tag->id);
 
index 7273624..e101961 100644 (file)
@@ -33,7 +33,7 @@ $version  = 2013090500.01;              // YYYYMMDD      = weekly release date o
                                         //         RR    = release increments - 00 in DEV branches.
                                         //           .XX = incremental changes.
 
-$release  = '2.6dev (Build: 20130905)'; // Human-friendly version name
+$release  = '2.6dev (Build: 20130907)'; // Human-friendly version name
 
 $branch   = '26';                       // This version's branch.
 $maturity = MATURITY_ALPHA;             // This version's maturity level.