Merge branch 'MDL-52821-master-fix' of github.com:xow/moodle
authorAndrew Nicols <andrew@nicols.co.uk>
Wed, 16 Mar 2016 05:53:57 +0000 (13:53 +0800)
committerAndrew Nicols <andrew@nicols.co.uk>
Wed, 16 Mar 2016 05:53:57 +0000 (13:53 +0800)
42 files changed:
blocks/site_main_menu/block_site_main_menu.php
blocks/site_main_menu/styles.css
blocks/site_main_menu/tests/behat/edit_activities.feature [new file with mode: 0644]
blocks/social_activities/block_social_activities.php
blocks/social_activities/tests/behat/edit_activities.feature [new file with mode: 0644]
cohort/classes/output/cohortidnumber.php [new file with mode: 0644]
cohort/classes/output/cohortname.php [new file with mode: 0644]
cohort/index.php
cohort/lib.php
cohort/tests/behat/add_cohort.feature
course/classes/output/course_module_name.php [new file with mode: 0644]
course/lib.php
course/renderer.php
course/rest.php
course/tests/behat/activities_edit_name.feature [new file with mode: 0644]
course/tests/behat/behat_course.php
course/tests/courselib_test.php
course/yui/build/moodle-course-toolboxes/moodle-course-toolboxes-debug.js
course/yui/build/moodle-course-toolboxes/moodle-course-toolboxes-min.js
course/yui/build/moodle-course-toolboxes/moodle-course-toolboxes.js
course/yui/src/toolboxes/js/resource.js
course/yui/src/toolboxes/js/toolbox.js
lang/en/cache.php
lang/en/cohort.php
lang/en/moodle.php
lib/accesslib.php
lib/db/caches.php
lib/ddl/database_manager.php
lib/ddl/sql_generator.php
lib/deprecatedlib.php
lib/dml/moodle_database.php
lib/dml/mssql_native_moodle_database.php
lib/dml/mysqli_native_moodle_database.php
lib/dml/oci_native_moodle_database.php
lib/dml/pdo_moodle_database.php
lib/dml/pgsql_native_moodle_database.php
lib/dml/sqlite3_pdo_moodle_database.php
lib/dml/sqlsrv_native_moodle_database.php
lib/dml/tests/dml_test.php
repository/wikimedia/wikimedia.php
search/engine/solr/tests/engine_test.php
theme/upgrade.txt

index cd26cbc..866047d 100644 (file)
@@ -51,6 +51,7 @@ class block_site_main_menu extends block_list {
         require_once($CFG->dirroot.'/course/lib.php');
         $context = context_course::instance($course->id);
         $isediting = $this->page->user_is_editing() && has_capability('moodle/course:manageactivities', $context);
+        $courserenderer = $this->page->get_renderer('core', 'course');
 
 /// extra fast view mode
         if (!$isediting) {
@@ -69,32 +70,18 @@ class block_site_main_menu extends block_list {
                     }
 
                     if (!empty($cm->url)) {
-                        $attrs = array();
-                        $attrs['title'] = $cm->modfullname;
-                        $attrs['class'] = $cm->extraclasses . ' activity-action';
-                        if ($cm->onclick) {
-                            // Get on-click attribute value if specified and decode the onclick - it
-                            // has already been encoded for display.
-                            $attrs['onclick'] = htmlspecialchars_decode($cm->onclick);
-                        }
-                        if (!$cm->visible) {
-                            $attrs['class'] .= ' dimmed';
-                        }
-                        $icon = '<img src="' . $cm->get_icon_url() . '" class="icon" alt="" />';
-                        $content = html_writer::link($cm->url, $icon . $cm->get_formatted_name(), $attrs);
+                        $content = html_writer::div($courserenderer->course_section_cm_name($cm), 'activity');
                     } else {
                         $content = $cm->get_formatted_content(array('overflowdiv' => true, 'noclean' => true));
                     }
 
-                    $this->content->items[] = $indent.html_writer::div($content, 'main-menu-content');
+                    $this->content->items[] = $indent . $content;
                 }
             }
             return $this->content;
         }
 
         // Slow & hacky editing mode.
-        /** @var core_course_renderer $courserenderer */
-        $courserenderer = $this->page->get_renderer('core', 'course');
         $ismoving = ismoving($course->id);
         course_create_sections_if_missing($course, 0);
         $modinfo = get_fast_modinfo($course);
@@ -104,11 +91,9 @@ class block_site_main_menu extends block_list {
             $strmovehere = get_string('movehere');
             $strmovefull = strip_tags(get_string('movefull', '', "'$USER->activitycopyname'"));
             $strcancel= get_string('cancel');
-            $stractivityclipboard = $USER->activitycopyname;
         } else {
             $strmove = get_string('move');
         }
-        $editbuttons = '';
 
         if ($ismoving) {
             $this->content->icons[] = '<img src="'.$OUTPUT->pix_url('t/move') . '" class="iconsmall" alt="" />';
@@ -116,7 +101,6 @@ class block_site_main_menu extends block_list {
         }
 
         if (!empty($modinfo->sections[0])) {
-            $options = array('overflowdiv'=>true);
             foreach ($modinfo->sections[0] as $modnumber) {
                 $mod = $modinfo->cms[$modnumber];
                 if (!$mod->uservisible) {
@@ -153,27 +137,12 @@ class block_site_main_menu extends block_list {
                     } else {
                         $indent = '';
                     }
-                    $url = $mod->url;
-                    if (!$url) {
+                    if (!$mod->url) {
                         $content = $mod->get_formatted_content(array('overflowdiv' => true, 'noclean' => true));
                     } else {
-                        //Accessibility: incidental image - should be empty Alt text
-                        $attrs = array();
-                        $attrs['title'] = $mod->modfullname;
-                        $attrs['class'] = $mod->extraclasses . ' activity-action';
-                        if ($mod->onclick) {
-                            // Get on-click attribute value if specified and decode the onclick - it
-                            // has already been encoded for display.
-                            $attrs['onclick'] = htmlspecialchars_decode($mod->onclick);
-                        }
-                        if (!$mod->visible) {
-                            $attrs['class'] .= ' dimmed';
-                        }
-
-                        $icon = '<img src="' . $mod->get_icon_url() . '" class="icon" alt="" />';
-                        $content = html_writer::link($url, $icon . $mod->get_formatted_name(), $attrs);
+                        $content = html_writer::div($courserenderer->course_section_cm_name($mod), ' activity');
                     }
-                    $this->content->items[] = $indent.html_writer::div($content . $editbuttons, 'main-menu-content');
+                    $this->content->items[] = $indent. $content . $editbuttons;
                 }
             }
         }
index 0e15ab7..f437bae 100644 (file)
@@ -6,5 +6,4 @@
 .block_site_main_menu .footer { margin-top: 1em; }
 .block_site_main_menu .section_add_menus noscript div { display: inline;}
 .block_site_main_menu .mod-indent,
-.block_site_main_menu .main-menu-content { display: table-cell; }
-.block_site_main_menu .main-menu-content > .activity-action { display: block; }
+.block_site_main_menu .activity { display: table-cell; }
diff --git a/blocks/site_main_menu/tests/behat/edit_activities.feature b/blocks/site_main_menu/tests/behat/edit_activities.feature
new file mode 100644 (file)
index 0000000..b94a0ad
--- /dev/null
@@ -0,0 +1,21 @@
+@block @block_main_menu
+Feature: Edit activities in main menu block
+  In order to use main menu block
+  As an admin
+  I need to add and edit activities there
+
+  @javascript
+  Scenario: Edit name of acitivity in-place in site main menu block
+    Given I log in as "admin"
+    And I am on site homepage
+    And I navigate to "Turn editing on" node in "Front page settings"
+    When I add a "Forum" to section "0" and I fill the form with:
+      | Forum name | My forum name |
+    And I click on "Edit title" "link" in the "//.[contains(@class,'block_site_main_menu')]//li[contains(.,'My forum name')]" "xpath_element"
+    And I set the field "New name for activity My forum name" to "New forum name"
+    And I press key "13" in the field "New name for activity My forum name"
+    Then I should not see "My forum name"
+    And I should see "New forum name"
+    And I follow "New forum name"
+    And I should not see "My forum name"
+    And I should see "New forum name"
index 6c6971b..2553413 100644 (file)
@@ -48,6 +48,7 @@ class block_social_activities extends block_list {
         }
 
         $course = $this->page->course;
+        $courserenderer = $this->page->get_renderer('core', 'course');
 
         require_once($CFG->dirroot.'/course/lib.php');
 
@@ -58,25 +59,18 @@ class block_social_activities extends block_list {
 /// extra fast view mode
         if (!$isediting) {
             if (!empty($modinfo->sections[0])) {
-                $options = array('overflowdiv'=>true);
                 foreach($modinfo->sections[0] as $cmid) {
                     $cm = $modinfo->cms[$cmid];
                     if (!$cm->uservisible) {
                         continue;
                     }
 
-                    $content = $cm->get_formatted_content(array('overflowdiv' => true, 'noclean' => true));
-                    $instancename = $cm->get_formatted_name();
-
-                    if (!($url = $cm->url)) {
+                    if (!$cm->url) {
+                        $content = $cm->get_formatted_content(array('overflowdiv' => true, 'noclean' => true));
                         $this->content->items[] = $content;
                         $this->content->icons[] = '';
                     } else {
-                        $linkcss = $cm->visible ? '' : ' class="dimmed" ';
-                        //Accessibility: incidental image - should be empty Alt text
-                        $icon = '<img src="' . $cm->get_icon_url() . '" class="icon" alt="" />&nbsp;';
-                        $this->content->items[] = '<a title="'.$cm->modplural.'" '.$linkcss.' '.$cm->extra.
-                                ' href="' . $url . '">' . $icon . $instancename . '</a>';
+                        $this->content->items[] = html_writer::div($courserenderer->course_section_cm_name($cm), 'activity');
                     }
                 }
             }
@@ -85,21 +79,16 @@ class block_social_activities extends block_list {
 
 
         // Slow & hacky editing mode.
-        /** @var core_course_renderer $courserenderer */
-        $courserenderer = $this->page->get_renderer('core', 'course');
         $ismoving = ismoving($course->id);
-        $modinfo = get_fast_modinfo($course);
         $section = $modinfo->get_section_info(0);
 
         if ($ismoving) {
             $strmovehere = get_string('movehere');
             $strmovefull = strip_tags(get_string('movefull', '', "'$USER->activitycopyname'"));
             $strcancel= get_string('cancel');
-            $stractivityclipboard = $USER->activitycopyname;
         } else {
             $strmove = get_string('move');
         }
-        $editbuttons = '';
 
         if ($ismoving) {
             $this->content->icons[] = '&nbsp;<img align="bottom" src="'.$OUTPUT->pix_url('t/move') . '" class="iconsmall" alt="" />';
@@ -107,7 +96,6 @@ class block_social_activities extends block_list {
         }
 
         if (!empty($modinfo->sections[0])) {
-            $options = array('overflowdiv'=>true);
             foreach ($modinfo->sections[0] as $modnumber) {
                 $mod = $modinfo->cms[$modnumber];
                 if (!$mod->uservisible) {
@@ -139,19 +127,13 @@ class block_social_activities extends block_list {
                             '<img style="height:16px; width:80px; border:0px" src="'.$OUTPUT->pix_url('movehere') . '" alt="'.$strmovehere.'" /></a>';
                         $this->content->icons[] = '';
                     }
-                    $content = $mod->get_formatted_content(array('overflowdiv' => true, 'noclean' => true));
-                    $instancename = $mod->get_formatted_name();
-
-                    $linkcss = $mod->visible ? '' : ' class="dimmed" ';
-
-                    if (!($url = $mod->url)) {
+                    if (!$mod->url) {
+                        $content = $mod->get_formatted_content(array('overflowdiv' => true, 'noclean' => true));
                         $this->content->items[] = $content . $editbuttons;
                         $this->content->icons[] = '';
                     } else {
-                        //Accessibility: incidental image - should be empty Alt text
-                        $icon = '<img src="' . $mod->get_icon_url() . '" class="icon" alt="" />&nbsp;';
-                        $this->content->items[] = '<a title="' . $mod->modfullname . '" ' . $linkcss . ' ' . $mod->extra .
-                            ' href="' . $url . '">' . $icon . $instancename . '</a>' . $editbuttons;
+                        $this->content->items[] = html_writer::div($courserenderer->course_section_cm_name($mod), 'activity') .
+                            $editbuttons;
                     }
                 }
             }
diff --git a/blocks/social_activities/tests/behat/edit_activities.feature b/blocks/social_activities/tests/behat/edit_activities.feature
new file mode 100644 (file)
index 0000000..1db7a7f
--- /dev/null
@@ -0,0 +1,31 @@
+@block @block_social_activities
+Feature: Edit activities in social activities block
+  In order to use social activities block
+  As a teacher
+  I need to add and edit activities there
+
+  @javascript
+  Scenario: Edit name of acitivity in-place in social activities block
+    Given the following "courses" exist:
+      | fullname | shortname | format |
+      | Course 1 | C1        | social |
+    And the following "users" exist:
+      | username | firstname | lastname |
+      | user1 | User | One |
+    And the following "course enrolments" exist:
+      | user | course | role |
+      | user1 | C1 | editingteacher |
+    Given I log in as "user1"
+    And I follow "Course 1"
+    And I turn editing mode on
+    And I set the field "Add an activity to section 'section 0'" to "Forum"
+    And I set the field "Forum name" to "My forum name"
+    And I press "Save and return to course"
+    And I click on "Edit title" "link" in the "//.[contains(@class,'block_social_activities')]//li[contains(.,'My forum name')]" "xpath_element"
+    And I set the field "New name for activity My forum name" to "New forum name"
+    And I press key "13" in the field "New name for activity My forum name"
+    Then I should not see "My forum name" in the "Social activities" "block"
+    And I should see "New forum name"
+    And I follow "New forum name"
+    And I should not see "My forum name"
+    And I should see "New forum name"
diff --git a/cohort/classes/output/cohortidnumber.php b/cohort/classes/output/cohortidnumber.php
new file mode 100644 (file)
index 0000000..5628917
--- /dev/null
@@ -0,0 +1,70 @@
+<?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/>.
+
+/**
+ * Contains class core_cohort\output\cohortidnumber
+ *
+ * @package   core_cohort
+ * @copyright 2016 Marina Glancy
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace core_cohort\output;
+
+use lang_string;
+
+/**
+ * Class to prepare a cohort idnumber for display.
+ *
+ * @package   core_cohort
+ * @copyright 2016 Marina Glancy
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class cohortidnumber extends \core\output\inplace_editable {
+    /**
+     * Constructor.
+     *
+     * @param stdClass $cohort
+     */
+    public function __construct($cohort) {
+        $cohortcontext = \context::instance_by_id($cohort->contextid);
+        $editable = has_capability('moodle/cohort:manage', $cohortcontext);
+        $displayvalue = s($cohort->idnumber); // All idnumbers are plain text.
+        parent::__construct('core_cohort', 'cohortidnumber', $cohort->id, $editable,
+            $displayvalue,
+            $cohort->idnumber,
+            new lang_string('editcohortidnumber', 'cohort'),
+            new lang_string('newidnumberfor', 'cohort', $displayvalue));
+    }
+
+    /**
+     * Updates cohort name and returns instance of this object
+     *
+     * @param int $cohortid
+     * @param string $newvalue
+     * @return static
+     */
+    public static function update($cohortid, $newvalue) {
+        global $DB;
+        $cohort = $DB->get_record('cohort', array('id' => $cohortid), '*', MUST_EXIST);
+        $cohortcontext = \context::instance_by_id($cohort->contextid);
+        require_capability('moodle/cohort:manage', $cohortcontext);
+        $record = (object)array('id' => $cohort->id, 'idnumber' => $newvalue, 'contextid' => $cohort->contextid);
+        cohort_update_cohort($record);
+        $cohort->idnumber = $newvalue;
+        return new static($cohort);
+    }
+}
diff --git a/cohort/classes/output/cohortname.php b/cohort/classes/output/cohortname.php
new file mode 100644 (file)
index 0000000..7c74809
--- /dev/null
@@ -0,0 +1,73 @@
+<?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/>.
+
+/**
+ * Contains class core_cohort\output\cohortname
+ *
+ * @package   core_cohort
+ * @copyright 2016 Marina Glancy
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace core_cohort\output;
+
+use lang_string;
+
+/**
+ * Class to prepare a cohort name for display.
+ *
+ * @package   core_cohort
+ * @copyright 2016 Marina Glancy
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class cohortname extends \core\output\inplace_editable {
+    /**
+     * Constructor.
+     *
+     * @param stdClass $cohort
+     */
+    public function __construct($cohort) {
+        $cohortcontext = \context::instance_by_id($cohort->contextid);
+        $editable = has_capability('moodle/cohort:manage', $cohortcontext);
+        $displayvalue = format_string($cohort->name, true, array('context' => $cohortcontext));
+        parent::__construct('core_cohort', 'cohortname', $cohort->id, $editable,
+            $displayvalue,
+            $cohort->name,
+            new lang_string('editcohortname', 'cohort'),
+            new lang_string('newnamefor', 'cohort', $displayvalue));
+    }
+
+    /**
+     * Updates cohort name and returns instance of this object
+     *
+     * @param int $cohortid
+     * @param string $newvalue
+     * @return static
+     */
+    public static function update($cohortid, $newvalue) {
+        global $DB;
+        $cohort = $DB->get_record('cohort', array('id' => $cohortid), '*', MUST_EXIST);
+        $cohortcontext = \context::instance_by_id($cohort->contextid);
+        require_capability('moodle/cohort:manage', $cohortcontext);
+        $newvalue = clean_param($newvalue, PARAM_TEXT);
+        if (strval($newvalue) !== '') {
+            $record = (object)array('id' => $cohort->id, 'name' => $newvalue, 'contextid' => $cohort->contextid);
+            cohort_update_cohort($record);
+            $cohort->name = $newvalue;
+        }
+        return new static($cohort);
+    }
+}
index 923e464..7352bb8 100644 (file)
@@ -132,8 +132,10 @@ foreach($cohorts['cohorts'] as $cohort) {
             $line[] = $cohortcontext->get_context_name(false);
         }
     }
-    $line[] = format_string($cohort->name);
-    $line[] = s($cohort->idnumber); // All idnumbers are plain text.
+    $tmpl = new \core_cohort\output\cohortname($cohort);
+    $line[] = $OUTPUT->render_from_template('core/inplace_editable', $tmpl->export_for_template($OUTPUT));
+    $tmpl = new \core_cohort\output\cohortidnumber($cohort);
+    $line[] = $OUTPUT->render_from_template('core/inplace_editable', $tmpl->export_for_template($OUTPUT));
     $line[] = format_text($cohort->description, $cohort->descriptionformat);
 
     $line[] = $DB->count_records('cohort_members', array('cohortid'=>$cohort->id));
index 5c51578..de015a4 100644 (file)
@@ -516,3 +516,19 @@ function cohort_edit_controls(context $context, moodle_url $currenturl) {
     }
     return null;
 }
+
+/**
+ * Implements callback inplace_editable() allowing to edit values in-place
+ *
+ * @param string $itemtype
+ * @param int $itemid
+ * @param mixed $newvalue
+ * @return \core\output\inplace_editable
+ */
+function core_cohort_inplace_editable($itemtype, $itemid, $newvalue) {
+    if ($itemtype === 'cohortname') {
+        return \core_cohort\output\cohortname::update($itemid, $newvalue);
+    } else if ($itemtype === 'cohortidnumber') {
+        return \core_cohort\output\cohortidnumber::update($itemid, $newvalue);
+    }
+}
index f6b5512..e6983b2 100644 (file)
@@ -56,3 +56,14 @@ Feature: Add cohorts of users
     And the "Current users" select box should contain "Third User (third@example.com)"
     And the "Current users" select box should contain "Forth User (forth@example.com)"
     And the "Current users" select box should not contain "First User (first@example.com)"
+
+  @javascript
+  Scenario: Edit cohort name in-place
+    When I follow "Cohorts"
+    And I click on "Edit cohort name" "link" in the "Test cohort name" "table_row"
+    And I set the field "New name for cohort Test cohort name" to "Students cohort"
+    And I press key "13" in the field "New name for cohort Test cohort name"
+    Then I should not see "Test cohort name"
+    And I should see "Students cohort"
+    And I follow "Cohorts"
+    And I should see "Students cohort"
diff --git a/course/classes/output/course_module_name.php b/course/classes/output/course_module_name.php
new file mode 100644 (file)
index 0000000..e286e55
--- /dev/null
@@ -0,0 +1,100 @@
+<?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/>.
+
+/**
+ * Contains class core_tag\output\course_module_name
+ *
+ * @package   core_course
+ * @copyright 2016 Marina Glancy
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace core_course\output;
+
+use context_module;
+use lang_string;
+use cm_info;
+
+/**
+ * Class to prepare a course module name for display and in-place editing
+ *
+ * @package   core_course
+ * @copyright 2016 Marina Glancy
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class course_module_name extends \core\output\inplace_editable {
+
+    /** @var cm_info */
+    protected $cm;
+
+    /** @var array */
+    protected $displayoptions;
+
+    /**
+     * Constructor.
+     *
+     * @param cm_info $cm
+     * @param bool $editable
+     * @param array $displayoptions
+     */
+    public function __construct(cm_info $cm, $editable, $displayoptions = array()) {
+        $this->cm = $cm;
+        $this->displayoptions = $displayoptions;
+        $value = $cm->name;
+        $edithint = new lang_string('edittitle');
+        $editlabel = new lang_string('newactivityname', '', $cm->get_formatted_name());
+        $editable = $editable && has_capability('moodle/course:manageactivities',
+                    context_module::instance($cm->id));
+        parent::__construct(
+            'core_course', 'activityname', $cm->id, $editable, $value, $value, $edithint, $editlabel);
+    }
+
+    /**
+     * Export this data so it can be used as the context for a mustache template (core/inplace_editable).
+     *
+     * @param renderer_base $output typically, the renderer that's calling this function
+     * @return array data context for a mustache template
+     */
+    public function export_for_template(\renderer_base $output) {
+        global $PAGE;
+        $courserenderer = $PAGE->get_renderer('core', 'course');
+        $this->displayvalue = $courserenderer->course_section_cm_name_title($this->cm, $this->displayoptions);
+        if (strval($this->displayvalue) === '') {
+            $this->editable = false;
+        }
+        return parent::export_for_template($output);
+    }
+
+    /**
+     * Updates course module name
+     *
+     * @param int $itemid course module id
+     * @param string $newvalue new name
+     * @return static
+     */
+    public static function update($itemid, $newvalue) {
+        list($course, $cm) = get_course_and_cm_from_cmid($itemid);
+        $context = context_module::instance($cm->id);
+        // Check access.
+        require_login($course, false, $cm, true, true);
+        require_capability('moodle/course:manageactivities', $context);
+        // Update value.
+        set_coursemodule_name($cm->id, $newvalue);
+        // Return instance.
+        $cm = get_fast_modinfo($course)->get_cm($cm->id);
+        return new static($cm, true);
+    }
+}
index 6afaae0..59b69e7 100644 (file)
@@ -1605,6 +1605,50 @@ function set_coursemodule_visible($id, $visible) {
     return true;
 }
 
+/**
+ * Changes the course module name
+ *
+ * @param int $id course module id
+ * @param string $name new value for a name
+ * @return bool whether a change was made
+ */
+function set_coursemodule_name($id, $name) {
+    global $CFG, $DB;
+    require_once($CFG->libdir . '/gradelib.php');
+
+    $cm = get_coursemodule_from_id('', $id, 0, false, MUST_EXIST);
+
+    $module = new \stdClass();
+    $module->id = $cm->instance;
+
+    // Escape strings as they would be by mform.
+    if (!empty($CFG->formatstringstriptags)) {
+        $module->name = clean_param($name, PARAM_TEXT);
+    } else {
+        $module->name = clean_param($name, PARAM_CLEANHTML);
+    }
+    if ($module->name === $cm->name || strval($module->name) === '') {
+        return false;
+    }
+    if (\core_text::strlen($module->name) > 255) {
+        throw new \moodle_exception('maximumchars', 'moodle', '', 255);
+    }
+
+    $module->timemodified = time();
+    $DB->update_record($cm->modname, $module);
+    $cm->name = $module->name;
+    \core\event\course_module_updated::create_from_cm($cm)->trigger();
+    rebuild_course_cache($cm->course, true);
+
+    // Attempt to update the grade item if relevant.
+    $grademodule = $DB->get_record($cm->modname, array('id' => $cm->instance));
+    $grademodule->cmidnumber = $cm->idnumber;
+    $grademodule->modname = $cm->modname;
+    grade_update_mod_grades($grademodule);
+
+    return true;
+}
+
 /**
  * This function will handle the whole deletion process of a module. This includes calling
  * the modules delete_instance function, deleting files, events, grades, conditional data,
@@ -2241,53 +2285,6 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
     return $actions;
 }
 
-/**
- * Returns the rename action.
- *
- * @param cm_info $mod The module to produce editing buttons for
- * @param int $sr The section to link back to (used for creating the links)
- * @return The markup for the rename action, or an empty string if not available.
- */
-function course_get_cm_rename_action(cm_info $mod, $sr = null) {
-    global $COURSE, $OUTPUT;
-
-    static $str;
-    static $baseurl;
-
-    $modcontext = context_module::instance($mod->id);
-    $hasmanageactivities = has_capability('moodle/course:manageactivities', $modcontext);
-
-    if (!isset($str)) {
-        $str = get_strings(array('edittitle'));
-    }
-
-    if (!isset($baseurl)) {
-        $baseurl = new moodle_url('/course/mod.php', array('sesskey' => sesskey()));
-    }
-
-    if ($sr !== null) {
-        $baseurl->param('sr', $sr);
-    }
-
-    // AJAX edit title.
-    if ($mod->has_view() && $hasmanageactivities && course_ajax_enabled($COURSE) &&
-                (($mod->course == $COURSE->id) || ($mod->course == SITEID))) {
-        // we will not display link if we are on some other-course page (where we should not see this module anyway)
-        return html_writer::span(
-            html_writer::link(
-                new moodle_url($baseurl, array('update' => $mod->id)),
-                $OUTPUT->pix_icon('t/editstring', '', 'moodle', array('class' => 'iconsmall visibleifjs', 'title' => '')),
-                array(
-                    'class' => 'editing_title',
-                    'data-action' => 'edittitle',
-                    'title' => $str->edittitle,
-                )
-            )
-        );
-    }
-    return '';
-}
-
 /**
  * Returns the move action.
  *
@@ -3897,3 +3894,17 @@ function course_get_tagged_courses($tag, $exclusivemode = false, $fromctx = 0, $
     return new core_tag\output\tagindex($tag, 'core', 'course', $content,
             $exclusivemode, $fromctx, $ctx, $rec, $page, $totalpages);
 }
+
+/**
+ * Implements callback inplace_editable() allowing to edit values in-place
+ *
+ * @param string $itemtype
+ * @param int $itemid
+ * @param mixed $newvalue
+ * @return \core\output\inplace_editable
+ */
+function core_course_inplace_editable($itemtype, $itemid, $newvalue) {
+    if ($itemtype === 'activityname') {
+        return \core_course\output\course_module_name::update($itemid, $newvalue);
+    }
+}
index b71d488..617f4e8 100644 (file)
@@ -733,10 +733,34 @@ class core_course_renderer extends plugin_renderer_base {
      * @return string
      */
     public function course_section_cm_name(cm_info $mod, $displayoptions = array()) {
-        global $CFG;
+        if ((!$mod->uservisible && empty($mod->availableinfo)) || !$mod->url) {
+            // Nothing to be displayed to the user.
+            return '';
+        }
+
+        // Render element that allows to edit activity name inline. It calls {@link course_section_cm_name_title()}
+        // to get the display title of the activity.
+        $tmpl = new \core_course\output\course_module_name($mod, $this->page->user_is_editing(), $displayoptions);
+        return $this->output->render_from_template('core/inplace_editable', $tmpl->export_for_template($this->output));
+    }
+
+    /**
+     * Renders html to display a name with the link to the course module on a course page
+     *
+     * If module is unavailable for user but still needs to be displayed
+     * in the list, just the name is returned without a link
+     *
+     * Note, that for course modules that never have separate pages (i.e. labels)
+     * this function return an empty string
+     *
+     * @param cm_info $mod
+     * @param array $displayoptions
+     * @return string
+     */
+    public function course_section_cm_name_title(cm_info $mod, $displayoptions = array()) {
         $output = '';
         if (!$mod->uservisible && empty($mod->availableinfo)) {
-            // nothing to be displayed to the user
+            // Nothing to be displayed to the user.
             return $output;
         }
         $url = $mod->url;
@@ -985,10 +1009,6 @@ class core_course_renderer extends plugin_renderer_base {
             $output .= $cmname;
 
 
-            if ($this->page->user_is_editing()) {
-                $output .= ' ' . course_get_cm_rename_action($mod, $sectionreturn);
-            }
-
             // Module can put text after the link (e.g. forum unread)
             $output .= $mod->afterlink;
 
index 675f367..42b45ce 100644 (file)
@@ -150,49 +150,6 @@ switch($requestmethod) {
                         $isvisible = moveto_module($cm, $section, $beforemod);
                         echo json_encode(array('visible' => (bool) $isvisible));
                         break;
-                    case 'gettitle':
-                        require_capability('moodle/course:manageactivities', $modcontext);
-                        $cm = get_coursemodule_from_id('', $id, 0, false, MUST_EXIST);
-                        $module = new stdClass();
-                        $module->id = $cm->instance;
-
-                        // Don't pass edit strings through multilang filters - we need the entire string
-                        echo json_encode(array('instancename' => $cm->name));
-                        break;
-                    case 'updatetitle':
-                        require_capability('moodle/course:manageactivities', $modcontext);
-                        require_once($CFG->libdir . '/gradelib.php');
-                        $cm = get_coursemodule_from_id('', $id, 0, false, MUST_EXIST);
-                        $module = new stdClass();
-                        $module->id = $cm->instance;
-
-                        // Escape strings as they would be by mform
-                        if (!empty($CFG->formatstringstriptags)) {
-                            $module->name = clean_param($title, PARAM_TEXT);
-                        } else {
-                            $module->name = clean_param($title, PARAM_CLEANHTML);
-                        }
-
-                        if (strval($module->name) !== '') {
-                            $DB->update_record($cm->modname, $module);
-                            $cm->name = $module->name;
-                            \core\event\course_module_updated::create_from_cm($cm, $modcontext)->trigger();
-                            rebuild_course_cache($cm->course);
-                        } else {
-                            $module->name = $cm->name;
-                        }
-
-                        // Attempt to update the grade item if relevant
-                        $grademodule = $DB->get_record($cm->modname, array('id' => $cm->instance));
-                        $grademodule->cmidnumber = $cm->idnumber;
-                        $grademodule->modname = $cm->modname;
-                        grade_update_mod_grades($grademodule);
-
-                        // We need to return strings after they've been through filters for multilang
-                        $stringoptions = new stdClass;
-                        $stringoptions->context = $coursecontext;
-                        echo json_encode(array('instancename' => html_entity_decode(format_string($module->name, true,  $stringoptions))));
-                        break;
                 }
                 break;
 
diff --git a/course/tests/behat/activities_edit_name.feature b/course/tests/behat/activities_edit_name.feature
new file mode 100644 (file)
index 0000000..2d53b7c
--- /dev/null
@@ -0,0 +1,44 @@
+@core @core_course
+Feature: Edit activity name in-place
+  In order to quickly edit activity name
+  As a teacher
+  I need to use inplace editing
+
+  @javascript
+  Scenario: Edit activity name in-place
+    Given the following "users" exist:
+      | username | firstname | lastname | email |
+      | teacher1 | Teacher | 1 | teacher1@example.com |
+    And the following "courses" exist:
+      | fullname | shortname | format |
+      | Course 1 | C1 | topics |
+    And the following "course enrolments" exist:
+      | user | course | role |
+      | teacher1 | C1 | editingteacher |
+    When I log in as "teacher1"
+    And I follow "Course 1"
+    And I turn editing mode on
+    And I add a "Forum" to section "1" and I fill the form with:
+      | Forum name | Test forum name |
+      | Description | Test forum description |
+    # Rename activity
+    And I click on "Edit title" "link" in the "//div[contains(@class,'activityinstance') and contains(.,'Test forum name')]" "xpath_element"
+    And I set the field "New name for activity Test forum name" to "Good news"
+    And I press key "13" in the field "New name for activity Test forum name"
+    Then I should not see "Test forum name" in the ".course-content" "css_element"
+    And "New name for activity Test forum name" "field" should not exist
+    And I should see "Good news"
+    And I follow "Course 1"
+    And I should see "Good news"
+    And I should not see "Test forum name"
+    # Cancel renaming
+    And I click on "Edit title" "link" in the "//div[contains(@class,'activityinstance') and contains(.,'Good news')]" "xpath_element"
+    And I set the field "New name for activity Good news" to "Terrible news"
+    And I press key "27" in the field "New name for activity Good news"
+    And "New name for activity Good news" "field" should not exist
+    And I should see "Good news"
+    And I should not see "Terrible news"
+    And I follow "Course 1"
+    And I should see "Good news"
+    And I should not see "Terrible news"
+    And I log out
index 09ee8d4..d16aa1a 100644 (file)
@@ -467,7 +467,7 @@ class behat_course extends behat_base {
                 foreach ($activities as $activity) {
                     // Dimmed.
                     $this->find('xpath', "//div[contains(concat(' ', normalize-space(@class), ' '), ' activityinstance ')]" .
-                        "/a[contains(concat(' ', normalize-space(@class), ' '), ' dimmed ')]", $dimmedexception, $activity);
+                        "//a[contains(concat(' ', normalize-space(@class), ' '), ' dimmed ')]", $dimmedexception, $activity);
                 }
             }
         } else {
index 0e4e9de..aa50329 100644 (file)
@@ -2779,4 +2779,34 @@ class core_course_courselib_testcase extends advanced_testcase {
         $this->assertNull($DB->get_field('course_modules', 'availability',
                 array('id' => $label->cmid)));
     }
+
+    /**
+     * Test update_inplace_editable()
+     */
+    public function test_update_module_name_inplace() {
+        global $CFG, $DB, $PAGE;
+        require_once($CFG->dirroot . '/lib/external/externallib.php');
+
+        $this->setUser($this->getDataGenerator()->create_user());
+
+        $this->resetAfterTest(true);
+        $course = $this->getDataGenerator()->create_course();
+        $forum = self::getDataGenerator()->create_module('forum', array('course' => $course->id, 'name' => 'forum name'));
+
+        // Call service for core_course component without necessary permissions.
+        try {
+            core_external::update_inplace_editable('core_course', 'activityname', $forum->cmid, 'New forum name');
+            $this->fail('Exception expected');
+        } catch (moodle_exception $e) {
+            $this->assertEquals('Course or activity not accessible. (Not enrolled)',
+                $e->getMessage());
+        }
+
+        // Change to admin user and make sure that cm name can be updated using web service update_inplace_editable().
+        $this->setAdminUser();
+        $res = core_external::update_inplace_editable('core_course', 'activityname', $forum->cmid, 'New forum name');
+        $res = external_api::clean_returnvalue(core_external::update_inplace_editable_returns(), $res);
+        $this->assertEquals('New forum name', $res['value']);
+        $this->assertEquals('New forum name', $DB->get_field('forum', 'name', array('id' => $forum->id)));
+    }
 }
index 03d72a6..75ef3b8 100644 (file)
Binary files a/course/yui/build/moodle-course-toolboxes/moodle-course-toolboxes-debug.js and b/course/yui/build/moodle-course-toolboxes/moodle-course-toolboxes-debug.js differ
index ec2b8fa..290b316 100644 (file)
Binary files a/course/yui/build/moodle-course-toolboxes/moodle-course-toolboxes-min.js and b/course/yui/build/moodle-course-toolboxes/moodle-course-toolboxes-min.js differ
index 03d72a6..75ef3b8 100644 (file)
Binary files a/course/yui/build/moodle-course-toolboxes/moodle-course-toolboxes.js and b/course/yui/build/moodle-course-toolboxes/moodle-course-toolboxes.js differ
index 578630e..3bb4e60 100644 (file)
@@ -52,17 +52,6 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
      */
     GROUPS_VISIBLE: 2,
 
-    /**
-     * An Array of events added when editing a title.
-     * These should all be detached when editing is complete.
-     *
-     * @property edittitleevents
-     * @protected
-     * @type Array
-     * @protected
-     */
-    edittitleevents: [],
-
     /**
      * Initialize the resource toolbox
      *
@@ -113,10 +102,6 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
 
         // Switch based upon the action and do the desired thing.
         switch (action) {
-            case 'edittitle':
-                // The user wishes to edit the title of the event.
-                this.edit_title(ev, node, activity, action);
-                break;
             case 'moveleft':
             case 'moveright':
                 // The user changing the indent of the activity.
@@ -429,11 +414,13 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
                 dimarea.addClass(toggleclass);
                 // We need to toggle dimming on the description too.
                 activity.all(SELECTOR.CONTENTAFTERLINK).addClass(CSS.DIMMEDTEXT);
+                activity.all(SELECTOR.GROUPINGLABEL).addClass(CSS.DIMMEDTEXT);
             } else {
                 // Change the UI.
                 dimarea.removeClass(toggleclass);
                 // We need to toggle dimming on the description too.
                 activity.all(SELECTOR.CONTENTAFTERLINK).removeClass(CSS.DIMMEDTEXT);
+                activity.all(SELECTOR.GROUPINGLABEL).removeClass(CSS.DIMMEDTEXT);
             }
         }
         // Toggle availablity info for conditional activities.
@@ -510,172 +497,6 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
         return this;
     },
 
-    /**
-     * Edit the title for the resource
-     *
-     * @method edit_title
-     * @protected
-     * @param {EventFacade} ev The event that was fired.
-     * @param {Node} button The button that triggered this action.
-     * @param {Node} activity The activity node that this action will be performed on.
-     * @param {String} action The action that has been requested.
-     * @chainable
-     */
-    edit_title: function(ev, button, activity) {
-        // Get the element we're working on
-        var activityid = Y.Moodle.core_course.util.cm.getId(activity),
-            instancename  = activity.one(SELECTOR.INSTANCENAME),
-            instance = activity.one(SELECTOR.ACTIVITYINSTANCE),
-            currenttitle = instancename.get('firstChild'),
-            oldtitle = currenttitle.get('data'),
-            titletext = oldtitle,
-            thisevent,
-            anchor = instancename.ancestor('a'),// Grab the anchor so that we can swap it with the edit form.
-            data = {
-                'class': 'resource',
-                'field': 'gettitle',
-                'id': activityid
-            };
-
-        // Prevent the default actions.
-        ev.preventDefault();
-
-        this.send_request(data, null, function(response) {
-            if (M.core.actionmenu && M.core.actionmenu.instance) {
-                M.core.actionmenu.instance.hideMenu(ev);
-            }
-
-            // Try to retrieve the existing string from the server
-            if (response.instancename) {
-                titletext = response.instancename;
-            }
-
-            // Create the editor and submit button
-            var editform = Y.Node.create('<form action="#" />');
-            var editinstructions = Y.Node.create('<span class="'+CSS.EDITINSTRUCTIONS+'" id="id_editinstructions" />')
-                .set('innerHTML', M.util.get_string('edittitleinstructions', 'moodle'));
-            var editor = Y.Node.create('<input name="title" type="text" class="'+CSS.TITLEEDITOR+'" />').setAttrs({
-                'value': titletext,
-                'autocomplete': 'off',
-                'aria-describedby': 'id_editinstructions',
-                'maxLength': '255'
-            });
-
-            // Clear the existing content and put the editor in
-            editform.appendChild(activity.one(SELECTOR.ACTIVITYICON).cloneNode());
-            editform.appendChild(editor);
-            editform.setData('anchor', anchor);
-            instance.insert(editinstructions, 'before');
-            anchor.replace(editform);
-
-            // Force the editing instruction to match the mod-indent position.
-            var padside = 'left';
-            if (window.right_to_left()) {
-                padside = 'right';
-            }
-
-            // We hide various components whilst editing:
-            activity.addClass(CSS.EDITINGTITLE);
-
-            // Focus and select the editor text
-            editor.focus().select();
-
-            // Cancel the edit if we lose focus or the escape key is pressed.
-            thisevent = editor.on('blur', this.edit_title_cancel, this, activity, false);
-            this.edittitleevents.push(thisevent);
-            thisevent = editor.on('key', this.edit_title_cancel, 'esc', this, activity, true);
-            this.edittitleevents.push(thisevent);
-
-            // Handle form submission.
-            thisevent = editform.on('submit', this.edit_title_submit, this, activity, oldtitle);
-            this.edittitleevents.push(thisevent);
-        });
-        return this;
-    },
-
-    /**
-     * Handles the submit event when editing the activity or resources title.
-     *
-     * @method edit_title_submit
-     * @protected
-     * @param {EventFacade} ev The event that triggered this.
-     * @param {Node} activity The activity whose title we are altering.
-     * @param {String} originaltitle The original title the activity or resource had.
-     */
-    edit_title_submit: function(ev, activity, originaltitle) {
-        // We don't actually want to submit anything
-        ev.preventDefault();
-
-        var newtitle = Y.Lang.trim(activity.one(SELECTOR.ACTIVITYFORM + ' ' + SELECTOR.ACTIVITYTITLE).get('value'));
-        this.edit_title_clear(activity);
-        var spinner = this.add_spinner(activity);
-        if (newtitle !== null && newtitle !== "" && newtitle !== originaltitle) {
-            var data = {
-                'class': 'resource',
-                'field': 'updatetitle',
-                'title': newtitle,
-                'id': Y.Moodle.core_course.util.cm.getId(activity)
-            };
-            this.send_request(data, spinner, function(response) {
-                if (response.instancename) {
-                    activity.one(SELECTOR.INSTANCENAME).setContent(response.instancename);
-                }
-            });
-        }
-    },
-
-    /**
-     * Handles the cancel event when editing the activity or resources title.
-     *
-     * @method edit_title_cancel
-     * @protected
-     * @param {EventFacade} ev The event that triggered this.
-     * @param {Node} activity The activity whose title we are altering.
-     * @param {Boolean} preventdefault If true we should prevent the default action from occuring.
-     */
-    edit_title_cancel: function(ev, activity, preventdefault) {
-        if (preventdefault) {
-            ev.preventDefault();
-        }
-        this.edit_title_clear(activity);
-    },
-
-    /**
-     * Handles clearing the editing UI and returning things to the original state they were in.
-     *
-     * @method edit_title_clear
-     * @protected
-     * @param {Node} activity  The activity whose title we were altering.
-     */
-    edit_title_clear: function(activity) {
-        // Detach all listen events to prevent duplicate triggers
-        new Y.EventHandle(this.edittitleevents).detach();
-
-        var editform = activity.one(SELECTOR.ACTIVITYFORM),
-            instructions = activity.one('#id_editinstructions');
-        if (editform) {
-            editform.replace(editform.getData('anchor'));
-        }
-        if (instructions) {
-            instructions.remove();
-        }
-
-        // Remove the editing class again to revert the display.
-        activity.removeClass(CSS.EDITINGTITLE);
-
-        // Refocus the link which was clicked originally so the user can continue using keyboard nav.
-        Y.later(100, this, function() {
-            activity.one(SELECTOR.EDITTITLE).focus();
-        });
-
-        // TODO MDL-50768 This hack is to keep Behat happy until they release a version of
-        // MinkSelenium2Driver that fixes
-        // https://github.com/Behat/MinkSelenium2Driver/issues/80.
-        if (!Y.one('input[name=title]')) {
-            Y.one('body').append('<input type="text" name="title" style="display: none">');
-        }
-    },
-
     /**
      * Set the visibility of the specified resource to match the visible parameter.
      *
index 7fd7b3b..e3f6c8a 100644 (file)
@@ -17,31 +17,28 @@ var CSS = {
         DIMCLASS : 'dimmed',
         DIMMEDTEXT : 'dimmed_text',
         EDITINSTRUCTIONS : 'editinstructions',
-        EDITINGTITLE: 'editor_displayed',
         HIDE : 'hide',
         MODINDENTCOUNT : 'mod-indent-',
         MODINDENTHUGE : 'mod-indent-huge',
         MODULEIDPREFIX : 'module-',
         SECTIONHIDDENCLASS : 'hidden',
         SECTIONIDPREFIX : 'section-',
-        SHOW : 'editing_show',
-        TITLEEDITOR : 'titleeditor'
+        SHOW : 'editing_show'
     },
     // The CSS selectors we use.
     SELECTOR = {
         ACTIONAREA: '.actions',
         ACTIONLINKTEXT : '.actionlinktext',
-        ACTIVITYACTION : 'a.cm-edit-action[data-action], a.editing_title',
-        ACTIVITYFORM : '.' + CSS.ACTIVITYINSTANCE + ' form',
+        ACTIVITYACTION : 'a.cm-edit-action[data-action]',
         ACTIVITYICON : 'img.activityicon',
         ACTIVITYINSTANCE : '.' + CSS.ACTIVITYINSTANCE,
-        ACTIVITYLINK: '.' + CSS.ACTIVITYINSTANCE + ' > a',
+        ACTIVITYLINK: '.' + CSS.ACTIVITYINSTANCE + ' > a, .'+ CSS.ACTIVITYINSTANCE +
+            ' > span[data-inplaceeditable] > a:not([data-inplaceeditablelink])',
         ACTIVITYLI : 'li.activity',
-        ACTIVITYTITLE : 'input[name=title]',
         COMMANDSPAN : '.commands',
         CONTENTAFTERLINK : 'div.contentafterlink',
         CONTENTWITHOUTLINK : 'div.contentwithoutlink',
-        EDITTITLE: 'a.editing_title',
+        GROUPINGLABEL: '.' + CSS.ACTIVITYINSTANCE + ' .groupinglabel',
         HIDE : 'a.editing_hide',
         HIGHLIGHT : 'a.editing_highlight',
         INSTANCENAME : 'span.instancename',
index a8005ae..327da65 100644 (file)
@@ -63,6 +63,7 @@ $string['cachedef_search_results'] = 'Search results user data';
 $string['cachedef_grade_categories'] = 'Grade category queries';
 $string['cachedef_string'] = 'Language string cache';
 $string['cachedef_tags'] = 'Tags collections and areas';
+$string['cachedef_temp_tables'] = 'Temporary tables cache';
 $string['cachedef_userselections'] = 'Data used to persist user selections throughout Moodle';
 $string['cachedef_yuimodules'] = 'YUI Module definitions';
 $string['cachelock_file_default'] = 'Default file locking';
index 7b1dc38..3aa114e 100644 (file)
@@ -50,6 +50,8 @@ $string['description'] = 'Description';
 $string['displayedrows'] = '{$a->displayed} rows displayed out of {$a->total}.';
 $string['duplicateidnumber'] = 'Cohort with the same ID number already exists';
 $string['editcohort'] = 'Edit cohort';
+$string['editcohortidnumber'] = 'Edit cohort ID';
+$string['editcohortname'] = 'Edit cohort name';
 $string['eventcohortcreated'] = 'Cohort created';
 $string['eventcohortdeleted'] = 'Cohort deleted';
 $string['eventcohortmemberadded'] = 'User added to a cohort';
@@ -61,6 +63,8 @@ $string['memberscount'] = 'Cohort size';
 $string['name'] = 'Name';
 $string['namecolumnmissing'] = 'There is something wrong with the format of the CSV file. Please check that it includes column names.';
 $string['namefieldempty'] = 'Field name can not be empty';
+$string['newnamefor'] = 'New name for cohort {$a}';
+$string['newidnumberfor'] = 'New idnumber for cohort {$a}';
 $string['nocomponent'] = 'Created manually';
 $string['potusers'] = 'Potential users';
 $string['potusersmatching'] = 'Potential matching users';
index 13641d5..53c98f4 100644 (file)
@@ -1228,6 +1228,7 @@ $string['never'] = 'Never';
 $string['neverdeletelogs'] = 'Never delete logs';
 $string['new'] = 'New';
 $string['newaccount'] = 'New account';
+$string['newactivityname'] = 'New name for activity {$a}';
 $string['newcourse'] = 'New course';
 $string['newpassword'] = 'New password';
 $string['newpassword_help'] = 'Enter a new password or leave blank to keep current password.';
index ae3936d..32362d1 100644 (file)
@@ -4213,6 +4213,8 @@ function get_role_users($roleid, context $context, $parent = false, $fields = ''
     $fieldsarray = preg_split('/,\s*/', $fields);
     $addedfields = array();
     foreach ($sortarray as $sortfield) {
+        // Throw away any additional arguments to the sort (e.g. ASC/DESC).
+        list ($sortfield) = explode(' ', $sortfield);
         if (!in_array($sortfield, $fieldsarray)) {
             $fieldsarray[] = $sortfield;
             $addedfields[] = $sortfield;
index f9b0bd6..6dbdc1e 100644 (file)
@@ -276,4 +276,11 @@ $definitions = array(
         'mode' => cache_store::MODE_REQUEST,
         'simplekeys' => true,
     ),
+
+    // Store temporary tables information.
+    'temp_tables' => array(
+        'mode' => cache_store::MODE_REQUEST,
+        'simplekeys' => true,
+        'simpledata' => true
+    )
 );
index a909f33..aa01e3c 100644 (file)
@@ -70,10 +70,11 @@ class database_manager {
      * This function will execute an array of SQL commands.
      *
      * @param string[] $sqlarr Array of sql statements to execute.
+     * @param array|null $tablenames an array of xmldb table names affected by this request.
      * @throws ddl_change_structure_exception This exception is thrown if any error is found.
      */
-    protected function execute_sql_arr(array $sqlarr) {
-        $this->mdb->change_database_structure($sqlarr);
+    protected function execute_sql_arr(array $sqlarr, $tablenames = null) {
+        $this->mdb->change_database_structure($sqlarr, $tablenames);
     }
 
     /**
@@ -107,6 +108,12 @@ class database_manager {
     public function reset_sequence($table) {
         if (!is_string($table) and !($table instanceof xmldb_table)) {
             throw new ddl_exception('ddlunknownerror', NULL, 'incorrect table parameter!');
+        } else {
+            if ($table instanceof xmldb_table) {
+                $tablename = $table->getName();
+            } else {
+                $tablename = $table;
+            }
         }
 
         // Do not test if table exists because it is slow
@@ -115,7 +122,7 @@ class database_manager {
             throw new ddl_exception('ddlunknownerror', null, 'table reset sequence sql not generated');
         }
 
-        $this->execute_sql_arr($sqlarr);
+        $this->execute_sql_arr($sqlarr, array($tablename));
     }
 
     /**
@@ -322,8 +329,7 @@ class database_manager {
         if (!$sqlarr = $this->generator->getDropTableSQL($xmldb_table)) {
             throw new ddl_exception('ddlunknownerror', null, 'table drop sql not generated');
         }
-
-        $this->execute_sql_arr($sqlarr);
+        $this->execute_sql_arr($sqlarr, array($xmldb_table->getName()));
     }
 
     /**
@@ -409,7 +415,14 @@ class database_manager {
         if (!$sqlarr = $this->generator->getCreateStructureSQL($xmldb_structure)) {
             return; // nothing to do
         }
-        $this->execute_sql_arr($sqlarr);
+
+        $tablenames = array();
+        foreach ($xmldb_structure as $xmldb_table) {
+            if ($xmldb_table instanceof xmldb_table) {
+                $tablenames[] = $xmldb_table->getName();
+            }
+        }
+        $this->execute_sql_arr($sqlarr, $tablenames);
     }
 
     /**
@@ -428,7 +441,7 @@ class database_manager {
         if (!$sqlarr = $this->generator->getCreateTableSQL($xmldb_table)) {
             throw new ddl_exception('ddlunknownerror', null, 'table create sql not generated');
         }
-        $this->execute_sql_arr($sqlarr);
+        $this->execute_sql_arr($sqlarr, array($xmldb_table->getName()));
     }
 
     /**
@@ -451,8 +464,7 @@ class database_manager {
         if (!$sqlarr = $this->generator->getCreateTempTableSQL($xmldb_table)) {
             throw new ddl_exception('ddlunknownerror', null, 'temp table create sql not generated');
         }
-
-        $this->execute_sql_arr($sqlarr);
+        $this->execute_sql_arr($sqlarr, array($xmldb_table->getName()));
     }
 
     /**
@@ -530,7 +542,7 @@ class database_manager {
         if (!$sqlarr = $this->generator->getAddFieldSQL($xmldb_table, $xmldb_field)) {
             throw new ddl_exception('ddlunknownerror', null, 'addfield sql not generated');
         }
-        $this->execute_sql_arr($sqlarr);
+        $this->execute_sql_arr($sqlarr, array($xmldb_table->getName()));
     }
 
     /**
@@ -555,7 +567,7 @@ class database_manager {
             throw new ddl_exception('ddlunknownerror', null, 'drop_field sql not generated');
         }
 
-        $this->execute_sql_arr($sqlarr);
+        $this->execute_sql_arr($sqlarr, array($xmldb_table->getName()));
     }
 
     /**
@@ -580,7 +592,7 @@ class database_manager {
             return; // probably nothing to do
         }
 
-        $this->execute_sql_arr($sqlarr);
+        $this->execute_sql_arr($sqlarr, array($xmldb_table->getName()));
     }
 
     /**
@@ -643,7 +655,7 @@ class database_manager {
             return; //Empty array = nothing to do = no error
         }
 
-        $this->execute_sql_arr($sqlarr);
+        $this->execute_sql_arr($sqlarr, array($xmldb_table->getName()));
     }
 
     /**
@@ -687,7 +699,7 @@ class database_manager {
             return; //Empty array = nothing to do = no error
         }
 
-        $this->execute_sql_arr($sqlarr);
+        $this->execute_sql_arr($sqlarr, array($xmldb_table->getName()));
     }
 
     /**
@@ -741,7 +753,7 @@ class database_manager {
             return; //Empty array = nothing to do = no error
         }
 
-        $this->execute_sql_arr($sqlarr);
+        $this->execute_sql_arr($sqlarr, array($xmldb_table->getName()));
     }
 
     /**
@@ -760,7 +772,7 @@ class database_manager {
             return; //Empty array = nothing to do = no error
         }
 
-        $this->execute_sql_arr($sqlarr);
+        $this->execute_sql_arr($sqlarr, array($xmldb_table->getName()));
     }
 
     /**
@@ -784,7 +796,7 @@ class database_manager {
             throw new ddl_exception('ddlunknownerror', null, 'Some DBs do not support key renaming (MySQL, PostgreSQL, MsSQL). Rename skipped');
         }
 
-        $this->execute_sql_arr($sqlarr);
+        $this->execute_sql_arr($sqlarr, array($xmldb_table->getName()));
     }
 
     /**
@@ -811,7 +823,7 @@ class database_manager {
             throw new ddl_exception('ddlunknownerror', null, 'add_index sql not generated');
         }
 
-        $this->execute_sql_arr($sqlarr);
+        $this->execute_sql_arr($sqlarr, array($xmldb_table->getName()));
     }
 
     /**
@@ -838,7 +850,7 @@ class database_manager {
             throw new ddl_exception('ddlunknownerror', null, 'drop_index sql not generated');
         }
 
-        $this->execute_sql_arr($sqlarr);
+        $this->execute_sql_arr($sqlarr, array($xmldb_table->getName()));
     }
 
     /**
@@ -870,7 +882,7 @@ class database_manager {
             throw new ddl_exception('ddlunknownerror', null, 'Some DBs do not support index renaming (MySQL). Rename skipped');
         }
 
-        $this->execute_sql_arr($sqlarr);
+        $this->execute_sql_arr($sqlarr, array($xmldb_table->getName()));
     }
 
     /**
index 8e50fe1..356fb71 100644 (file)
@@ -226,9 +226,12 @@ abstract class sql_generator {
             $tablename = $table->getName();
         }
 
+        if ($this->temptables->is_temptable($tablename)) {
+            return true;
+        }
+
         // Get all tables in moodle database.
         $tables = $this->mdb->get_tables();
-
         return isset($tables[$tablename]);
     }
 
index 5b806b1..b787c16 100644 (file)
@@ -4408,3 +4408,54 @@ function get_clam_error_code($returncode) {
     $antivirus = \core\antivirus\manager::get_antivirus('clamav');
     return $antivirus->get_clam_error_code($returncode);
 }
+
+/**
+ * Returns the rename action.
+ *
+ * @deprecated since 3.1
+ * @param cm_info $mod The module to produce editing buttons for
+ * @param int $sr The section to link back to (used for creating the links)
+ * @return The markup for the rename action, or an empty string if not available.
+ */
+function course_get_cm_rename_action(cm_info $mod, $sr = null) {
+    global $COURSE, $OUTPUT;
+
+    static $str;
+    static $baseurl;
+
+    debugging('Function course_get_cm_rename_action() is deprecated. Please use inplace_editable ' .
+        'https://docs.moodle.org/dev/Inplace_editable', DEBUG_DEVELOPER);
+
+    $modcontext = context_module::instance($mod->id);
+    $hasmanageactivities = has_capability('moodle/course:manageactivities', $modcontext);
+
+    if (!isset($str)) {
+        $str = get_strings(array('edittitle'));
+    }
+
+    if (!isset($baseurl)) {
+        $baseurl = new moodle_url('/course/mod.php', array('sesskey' => sesskey()));
+    }
+
+    if ($sr !== null) {
+        $baseurl->param('sr', $sr);
+    }
+
+    // AJAX edit title.
+    if ($mod->has_view() && $hasmanageactivities && course_ajax_enabled($COURSE) &&
+        (($mod->course == $COURSE->id) || ($mod->course == SITEID))) {
+        // we will not display link if we are on some other-course page (where we should not see this module anyway)
+        return html_writer::span(
+            html_writer::link(
+                new moodle_url($baseurl, array('update' => $mod->id)),
+                $OUTPUT->pix_icon('t/editstring', '', 'moodle', array('class' => 'iconsmall visibleifjs', 'title' => '')),
+                array(
+                    'class' => 'editing_title',
+                    'data-action' => 'edittitle',
+                    'title' => $str->edittitle,
+                )
+            )
+        );
+    }
+    return '';
+}
index 1573ef5..70a3b30 100644 (file)
@@ -336,6 +336,15 @@ abstract class moodle_database {
         return cache::make('core', 'databasemeta', $properties);
     }
 
+    /**
+     * Handle the creation and caching of the temporary tables.
+     *
+     * @return cache_application The temp_tables cachestore to complete operations on.
+     */
+    protected function get_temp_tables_cache() {
+        return cache::make('core', 'temp_tables');
+    }
+
     /**
      * Attempt to create the database
      * @param string $dbhost The database host.
@@ -1040,13 +1049,30 @@ abstract class moodle_database {
 
     /**
      * Resets the internal column details cache
+     *
+     * @param array|null $tablenames an array of xmldb table names affected by this request.
      * @return void
      */
-    public function reset_caches() {
-        $this->tables = null;
-        // Purge MUC as well.
-        $this->get_metacache()->purge();
-        $this->metacache = null;
+    public function reset_caches($tablenames = null) {
+        if (!empty($tablenames)) {
+            $dbmetapurged = false;
+            foreach ($tablenames as $tablename) {
+                if ($this->temptables->is_temptable($tablename)) {
+                    $this->get_temp_tables_cache()->delete($tablename);
+                } else if ($dbmetapurged === false) {
+                    $this->tables = null;
+                    $this->get_metacache()->purge();
+                    $this->metacache = null;
+                    $dbmetapurged = true;
+                }
+            }
+        } else {
+            $this->get_temp_tables_cache()->purge();
+            $this->tables = null;
+            // Purge MUC as well.
+            $this->get_metacache()->purge();
+            $this->metacache = null;
+        }
     }
 
     /**
@@ -1115,10 +1141,11 @@ abstract class moodle_database {
     /**
      * Do NOT use in code, this is for use by database_manager only!
      * @param string|array $sql query or array of queries
+     * @param array|null $tablenames an array of xmldb table names affected by this request.
      * @return bool true
      * @throws ddl_change_structure_exception A DDL specific exception is thrown for any errors.
      */
-    public abstract function change_database_structure($sql);
+    public abstract function change_database_structure($sql, $tablenames = null);
 
     /**
      * Executes a general sql query. Should be used only when no other method suitable.
index 6c9506c..fd1721a 100644 (file)
@@ -438,8 +438,14 @@ class mssql_native_moodle_database extends moodle_database {
     public function get_columns($table, $usecache=true) {
 
         if ($usecache) {
-            if ($data = $this->get_metacache()->get($table)) {
-                return $data;
+            if ($this->temptables->is_temptable($table)) {
+                if ($data = $this->get_temp_tables_cache()->get($table)) {
+                    return $data;
+                }
+            } else {
+                if ($data = $this->get_metacache()->get($table)) {
+                    return $data;
+                }
             }
         }
 
@@ -534,7 +540,11 @@ class mssql_native_moodle_database extends moodle_database {
         $this->free_result($result);
 
         if ($usecache) {
-            $this->get_metacache()->set($table, $structure);
+            if ($this->temptables->is_temptable($table)) {
+                $this->get_temp_tables_cache()->set($table, $structure);
+            } else {
+                $this->get_metacache()->set($table, $structure);
+            }
         }
 
         return $structure;
@@ -634,10 +644,11 @@ class mssql_native_moodle_database extends moodle_database {
     /**
      * Do NOT use in code, to be used by database_manager only!
      * @param string|array $sql query
+     * @param array|null $tablenames an array of xmldb table names affected by this request.
      * @return bool true
      * @throws ddl_change_structure_exception A DDL specific exception is thrown for any errors.
      */
-    public function change_database_structure($sql) {
+    public function change_database_structure($sql, $tablenames = null) {
         $this->get_manager(); // Includes DDL exceptions classes ;-)
         $sqls = (array)$sql;
 
@@ -648,11 +659,11 @@ class mssql_native_moodle_database extends moodle_database {
                 $this->query_end($result);
             }
         } catch (ddl_change_structure_exception $e) {
-            $this->reset_caches();
+            $this->reset_caches($tablenames);
             throw $e;
         }
 
-        $this->reset_caches();
+        $this->reset_caches($tablenames);
         return true;
     }
 
index 32a5db7..e8015a2 100644 (file)
@@ -576,10 +576,15 @@ class mysqli_native_moodle_database extends moodle_database {
      * @return database_column_info[] array of database_column_info objects indexed with column names
      */
     public function get_columns($table, $usecache=true) {
-
         if ($usecache) {
-            if ($data = $this->get_metacache()->get($table)) {
-                return $data;
+            if ($this->temptables->is_temptable($table)) {
+                if ($data = $this->get_temp_tables_cache()->get($table)) {
+                    return $data;
+                }
+            } else {
+                if ($data = $this->get_metacache()->get($table)) {
+                    return $data;
+                }
             }
         }
 
@@ -684,7 +689,11 @@ class mysqli_native_moodle_database extends moodle_database {
         }
 
         if ($usecache) {
-            $this->get_metacache()->set($table, $structure);
+            if ($this->temptables->is_temptable($table)) {
+                $this->get_temp_tables_cache()->set($table, $structure);
+            } else {
+                $this->get_metacache()->set($table, $structure);
+            }
         }
 
         return $structure;
@@ -887,10 +896,11 @@ class mysqli_native_moodle_database extends moodle_database {
     /**
      * Do NOT use in code, to be used by database_manager only!
      * @param string|array $sql query
+     * @param array|null $tablenames an array of xmldb table names affected by this request.
      * @return bool true
      * @throws ddl_change_structure_exception A DDL specific exception is thrown for any errors.
      */
-    public function change_database_structure($sql) {
+    public function change_database_structure($sql, $tablenames = null) {
         $this->get_manager(); // Includes DDL exceptions classes ;-)
         if (is_array($sql)) {
             $sql = implode("\n;\n", $sql);
@@ -913,11 +923,11 @@ class mysqli_native_moodle_database extends moodle_database {
             while (@$this->mysqli->more_results()) {
                 @$this->mysqli->next_result();
             }
-            $this->reset_caches();
+            $this->reset_caches($tablenames);
             throw $e;
         }
 
-        $this->reset_caches();
+        $this->reset_caches($tablenames);
         return true;
     }
 
index c19373d..929ffbd 100644 (file)
@@ -470,8 +470,14 @@ class oci_native_moodle_database extends moodle_database {
     public function get_columns($table, $usecache=true) {
 
         if ($usecache) {
-            if ($data = $this->get_metacache()->get($table)) {
-                return $data;
+            if ($this->temptables->is_temptable($table)) {
+                if ($data = $this->get_temp_tables_cache()->get($table)) {
+                    return $data;
+                }
+            } else {
+                if ($data = $this->get_metacache()->get($table)) {
+                    return $data;
+                }
             }
         }
 
@@ -662,7 +668,11 @@ class oci_native_moodle_database extends moodle_database {
         }
 
         if ($usecache) {
-            $this->get_metacache()->set($table, $structure);
+            if ($this->temptables->is_temptable($table)) {
+                $this->get_temp_tables_cache()->set($table, $structure);
+            } else {
+                $this->get_metacache()->set($table, $structure);
+            }
         }
 
         return $structure;
@@ -887,10 +897,11 @@ class oci_native_moodle_database extends moodle_database {
     /**
      * Do NOT use in code, to be used by database_manager only!
      * @param string|array $sql query
+     * @param array|null $tablenames an array of xmldb table names affected by this request.
      * @return bool true
      * @throws ddl_change_structure_exception A DDL specific exception is thrown for any errors.
      */
-    public function change_database_structure($sql) {
+    public function change_database_structure($sql, $tablenames = null) {
         $this->get_manager(); // Includes DDL exceptions classes ;-)
         $sqls = (array)$sql;
 
@@ -903,11 +914,11 @@ class oci_native_moodle_database extends moodle_database {
                 oci_free_statement($stmt);
             }
         } catch (ddl_change_structure_exception $e) {
-            $this->reset_caches();
+            $this->reset_caches($tablenames);
             throw $e;
         }
 
-        $this->reset_caches();
+        $this->reset_caches($tablenames);
         return true;
     }
 
index 29cdd65..7f71905 100644 (file)
@@ -175,10 +175,11 @@ abstract class pdo_moodle_database extends moodle_database {
     /**
      * Do NOT use in code, to be used by database_manager only!
      * @param string|array $sql query
+     * @param array|null $tablenames an array of xmldb table names affected by this request.
      * @return bool true
      * @throws ddl_change_structure_exception A DDL specific exception is thrown for any errors.
      */
-    public function change_database_structure($sql) {
+    public function change_database_structure($sql, $tablenames = null) {
         $this->get_manager(); // Includes DDL exceptions classes ;-)
         $sqls = (array)$sql;
 
@@ -196,11 +197,11 @@ abstract class pdo_moodle_database extends moodle_database {
                 $this->query_end($result);
             }
         } catch (ddl_change_structure_exception $e) {
-            $this->reset_caches();
+            $this->reset_caches($tablenames);
             throw $e;
         }
 
-        $this->reset_caches();
+        $this->reset_caches($tablenames);
         return true;
     }
 
index 21f86e7..efc5043 100644 (file)
@@ -390,8 +390,14 @@ class pgsql_native_moodle_database extends moodle_database {
      */
     public function get_columns($table, $usecache=true) {
         if ($usecache) {
-            if ($data = $this->get_metacache()->get($table)) {
-                return $data;
+            if ($this->temptables->is_temptable($table)) {
+                if ($data = $this->get_temp_tables_cache()->get($table)) {
+                    return $data;
+                }
+            } else {
+                if ($data = $this->get_metacache()->get($table)) {
+                    return $data;
+                }
             }
         }
 
@@ -594,7 +600,11 @@ class pgsql_native_moodle_database extends moodle_database {
         pg_free_result($result);
 
         if ($usecache) {
-            $this->get_metacache()->set($table, $structure);
+            if ($this->temptables->is_temptable($table)) {
+                $this->get_temp_tables_cache()->set($table, $structure);
+            } else {
+                $this->get_metacache()->set($table, $structure);
+            }
         }
 
         return $structure;
@@ -650,10 +660,11 @@ class pgsql_native_moodle_database extends moodle_database {
     /**
      * Do NOT use in code, to be used by database_manager only!
      * @param string|array $sql query
+     * @param array|null $tablenames an array of xmldb table names affected by this request.
      * @return bool true
      * @throws ddl_change_structure_exception A DDL specific exception is thrown for any errors.
      */
-    public function change_database_structure($sql) {
+    public function change_database_structure($sql, $tablenames = null) {
         $this->get_manager(); // Includes DDL exceptions classes ;-)
         if (is_array($sql)) {
             $sql = implode("\n;\n", $sql);
@@ -673,11 +684,11 @@ class pgsql_native_moodle_database extends moodle_database {
                 $result = @pg_query($this->pgsql, "ROLLBACK");
                 @pg_free_result($result);
             }
-            $this->reset_caches();
+            $this->reset_caches($tablenames);
             throw $e;
         }
 
-        $this->reset_caches();
+        $this->reset_caches($tablenames);
         return true;
     }
 
index 1196d67..58753bd 100644 (file)
@@ -201,8 +201,14 @@ class sqlite3_pdo_moodle_database extends pdo_moodle_database {
     public function get_columns($table, $usecache=true) {
 
         if ($usecache) {
-            if ($data = $this->get_metacache()->get($table)) {
-                return $data;
+            if ($this->temptables->is_temptable($table)) {
+                if ($data = $this->get_temp_tables_cache()->get($table)) {
+                    return $data;
+                }
+            } else {
+                if ($data = $this->get_metacache()->get($table)) {
+                    return $data;
+                }
             }
         }
 
@@ -298,7 +304,11 @@ class sqlite3_pdo_moodle_database extends pdo_moodle_database {
         }
 
         if ($usecache) {
-            $this->get_metacache()->set($table, $structure);
+            if ($this->temptables->is_temptable($table)) {
+                $this->get_temp_tables_cache()->set($table, $structure);
+            } else {
+                $this->get_metacache()->set($table, $structure);
+            }
         }
 
         return $structure;
index 904e7e3..e2d253f 100644 (file)
@@ -508,8 +508,14 @@ class sqlsrv_native_moodle_database extends moodle_database {
      */
     public function get_columns($table, $usecache = true) {
         if ($usecache) {
-            if ($data = $this->get_metacache()->get($table)) {
-                return $data;
+            if ($this->temptables->is_temptable($table)) {
+                if ($data = $this->get_temp_tables_cache()->get($table)) {
+                    return $data;
+                }
+            } else {
+                if ($data = $this->get_metacache()->get($table)) {
+                    return $data;
+                }
             }
         }
 
@@ -604,7 +610,11 @@ class sqlsrv_native_moodle_database extends moodle_database {
         $this->free_result($result);
 
         if ($usecache) {
-            $this->get_metacache()->set($table, $structure);
+            if ($this->temptables->is_temptable($table)) {
+                $this->get_temp_tables_cache()->set($table, $structure);
+            } else {
+                $this->get_metacache()->set($table, $structure);
+            }
         }
 
         return $structure;
@@ -714,10 +724,11 @@ class sqlsrv_native_moodle_database extends moodle_database {
     /**
      * Do NOT use in code, to be used by database_manager only!
      * @param string|array $sql query
+     * @param array|null $tablenames an array of xmldb table names affected by this request.
      * @return bool true
      * @throws ddl_change_structure_exception A DDL specific exception is thrown for any errors.
      */
-    public function change_database_structure($sql) {
+    public function change_database_structure($sql, $tablenames = null) {
         $this->get_manager(); // Includes DDL exceptions classes ;-)
         $sqls = (array)$sql;
 
@@ -728,11 +739,11 @@ class sqlsrv_native_moodle_database extends moodle_database {
                 $this->query_end($result);
             }
         } catch (ddl_change_structure_exception $e) {
-            $this->reset_caches();
+            $this->reset_caches($tablenames);
             throw $e;
         }
 
-        $this->reset_caches();
+        $this->reset_caches($tablenames);
         return true;
     }
 
index 7e9dc55..b2bb25e 100644 (file)
@@ -5510,7 +5510,7 @@ class moodle_database_for_testing extends moodle_database {
     protected function normalise_value($column, $value) {}
     public function set_debug($state) {}
     public function get_debug() {}
-    public function change_database_structure($sql) {}
+    public function change_database_structure($sql, $tablenames = null) {}
     public function execute($sql, array $params=null) {}
     public function get_recordset_sql($sql, array $params=null, $limitfrom=0, $limitnum=0) {}
     public function get_records_sql($sql, array $params=null, $limitfrom=0, $limitnum=0) {}
index 518b77c..ab65184 100644 (file)
@@ -106,13 +106,14 @@ class wikimedia {
      * @param int $orig_width
      * @param int $orig_height
      * @param int $thumb_width
+     * @param bool $force When true, forces the generation of a thumb URL.
      * @global object OUTPUT
      * @return string
      */
-    public function get_thumb_url($image_url, $orig_width, $orig_height, $thumb_width=75) {
+    public function get_thumb_url($image_url, $orig_width, $orig_height, $thumb_width = 75, $force = false) {
         global $OUTPUT;
 
-        if ($orig_width <= $thumb_width AND $orig_height <= $thumb_width) {
+        if (!$force && $orig_width <= $thumb_width && $orig_height <= $thumb_width) {
             return $image_url;
         } else {
             $thumb_url = '';
@@ -169,9 +170,14 @@ class wikimedia {
                 $image_types = array('image/jpeg', 'image/png', 'image/gif', 'image/svg+xml');
                 if (in_array($file_type, $image_types)) {  //is image
                     $extension = pathinfo($title, PATHINFO_EXTENSION);
-                    if (strcmp($extension, 'svg') == 0) {               //upload png version of svg-s
+                    $issvg = strcmp($extension, 'svg') == 0;
+
+                    // Get PNG equivalent to SVG files.
+                    if ($issvg) {
                         $title .= '.png';
                     }
+
+                    // The thumbnail (max size requested) is smaller than the original size, we will use the thumbnail.
                     if ($page['imageinfo'][0]['thumbwidth'] < $page['imageinfo'][0]['width']) {
                         $attrs = array(
                             //upload scaled down image
@@ -185,14 +191,24 @@ class wikimedia {
                         if ($attrs['image_width'] <= 24 && $attrs['image_height'] <= 24) {
                             $attrs['realicon'] = $attrs['source'];
                         }
+
+                    // We use the original file.
                     } else {
                         $attrs = array(
                             //upload full size image
-                            'source' => $page['imageinfo'][0]['url'],
                             'image_width' => $page['imageinfo'][0]['width'],
                             'image_height' => $page['imageinfo'][0]['height'],
                             'size' => $page['imageinfo'][0]['size']
                         );
+
+                        // We cannot use the source when the file is SVG.
+                        if ($issvg) {
+                            // So we generate a PNG thumbnail of the file at its original size.
+                            $attrs['source'] = $this->get_thumb_url($page['imageinfo'][0]['url'], $page['imageinfo'][0]['width'],
+                                $page['imageinfo'][0]['height'], $page['imageinfo'][0]['width'], true);
+                        } else {
+                            $attrs['source'] = $page['imageinfo'][0]['url'];
+                        }
                     }
                     $attrs += array(
                         'realthumbnail' => $this->get_thumb_url($page['imageinfo'][0]['url'], $page['imageinfo'][0]['width'], $page['imageinfo'][0]['height'], WIKIMEDIA_THUMB_SIZE),
index 855541b..e99b829 100644 (file)
@@ -208,7 +208,7 @@ class search_solr_engine_testcase extends advanced_testcase {
             $engine->add_document($doc->export_for_engine());
         }
 
-        $engine->commit();
+        $engine->area_index_complete($area->get_area_id());
 
         $querydata = new stdClass();
         $querydata->q = 'message';
index 05587d5..47492e5 100644 (file)
@@ -11,6 +11,9 @@ information provided here is intended especially for theme designer.
   * notification_problem.mustache => notification_error.mustache
   * notification_message          => notification_info
   * notification_redirect         => notification_warning
+* Method core_course_renderer::course_section_cm_name() is split into two methods, custom themes that override
+  this method must be modified or otherwise editing functionality may become broken. This method is now also used by
+  social activities block and site menu block to display activities names.
 
 === 3.0 ===