Merge branch 'MDL-33398b' of git://github.com/srynot4sale/moodle
authorDan Poltawski <dan@moodle.com>
Wed, 30 May 2012 03:35:56 +0000 (11:35 +0800)
committerDan Poltawski <dan@moodle.com>
Wed, 30 May 2012 03:35:56 +0000 (11:35 +0800)
35 files changed:
admin/cli/install.php
admin/cli/mysql_engine.php
admin/cli/upgrade.php
admin/tool/bloglevelupgrade/index.php
backup/moodle2/backup_stepslib.php
backup/util/dbops/backup_controller_dbops.class.php
calendar/lib.php
course/changenumsections.php
course/format/renderer.php
course/format/topics/format.js
course/format/topics/lib.php
course/format/weeks/format.js
course/format/weeks/lib.php
course/lib.php
course/recent.php
course/rest.php
course/yui/coursebase/coursebase.js
course/yui/dragdrop/dragdrop.js
lang/en/access.php
lang/en/admin.php
lib/conditionlib.php
lib/filebrowser/file_info_stored.php
lib/filelib.php
lib/filestorage/file_storage.php
lib/form/dndupload.js
lib/form/filemanager.js
lib/form/filepicker.js
lib/installlib.php
lib/portfolio/exporter.php
lib/setup.php
lib/tests/conditionlib_test.php
mod/assign/settings.php
mod/resource/lib.php
mod/scorm/datamodels/aicclib.php
repository/coursefiles/lib.php

index dc65e31..2cd66f7 100644 (file)
@@ -425,7 +425,8 @@ if (isset($maturity)) {
                 exit(1);
             }
         } else {
-            cli_error(get_string('maturitycorewarning', 'admin'));
+            cli_problem(get_string('maturitycorewarning', 'admin', $maturitylevel));
+            cli_error(get_string('maturityallowunstable', 'admin'));
         }
     }
 }
index 3b51f41..6bc3642 100644 (file)
@@ -34,8 +34,8 @@ if ($DB->get_dbfamily() !== 'mysql') {
 }
 
 // now get cli options
-list($options, $unrecognized) = cli_get_params(array('help'=>false, 'list'=>false, 'engine'=>false),
-                                               array('h'=>'help', 'l'=>'list'));
+list($options, $unrecognized) = cli_get_params(array('help'=>false, 'list'=>false, 'engine'=>false, 'available'=>false),
+                                               array('h'=>'help', 'l'=>'list', 'a'=>'available'));
 
 if ($unrecognized) {
     $unrecognized = implode("\n  ", $unrecognized);
@@ -52,6 +52,7 @@ and does not support transactions.
 Options:
 --engine=ENGINE       Convert MySQL tables to different engine
 -l, --list            Show table information
+-a, --available       Show list of available engines
 -h, --help            Print out this help
 
 Example:
@@ -59,7 +60,11 @@ Example:
 ";
 
 if (!empty($options['engine'])) {
+    $engines = mysql_get_engines();
     $engine = clean_param($options['engine'], PARAM_ALPHA);
+    if (!isset($engines[strtoupper($engine)])) {
+        cli_error("Error: engine '$engine' is not available on this server!");
+    }
 
     echo "Converting tables to '$engine' for $CFG->wwwroot:\n";
     $prefix = $DB->get_prefix();
@@ -68,9 +73,11 @@ if (!empty($options['engine'])) {
     $rs = $DB->get_recordset_sql($sql);
     $converted = 0;
     $skipped   = 0;
+    $errors    = 0;
     foreach ($rs as $table) {
-        if ($table->engine === $engine) {
-            echo str_pad($table->name, 40). " - NO CONVERSION NEEDED\n";
+        if (strtoupper($table->engine) === strtoupper($engine)) {
+            $newengine = mysql_get_table_engine($table->name);
+            echo str_pad($table->name, 40). " - NO CONVERSION NEEDED ($newengine)\n";
             $skipped++;
             continue;
         }
@@ -78,16 +85,22 @@ if (!empty($options['engine'])) {
 
         try {
             $DB->change_database_structure("ALTER TABLE {$table->name} ENGINE = $engine");
+            $newengine = mysql_get_table_engine($table->name);
+            if (strtoupper($newengine) !== strtoupper($engine)) {
+                echo "ERROR ($newengine)\n";
+                $errors++;
+                continue;
+            }
+            echo "DONE ($newengine)\n";
+            $converted++;
         } catch (moodle_exception $e) {
             echo $e->getMessage()."\n";
-            $skipped++;
+            $errors++;
             continue;
         }
-        echo "DONE\n";
-        $converted++;
     }
     $rs->close();
-    echo "Converted: $converted, skipped: $skipped\n";
+    echo "Converted: $converted, skipped: $skipped, errors: $errors\n";
     exit(0); // success
 
 } else if (!empty($options['list'])) {
@@ -115,7 +128,53 @@ if (!empty($options['engine'])) {
     }
     exit(0); // success
 
+} else if (!empty($options['available'])) {
+    echo "List of available MySQL engines for $CFG->wwwroot:\n";
+    $engines = mysql_get_engines();
+    foreach ($engines as $engine) {
+        echo " $engine\n";
+    }
+    die;
+
 } else {
     echo $help;
     die;
 }
+
+
+
+// ========== Some functions ==============
+
+function mysql_get_engines() {
+    global $DB;
+
+    $sql = "SHOW Engines";
+    $rs = $DB->get_recordset_sql($sql);
+    $engines = array();
+    foreach ($rs as $engine) {
+        if (strtoupper($engine->support) !== 'YES' and strtoupper($engine->support) !== 'DEFAULT') {
+            continue;
+        }
+        $engines[strtoupper($engine->engine)] = $engine->engine;
+        if (strtoupper($engine->support) === 'DEFAULT') {
+            $engines[strtoupper($engine->engine)] .= ' (default)';
+        }
+    }
+    $rs->close();
+
+    return $engines;
+}
+
+function mysql_get_table_engine($tablename) {
+    global $DB;
+
+    $engine = null;
+    $sql = "SHOW TABLE STATUS WHERE Name = '$tablename'"; // no special chars expected here
+    $rs = $DB->get_recordset_sql($sql);
+    if ($rs->valid()) {
+        $record = $rs->current();
+        $engine = $record->engine;
+    }
+    $rs->close();
+    return $engine;
+}
index 33e66cc..e552d4e 100644 (file)
@@ -132,7 +132,8 @@ if (isset($maturity)) {
             echo get_string('morehelp') . ': ' . get_docs_url('admin/versions') . PHP_EOL;
             cli_separator();
         } else {
-            cli_error(get_string('maturitycorewarning', 'admin', $maturitylevel));
+            cli_problem(get_string('maturitycorewarning', 'admin', $maturitylevel));
+            cli_error(get_string('maturityallowunstable', 'admin'));
         }
     }
 }
index 9c87eec..bd2a531 100644 (file)
@@ -121,7 +121,7 @@ function bloglevelupgrade_entries($blogentries, $forum, $cm, $groupid=-1) {
         $discussion->groupid = $groupid;
         $message = '';
 
-        $discussionid = forum_add_discussion($discussion, null, $message);
+        $discussionid = forum_add_discussion($discussion, null, $message, $blogentry->userid);
 
         // Copy file attachment records
         $fs = get_file_storage();
index d1be602..a2fa948 100644 (file)
@@ -1414,7 +1414,7 @@ class backup_final_files_structure_step extends backup_structure_step {
 
         $file->set_source_sql("SELECT f.*, r.repositoryid, r.reference
                                  FROM {files} f
-                                 JOIN {files_reference} r
+                                 LEFT JOIN {files_reference} r
                                       ON r.id = f.referencefileid
                                  JOIN {backup_ids_temp} bi
                                       ON f.id = bi.itemid
index ee98987..68c1752 100644 (file)
@@ -420,7 +420,7 @@ abstract class backup_controller_dbops extends backup_dbops {
 
         $sql = "SELECT count(r.repositoryid)
                   FROM {files} f
-                  JOIN {files_reference} r
+                  LEFT JOIN {files_reference} r
                        ON r.id = f.referencefileid
                   JOIN {backup_ids_temp} bi
                        ON f.id = bi.itemid
index 184449a..8152990 100644 (file)
@@ -242,7 +242,6 @@ function calendar_get_mini($courses, $groups, $users, $cal_month = false, $cal_y
     $days_title = calendar_get_days();
 
     $summary = get_string('calendarheading', 'calendar', userdate(make_timestamp($y, $m), get_string('strftimemonthyear')));
-    $summary = get_string('tabledata', 'access', $summary);
     $content .= '<table class="minicalendar calendartable" summary="'.$summary.'">'; // Begin table
     $content .= '<tr class="weekdays">'; // Header row: day names
 
index f2af45a..3354f1c 100644 (file)
@@ -53,5 +53,7 @@ if ($course->numsections >= 0) {
     $DB->update_record('course', $course);
 }
 
+$url = course_get_url($course);
+$url->set_anchor('changenumsections');
 // Redirect to where we were..
-redirect(course_get_url($course));
+redirect($url);
index fb59c38..f0dd91f 100644 (file)
@@ -56,6 +56,21 @@ abstract class format_section_renderer_base extends plugin_renderer_base {
      */
     abstract protected function page_title();
 
+    /**
+     * Generate the section title
+     *
+     * @param stdClass $section The course_section entry from DB
+     * @param stdClass $course The course entry from DB
+     * @return string HTML to output.
+     */
+    public function section_title($section, $course) {
+        $title = get_section_name($course, $section);
+        if ($section->section != 0 && $course->coursedisplay == COURSE_DISPLAY_MULTIPAGE) {
+            $title = html_writer::link(course_get_url($course, $section->section), $title);
+        }
+        return $title;
+    }
+
     /**
      * Generate the content to displayed on the right part of a section
      * before course modules are included
@@ -106,7 +121,7 @@ abstract class format_section_renderer_base extends plugin_renderer_base {
      *
      * @param stdClass $section The course_section entry from DB
      * @param stdClass $course The course entry from DB
-     * @param bool $onsectionpage true if being printed on a section page
+     * @param bool $onsectionpage true if being printed on a single-section page
      * @return string HTML to output.
      */
     protected function section_header($section, $course, $onsectionpage) {
@@ -115,7 +130,6 @@ abstract class format_section_renderer_base extends plugin_renderer_base {
         $o = '';
         $currenttext = '';
         $sectionstyle = '';
-        $linktitle = false;
 
         if ($section->section != 0) {
             // Only in the non-general sections.
@@ -124,7 +138,6 @@ abstract class format_section_renderer_base extends plugin_renderer_base {
             } else if ($this->is_section_current($section, $course)) {
                 $sectionstyle = ' current';
             }
-            $linktitle = ($course->coursedisplay == COURSE_DISPLAY_MULTIPAGE);
         }
 
         $o.= html_writer::start_tag('li', array('id' => 'section-'.$section->section,
@@ -138,11 +151,7 @@ abstract class format_section_renderer_base extends plugin_renderer_base {
         $o.= html_writer::start_tag('div', array('class' => 'content'));
 
         if (!$onsectionpage) {
-            $title = get_section_name($course, $section);
-            if ($linktitle) {
-                $title = html_writer::link(course_get_url($course, $section->section), $title);
-            }
-            $o.= $this->output->heading($title, 3, 'sectionname');
+            $o.= $this->output->heading($this->section_title($section, $course), 3, 'sectionname');
         }
 
         $o.= html_writer::start_tag('div', array('class' => 'summary'));
@@ -506,7 +515,7 @@ abstract class format_section_renderer_base extends plugin_renderer_base {
         $completioninfo = new completion_info($course);
         echo $completioninfo->display_help_icon();
 
-        print_section($course, $thissection, $mods, $modnamesused, true);
+        print_section($course, $thissection, $mods, $modnamesused, true, '100%', false, true);
         if ($PAGE->user_is_editing()) {
             print_section_add_menus($course, $displaysection, $modnames);
         }
@@ -624,7 +633,7 @@ abstract class format_section_renderer_base extends plugin_renderer_base {
 
             echo $this->end_section_list();
 
-            echo html_writer::start_tag('div', array('class' => 'mdl-right'));
+            echo html_writer::start_tag('div', array('id' => 'changenumsections', 'class' => 'mdl-right'));
 
             // Increase number of sections.
             $straddsection = get_string('increasesections', 'moodle');
index 218492d..71e8797 100644 (file)
@@ -1,4 +1,4 @@
-// Javascript functions for course format
+// Javascript functions for Topics course format
 
 M.course = M.course || {};
 
@@ -36,13 +36,32 @@ M.course.format.get_config = function() {
 M.course.format.swap_sections = function(Y, node1, node2) {
     var CSS = {
         COURSECONTENT : 'course-content',
-        LEFT : 'left',
         SECTIONADDMENUS : 'section_add_menus'
     };
 
     var sectionlist = Y.Node.all('.'+CSS.COURSECONTENT+' '+M.course.format.get_section_selector(Y));
-    // Swap left block
-    sectionlist.item(node1).one('.'+CSS.LEFT).swap(sectionlist.item(node2).one('.'+CSS.LEFT));
     // Swap menus
     sectionlist.item(node1).one('.'+CSS.SECTIONADDMENUS).swap(sectionlist.item(node2).one('.'+CSS.SECTIONADDMENUS));
 }
+
+/**
+ * Process sections after ajax response
+ *
+ * @param {YUI} Y YUI3 instance
+ * @param {array} response ajax response
+ * @param {string} sectionfrom first affected section
+ * @param {string} sectionto last affected section
+ * @return void
+ */
+M.course.format.process_sections = function(Y, sectionlist, response, sectionfrom, sectionto) {
+    var CSS = {
+        SECTIONNAME : 'sectionname'
+    };
+
+    if (response.action == 'move') {
+        // update titles in all affected sections
+        for (var i = sectionfrom; i <= sectionto; i++) {
+            sectionlist.item(i).one('.'+CSS.SECTIONNAME).setContent(response.sectiontitles[i]);
+        }
+    }
+}
index 710abaf..e8632fc 100644 (file)
@@ -80,3 +80,24 @@ function callback_topics_ajax_support() {
     $ajaxsupport->testedbrowsers = array('MSIE' => 6.0, 'Gecko' => 20061111, 'Safari' => 531, 'Chrome' => 6.0);
     return $ajaxsupport;
 }
+
+/**
+ * Callback function to do some action after section move
+ *
+ * @param stdClass $course The course entry from DB
+ * @return array This will be passed in ajax respose.
+ */
+function callback_topics_ajax_section_move($course) {
+    global $COURSE, $PAGE;
+
+    $titles = array();
+    rebuild_course_cache($course->id);
+    $modinfo = get_fast_modinfo($COURSE);
+    $renderer = $PAGE->get_renderer('format_topics');
+    if ($renderer && ($sections = $modinfo->get_section_info_all())) {
+        foreach ($sections as $number => $section) {
+            $titles[$number] = $renderer->section_title($section, $course);
+        }
+    }
+    return array('sectiontitles' => $titles, 'action' => 'move');
+}
index 159f94b..f410e07 100644 (file)
@@ -1,4 +1,4 @@
-// Javascript functions for course format
+// Javascript functions for Weeks course format
 
 M.course = M.course || {};
 
@@ -36,16 +36,32 @@ M.course.format.get_config = function() {
 M.course.format.swap_sections = function(Y, node1, node2) {
     var CSS = {
         COURSECONTENT : 'course-content',
-        LEFT : 'left',
         SECTIONADDMENUS : 'section_add_menus',
-        WEEKDATES: 'sectionname'
     };
 
     var sectionlist = Y.Node.all('.'+CSS.COURSECONTENT+' '+M.course.format.get_section_selector(Y));
-    // Swap left block
-    sectionlist.item(node1).one('.'+CSS.LEFT).swap(sectionlist.item(node2).one('.'+CSS.LEFT));
     // Swap menus
     sectionlist.item(node1).one('.'+CSS.SECTIONADDMENUS).swap(sectionlist.item(node2).one('.'+CSS.SECTIONADDMENUS));
-    // Swap week dates
-    sectionlist.item(node1).one('.'+CSS.WEEKDATES).swap(sectionlist.item(node2).one('.'+CSS.WEEKDATES));
+}
+
+/**
+ * Process sections after ajax response
+ *
+ * @param {YUI} Y YUI3 instance
+ * @param {array} response ajax response
+ * @param {string} sectionfrom first affected section
+ * @param {string} sectionto last affected section
+ * @return void
+ */
+M.course.format.process_sections = function(Y, sectionlist, response, sectionfrom, sectionto) {
+    var CSS = {
+        SECTIONNAME : 'sectionname'
+    };
+
+    if (response.action == 'move') {
+        // update titles in all affected sections
+        for (var i = sectionfrom; i <= sectionto; i++) {
+            sectionlist.item(i).one('.'+CSS.SECTIONNAME).setContent(response.sectiontitles[i]);
+        }
+    }
 }
index 834adda..a1e1ea9 100644 (file)
@@ -117,3 +117,24 @@ function format_weeks_get_section_dates($section, $course) {
 
     return $dates;
 }
+
+/**
+ * Callback function to do some action after section move
+ *
+ * @param stdClass $course The course entry from DB
+ * @return array This will be passed in ajax respose.
+ */
+function callback_weeks_ajax_section_move($course) {
+    global $COURSE, $PAGE;
+
+    $titles = array();
+    rebuild_course_cache($course->id);
+    $modinfo = get_fast_modinfo($COURSE);
+    $renderer = $PAGE->get_renderer('format_weeks');
+    if ($renderer && ($sections = $modinfo->get_section_info_all())) {
+        foreach ($sections as $number => $section) {
+            $titles[$number] = $renderer->section_title($section, $course);
+        }
+    }
+    return array('sectiontitles' => $titles, 'action' => 'move');
+}
index 648f87e..a5566d6 100644 (file)
@@ -1728,7 +1728,7 @@ function print_section($course, $section, $mods, $modnamesused, $absolute=false,
             // see the activity itself, or for staff)
             if (!$mod->uservisible) {
                 echo '<div class="availabilityinfo">'.$mod->availableinfo.'</div>';
-            } else if ($canviewhidden && !empty($CFG->enableavailability)) {
+            } else if ($canviewhidden && !empty($CFG->enableavailability) && $mod->visible) {
                 $ci = new condition_info($mod);
                 $fullinfo = $ci->get_full_information();
                 if($fullinfo) {
index f33ef54..8b31e29 100644 (file)
@@ -221,7 +221,9 @@ if (!empty($activities)) {
                 echo $OUTPUT->spacer(array('height'=>30, 'br'=>true)); // should be done with CSS instead
             }
             echo $OUTPUT->box_start();
-            echo "<h2>$activity->name</h2>";
+            if (!empty($activity->name)) {
+                echo html_writer::tag('h2', $activity->name);
+            }
             $inbox = true;
 
         } else if ($activity->type == 'activity') {
@@ -230,16 +232,17 @@ if (!empty($activities)) {
                 $cm = $modinfo->cms[$activity->cmid];
 
                 if ($cm->visible) {
-                    $linkformat = '';
+                    $class = '';
                 } else {
-                    $linkformat = 'class="dimmed"';
+                    $class = 'dimmed';
                 }
                 $name        = format_string($cm->name);
                 $modfullname = $modnames[$cm->modname];
 
-                $image = "<img src=\"" . $OUTPUT->pix_url('icon', $cm->modname) . "\" class=\"icon\" alt=\"$modfullname\" />";
-                echo "<h3>$image $modfullname".
-                     " <a href=\"$CFG->wwwroot/mod/$cm->modname/view.php?id=$cm->id\" $linkformat>$name</a></h3>";
+                $image = $OUTPUT->pix_icon('icon', $modfullname, $cm->modname, array('class' => 'icon smallicon'));
+                $link = html_writer::link(new moodle_url("/mod/$cm->modname/view.php",
+                            array("id" => $cm->id)), $name, array('class' => $class));
+                echo html_writer::tag('h3', "$image $modfullname $link");
            }
 
         } else {
@@ -269,7 +272,7 @@ if (!empty($activities)) {
 
 } else {
 
-    echo '<h3><center>' . get_string('norecentactivity') . '</center></h3>';
+    echo html_writer::tag('h3', get_string('norecentactivity'), array('class' => 'mdl-align'));
 
 }
 
index 5152563..6efd228 100644 (file)
@@ -89,6 +89,15 @@ switch($requestmethod) {
 
                     case 'move':
                         move_section_to($course, $id, $value);
+                        // See if format wants to do something about it
+                        $libfile = $CFG->dirroot.'/course/format/'.$course->format.'/lib.php';
+                        $functionname = 'callback_'.$course->format.'_ajax_section_move';
+                        if (!function_exists($functionname) && file_exists($libfile)) {
+                            require_once $libfile;
+                        }
+                        if (function_exists($functionname)) {
+                            echo json_encode($functionname($course));
+                        }
                         break;
                 }
                 rebuild_course_cache($course->id);
index 3dbbf0b..b02c362 100644 (file)
@@ -68,6 +68,21 @@ YUI.add('moodle-course-coursebase', function(Y) {
         return null;
     }
 
+   /**
+    * Process sections after ajax response (should be defined in format.js)
+    * If some response is expected, we pass it over to format, as it knows better
+    * hot to process it.
+    *
+    * @param {YUI} Y YUI3 instance
+    * @param {NodeList} list of sections
+    * @param {array} response ajax response
+    * @param {string} sectionfrom first affected section
+    * @param {string} sectionto last affected section
+    * @return void
+    */
+    M.course.format.process_sections = M.course.format.process_sections || function(Y, sectionlist, response, sectionfrom, sectionto) {
+        return null;
+    }
 
    /**
     * Get sections config for this format, for examples see function definition
index a8b293a..080cace 100644 (file)
@@ -179,9 +179,16 @@ YUI.add('moodle-course-dragdrop', function(Y) {
                         lightbox.show();
                     },
                     success: function(tid, response) {
-                        window.setTimeout(function(e) {
-                            lightbox.hide();
-                        }, 250);
+                        // Update section titles, we can't simply swap them as
+                        // they might have custom title
+                        try {
+                            var responsetext = Y.JSON.parse(response.responseText);
+                            if (responsetext.error) {
+                                new M.core.ajaxException(responsetext);
+                            }
+                            M.course.format.process_sections(Y, sectionlist, responsetext, loopstart, loopend);
+                        } catch (e) {}
+
                         // Classic bubble sort algorithm is applied to the section
                         // nodes between original drag node location and the new one.
                         do {
@@ -200,6 +207,11 @@ YUI.add('moodle-course-dragdrop', function(Y) {
                             }
                             loopend = loopend - 1;
                         } while (swapped);
+
+                        // Finally, hide the lightbox
+                        window.setTimeout(function(e) {
+                            lightbox.hide();
+                        }, 250);
                     },
                     failure: function(tid, response) {
                         this.ajax_failure(response);
index b338d42..ee81afc 100644 (file)
@@ -39,8 +39,6 @@ $string['skipa'] = 'Skip {$a}';
 $string['skipblock'] = 'Skip block';
 $string['skipnavigation'] = 'Skip navigation';
 $string['skipto'] = 'Skip to {$a}';
-$string['tabledata'] = 'Data table, {$a}';
-$string['tablelayout'] = 'Layout table, {$a}';
 $string['tocontent'] = 'Skip to main content';
 $string['tonavigation'] = 'Go to navigation';
 $string['youarehere'] = 'You are here';
index 2ac7b1e..82581fe 100644 (file)
@@ -636,6 +636,7 @@ $string['maturity50'] = 'Alpha';
 $string['maturity100'] = 'Beta';
 $string['maturity150'] = 'Release candidate';
 $string['maturity200'] = 'Stable version';
+$string['maturityallowunstable'] = 'Hint: You may want to run this script with --allow-unstable option';
 $string['maturitycoreinfo'] = 'Your site is currently running unstable "{$a}" development code.';
 $string['maturitycorewarning'] = 'The version of Moodle that you are about to install or upgrade to contains
 unstable "{$a}" development code that is not suitable for use on most production
index 9bcd4bb..0d8b3cb 100644 (file)
@@ -69,7 +69,8 @@ class condition_info extends condition_info_base {
      * @param object $cm Moodle course-module object. May have extra fields
      *   ->conditionsgrade, ->conditionscompletion which should come from
      *   get_fast_modinfo. Should have ->availablefrom, ->availableuntil,
-     *   and ->showavailability, ->course; but the only required thing is ->id.
+     *   and ->showavailability, ->course, ->visible; but the only required
+     *   thing is ->id.
      * @param int $expectingmissing Used to control whether or not a developer
      *   debugging message (performance warning) will be displayed if some of
      *   the above data is missing and needs to be retrieved; a
@@ -426,7 +427,8 @@ abstract class condition_info_base {
      * @return array Array of field names
      */
     protected function get_main_table_fields() {
-        return array('id', 'course', 'availablefrom', 'availableuntil', 'showavailability');
+        return array('id', 'course', 'visible',
+                'availablefrom', 'availableuntil', 'showavailability');
     }
 
     /**
@@ -846,6 +848,16 @@ abstract class condition_info_base {
             }
         }
 
+        // If the item is marked as 'not visible' then we don't change the available
+        // flag (visible/available are treated distinctly), but we remove any
+        // availability info. If the item is hidden with the eye icon, it doesn't
+        // make sense to show 'Available from <date>' or similar, because even
+        // when that date arrives it will still not be available unless somebody
+        // toggles the eye icon.
+        if (!$this->item->visible) {
+            $information = '';
+        }
+
         $information = trim($information);
         return $available;
     }
index a5a37a3..2f3ea57 100644 (file)
@@ -505,7 +505,7 @@ class file_info_stored extends file_info {
         if ($this->is_directory()) {
             $filepath = $this->lf->get_filepath();
             $fs = get_file_storage();
-            $storedfiles = $fs->get_area_files($this->context->id, $this->get_component(), $this->lf->get_filearea(), $this->lf->get_itemid(), "");
+            $storedfiles = $fs->get_area_files($this->context->id, $this->get_component(), $this->lf->get_filearea(), $this->lf->get_itemid());
             foreach ($storedfiles as $file) {
                 if (strpos($file->get_filepath(), $filepath) === 0) {
                     $file->delete();
index 302ee9b..7aa8841 100644 (file)
@@ -2287,14 +2287,22 @@ function send_stored_file($stored_file, $lifetime=86400 , $filter=0, $forcedownl
     if (!empty($options['preview'])) {
         // replace the file with its preview
         $fs = get_file_storage();
-        $stored_file = $fs->get_file_preview($stored_file, $options['preview']);
-        if (!$stored_file) {
-            // unable to create a preview of the file
-            send_header_404();
-            die();
+        $preview_file = $fs->get_file_preview($stored_file, $options['preview']);
+        if (!$preview_file) {
+            // unable to create a preview of the file, send its default mime icon instead
+            if ($options['preview'] === 'tinyicon') {
+                $size = 24;
+            } else if ($options['preview'] === 'thumb') {
+                $size = 90;
+            } else {
+                $size = 256;
+            }
+            $fileicon = file_file_icon($stored_file, $size);
+            send_file($CFG->dirroot.'/pix/'.$fileicon.'.png', basename($fileicon).'.png');
         } else {
             // preview images have fixed cache lifetime and they ignore forced download
             // (they are generated by GD and therefore they are considered reasonably safe).
+            $stored_file = $preview_file;
             $lifetime = DAYSECS;
             $filter = 0;
             $forcedownload = false;
index 9f0a3c2..d5ce7c1 100644 (file)
@@ -366,7 +366,7 @@ class file_storage {
      * Returns all files belonging to given repository
      *
      * @param int $repositoryid
-     * @param string $sort
+     * @param string $sort A fragment of SQL to use for sorting
      */
     public function get_external_files($repositoryid, $sort = 'sortorder, itemid, filepath, filename') {
         global $DB;
@@ -374,8 +374,10 @@ class file_storage {
                   FROM {files} f
              LEFT JOIN {files_reference} r
                        ON f.referencefileid = r.id
-                 WHERE r.repositoryid = ?
-              ORDER BY $sort";
+                 WHERE r.repositoryid = ?";
+        if (!empty($sort)) {
+            $sql .= " ORDER BY {$sort}";
+        }
 
         $result = array();
         $filerecords = $DB->get_records_sql($sql, array($repositoryid));
@@ -392,11 +394,11 @@ class file_storage {
      * @param string $component component
      * @param string $filearea file area
      * @param int $itemid item ID or all files if not specified
-     * @param string $sort sort fields
+     * @param string $sort A fragment of SQL to use for sorting
      * @param bool $includedirs whether or not include directories
      * @return array of stored_files indexed by pathanmehash
      */
-    public function get_area_files($contextid, $component, $filearea, $itemid = false, $sort="sortorder, itemid, filepath, filename", $includedirs = true) {
+    public function get_area_files($contextid, $component, $filearea, $itemid = false, $sort = "sortorder, itemid, filepath, filename", $includedirs = true) {
         global $DB;
 
         $conditions = array('contextid'=>$contextid, 'component'=>$component, 'filearea'=>$filearea);
@@ -414,8 +416,10 @@ class file_storage {
                  WHERE f.contextid = :contextid
                        AND f.component = :component
                        AND f.filearea = :filearea
-                       $itemidsql
-              ORDER BY $sort";
+                       $itemidsql";
+        if (!empty($sort)) {
+            $sql .= " ORDER BY {$sort}";
+        }
 
         $result = array();
         $filerecords = $DB->get_records_sql($sql, $conditions);
@@ -489,7 +493,7 @@ class file_storage {
      * @param int $filepath directory path
      * @param bool $recursive include all subdirectories
      * @param bool $includedirs include files and directories
-     * @param string $sort sort fields
+     * @param string $sort A fragment of SQL to use for sorting
      * @return array of stored_files indexed by pathanmehash
      */
     public function get_directory_files($contextid, $component, $filearea, $itemid, $filepath, $recursive = false, $includedirs = true, $sort = "filepath, filename") {
@@ -499,6 +503,8 @@ class file_storage {
             return array();
         }
 
+        $orderby = (!empty($sort)) ? " ORDER BY {$sort}" : '';
+
         if ($recursive) {
 
             $dirs = $includedirs ? "" : "AND filename <> '.'";
@@ -512,7 +518,7 @@ class file_storage {
                            AND ".$DB->sql_substr("f.filepath", 1, $length)." = :filepath
                            AND f.id <> :dirid
                            $dirs
-                  ORDER BY $sort";
+                           $orderby";
             $params = array('contextid'=>$contextid, 'component'=>$component, 'filearea'=>$filearea, 'itemid'=>$itemid, 'filepath'=>$filepath, 'dirid'=>$directory->get_id());
 
             $files = array();
@@ -542,7 +548,7 @@ class file_storage {
                                AND f.itemid = :itemid AND f.filename = '.'
                                AND ".$DB->sql_substr("f.filepath", 1, $length)." = :filepath
                                AND f.id <> :dirid
-                      ORDER BY $sort";
+                               $orderby";
                 $reqlevel = substr_count($filepath, '/') + 1;
                 $filerecords = $DB->get_records_sql($sql, $params);
                 foreach ($filerecords as $filerecord) {
@@ -559,7 +565,7 @@ class file_storage {
                            ON f.referencefileid = r.id
                      WHERE f.contextid = :contextid AND f.component = :component AND f.filearea = :filearea AND f.itemid = :itemid
                            AND f.filepath = :filepath AND f.filename <> '.'
-                  ORDER BY $sort";
+                           $orderby";
 
             $filerecords = $DB->get_records_sql($sql, $params);
             foreach ($filerecords as $filerecord) {
index bf7316a..2e1514c 100644 (file)
@@ -91,6 +91,7 @@ M.form_dndupload.init = function(Y, options) {
             this.maxfiles = options.maxfiles;
             this.maxbytes = options.maxbytes;
             this.itemid = options.itemid;
+            this.author = options.author;
             this.container = this.Y.one('#'+options.containerid);
 
             if (options.filemanager) {
@@ -452,6 +453,9 @@ M.form_dndupload.init = function(Y, options) {
             formdata.append('sesskey', M.cfg.sesskey);
             formdata.append('repo_id', this.repositoryid);
             formdata.append('itemid', this.itemid);
+            if (this.author) {
+                formdata.append('author', this.author);
+            }
             if (this.filemanager) { // Filepickers do not have folders
                 formdata.append('savepath', this.filemanager.currentpath);
             }
index 592dc1c..6627c2a 100644 (file)
@@ -963,6 +963,7 @@ M.form_filemanager.init = function(Y, options) {
         filemanager: manager,
         acceptedtypes: options.accepted_types,
         clientid: options.client_id,
+        author: options.author,
         maxfiles: options.maxfiles,
         maxbytes: options.maxbytes,
         itemid: options.itemid,
index 4b5de33..e372a23 100644 (file)
@@ -47,6 +47,7 @@ M.form_filepicker.init = function(Y, options) {
     var dndoptions = {
         clientid: options.client_id,
         acceptedtypes: options.accepted_types,
+        author: options.author,
         maxfiles: -1,
         maxbytes: options.maxbytes,
         itemid: options.itemid,
index e652a8c..7da6ed6 100644 (file)
@@ -455,6 +455,11 @@ function install_cli_database(array $options, $interactive) {
     set_config('release', $release);
     set_config('branch', $branch);
 
+    if (PHPUNIT_TEST) {
+        // mark as test database as soon as possible
+        set_config('phpunittest', 'na');
+    }
+
     // install all plugins types, local, etc.
     upgrade_noncore(true);
 
index 81727f5..3baf0b5 100644 (file)
@@ -809,7 +809,7 @@ class portfolio_exporter {
      */
     public function get_tempfiles($skipfile='portfolio-export.zip') {
         $fs = get_file_storage();
-        $files = $fs->get_area_files(SYSCONTEXTID, 'portfolio', 'exporter', $this->id, '', false);
+        $files = $fs->get_area_files(SYSCONTEXTID, 'portfolio', 'exporter', $this->id, 'sortorder, itemid, filepath, filename', false);
         if (empty($files)) {
             return array();
         }
index 1a635f3..23cf9e1 100644 (file)
@@ -478,8 +478,21 @@ setup_DB();
 if (PHPUNIT_TEST and !PHPUNIT_UTIL) {
     // make sure tests do not run in parallel
     phpunit_util::acquire_test_lock();
-    // reset DB tables
-    phpunit_util::reset_database();
+    $dbhash = null;
+    try {
+        if ($dbhash = $DB->get_field('config', 'value', array('name'=>'phpunittest'))) {
+            // reset DB tables
+            phpunit_util::reset_database();
+        }
+    } catch (Exception $e) {
+        if ($dbhash) {
+            // we ned to reinit if reset fails
+            $DB->set_field('config', 'value', 'na', array('name'=>'phpunittest'));
+        } else {
+            throw $e;
+        }
+    }
+    unset($dbhash);
 }
 
 // Disable errors for now - needed for installation when debug enabled in config.php
index f35c916..2315916 100644 (file)
@@ -70,7 +70,8 @@ class conditionlib_testcase extends advanced_testcase {
         $this->assertEquals(
             (object)array('id'=>$id,'showavailability'=>1,
                 'availablefrom'=>17,'availableuntil'=>398,'course'=>64,
-                'conditionsgrade'=>array(), 'conditionscompletion'=>array()),
+                'conditionsgrade'=>array(), 'conditionscompletion'=>array(),
+                'visible' => 1),
             $test->get_full_course_module());
 
         // just the course_modules stuff; check it doesn't request that from db
@@ -78,11 +79,13 @@ class conditionlib_testcase extends advanced_testcase {
         $cm->availablefrom=2;
         $cm->availableuntil=74;
         $cm->course=38;
+        $cm->visible = 1;
         $test=new condition_info($cm,CONDITION_MISSING_EXTRATABLE);
         $this->assertEquals(
             (object)array('id'=>$id,'showavailability'=>0,
                 'availablefrom'=>2,'availableuntil'=>74,'course'=>38,
-                'conditionsgrade'=>array(), 'conditionscompletion'=>array()),
+                'conditionsgrade' => array(), 'conditionscompletion' => array(),
+                'visible' => 1),
             $test->get_full_course_module());
 
         // Now let's add some actual grade/completion conditions
@@ -136,7 +139,8 @@ class conditionlib_testcase extends advanced_testcase {
         $this->assertEquals(
                 (object)array('id' => $id, 'showavailability' => 1, 'groupingid' => 13,
                     'availablefrom' => 17, 'availableuntil' => 398, 'course' => 64,
-                    'conditionsgrade' => array(), 'conditionscompletion' => array()),
+                    'conditionsgrade' => array(), 'conditionscompletion' => array(),
+                    'visible' => 1),
                 $test->get_full_section());
 
         // Just the course_sections stuff; check it doesn't request that from db
@@ -146,11 +150,13 @@ class conditionlib_testcase extends advanced_testcase {
         $section->availableuntil = 74;
         $section->course = 38;
         $section->groupingid = 99;
+        $section->visible = 1;
         $test = new condition_info_section($section, CONDITION_MISSING_EXTRATABLE);
         $this->assertEquals(
                 (object)array('id' => $id, 'showavailability' => 0, 'groupingid' => 99,
                     'availablefrom' => 2, 'availableuntil' => 74, 'course' => 38,
-                    'conditionsgrade' => array(), 'conditionscompletion' => array()),
+                    'conditionsgrade' => array(), 'conditionscompletion' => array(),
+                    'visible' => 1),
                 $test->get_full_section());
 
         // Now let's add some actual grade/completion conditions
index 7860b64..187bc9a 100644 (file)
@@ -36,6 +36,9 @@ $ADMIN->add('assignmentplugins', new admin_category('assignfeedbackplugins',
 $ADMIN->add('assignfeedbackplugins', new assign_admin_page_manage_assign_plugins('assignfeedback'));
 
 
+assign_plugin_manager::add_admin_assign_plugin_settings('assignsubmission', $ADMIN, $settings, $module);
+assign_plugin_manager::add_admin_assign_plugin_settings('assignfeedback', $ADMIN, $settings, $module);
+
 if ($ADMIN->fulltree) {
     $menu = array();
     foreach (get_plugin_list('assignfeedback') as $type => $notused) {
@@ -54,4 +57,4 @@ if ($ADMIN->fulltree) {
                    new lang_string('configshowrecentsubmissions', 'assign'), 0));
     $settings->add(new admin_setting_configcheckbox('assign/submissionreceipts',
                    get_string('sendsubmissionreceipts', 'mod_assign'), get_string('sendsubmissionreceipts_help', 'mod_assign'), 1));
-}
\ No newline at end of file
+}
index 179c507..d5f2081 100644 (file)
@@ -500,7 +500,7 @@ function mod_resource_dndupload_handle($uploadinfo) {
     $data = new stdClass();
     $data->course = $uploadinfo->course->id;
     $data->name = $uploadinfo->displayname;
-    $data->intro = '<p>'.$uploadinfo->displayname.'</p>';
+    $data->intro = '';
     $data->introformat = FORMAT_HTML;
     $data->coursemodule = $uploadinfo->coursemodule;
     $data->files = $uploadinfo->draftitemid;
@@ -512,6 +512,8 @@ function mod_resource_dndupload_handle($uploadinfo) {
     $data->popupwidth = $config->popupwidth;
     $data->printheading = $config->printheading;
     $data->printintro = $config->printintro;
+    $data->showsize = $config->showsize;
+    $data->showtype = $config->showtype;
 
     return resource_add_instance($data, null);
 }
index c926c12..43369fe 100644 (file)
@@ -121,7 +121,7 @@ function scorm_parse_aicc($scorm) {
 
     $fs = get_file_storage();
 
-    $files = $fs->get_area_files($context->id, 'mod_scorm', 'content', 0, '', false);
+    $files = $fs->get_area_files($context->id, 'mod_scorm', 'content', 0, 'sortorder, itemid, filepath, filename', false);
 
     $version = 'AICC';
     $ids = array();
index 2f1e8fe..16353b8 100644 (file)
@@ -186,7 +186,7 @@ class repository_coursefiles extends repository {
     }
 
     public function supported_returntypes() {
-        return (FILE_INTERNAL | FILE_EXTERNAL | FILE_REFERENCE);
+        return (FILE_INTERNAL | FILE_REFERENCE);
     }
 
     public static function get_type_option_names() {