Merge branch 'MDL-74465-master-5' of https://github.com/marinaglancy/moodle

This commit is contained in:
Shamim Rezaie 2023-03-31 13:45:15 +11:00
commit e541732a6a
54 changed files with 1108 additions and 776 deletions

View File

@ -124,4 +124,13 @@ class block_activity_results_edit_form extends block_edit_form {
$mform->freeze('config_decimalpoints');
}
}
/**
* Display the configuration form when block is being added to the page
*
* @return bool
*/
public static function display_form_when_adding(): bool {
return true;
}
}

View File

@ -47,15 +47,12 @@ Feature: The activity results block displays student scores
Scenario: Configure the block on a non-graded activity to show 3 high scores
Given I am on the "Test page name" "page activity" page
And I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
And I add the "Activity results" block to the default region with:
| config_activitygradeitemid | Test assignment 1 |
| config_showbest | 3 |
| config_showworst | 0 |
| config_gradeformat | Absolute numbers |
| config_nameformat | Display full names |
And I press "Save changes"
Then I should see "Student 1" in the "Activity results" "block"
And I should see "90.00" in the "Activity results" "block"
And I should see "Student 2" in the "Activity results" "block"
@ -63,26 +60,24 @@ Feature: The activity results block displays student scores
And I should see "Student 3" in the "Activity results" "block"
And I should see "70.00" in the "Activity results" "block"
@javascript @addablocklink
Scenario: Block should select current activity by default
Given I am on the "Test assignment 1" "assign activity" page
When I add the "Activity results" block
And I configure the "Activity results" block
Then the field "config_activitygradeitemid" matches value "Test assignment 1"
And I press "Cancel"
Given I click on "Test assignment 1" "link" in the "region-main" "region"
When I add the "Activity results..." block
Then the field "config_activitygradeitemid" in the "Add Activity results block" "dialogue" matches value "Test assignment 1"
And I click on "Save changes" "button" in the "Add Activity results block" "dialogue"
And I am on "Course 1" course homepage
And I am on the "Test assignment 2" "assign activity" page
And I add the "Activity results" block
And I configure the "Activity results" block
And the field "config_activitygradeitemid" matches value "Test assignment 2"
And I press "Cancel"
And I click on "Test assignment 2" "link" in the "region-main" "region"
And I add the "Activity results..." block
And the field "config_activitygradeitemid" in the "Add Activity results block" "dialogue" matches value "Test assignment 2"
And I click on "Save changes" "button" in the "Add Activity results block" "dialogue"
And I am on "Course 1" course homepage
And I am on the "Test assignment 3" "assign activity" page
And I add the "Activity results" block
And I configure the "Activity results" block
And the field "config_activitygradeitemid" matches value "Test assignment 3"
And I press "Cancel"
And I click on "Test assignment 3" "link" in the "region-main" "region"
And I add the "Activity results..." block
And the field "config_activitygradeitemid" in the "Add Activity results block" "dialogue" matches value "Test assignment 3"
And I click on "Save changes" "button" in the "Add Activity results block" "dialogue"
And I am on "Course 1" course homepage
And I am on the "Test page name" "page activity" page
And I add the "Activity results" block
And I configure the "Activity results" block
And the field "config_activitygradeitemid" does not match value "Test page name"
And I click on "Test page name" "link" in the "region-main" "region"
And I add the "Activity results..." block
And the field "config_activitygradeitemid" in the "Add Activity results block" "dialogue" does not match value "Test page name"
And I click on "Save changes" "button" in the "Add Activity results block" "dialogue"

View File

@ -17,10 +17,16 @@ Feature: The activity results block doesn't displays student scores for unconfig
And I log in as "teacher1"
And I am on "Course 1" course homepage with editing mode on
Scenario: Add the block to a the course
Scenario: Add the block to a the course with Javascript disabled
Given I add the "Activity results" block
Then I should see "Please configure this block and select which activity it should display results from." in the "Activity results" "block"
@javascript
Scenario: Add the block to a the course with Javascript enabled
Given I add the "Activity results" block to the default region with:
| config_showbest | 3 |
Then I should see "Please configure this block and select which activity it should display results from." in the "Activity results" "block"
Scenario: Try to configure the block on the course page in a course without activities
Given I add the "Activity results" block
When I configure the "Activity results" block

View File

@ -39,63 +39,48 @@ Feature: The activity results block displays student high scores
And I am on "Course 1" course homepage
Scenario: Configure the block on the course page to show 0 high scores
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 0 |
| config_showworst | 0 |
| config_gradeformat | Percentages |
| config_nameformat | Display full names |
And I press "Save changes"
Then I should see "This block's configuration currently does not allow it to show any results." in the "Activity results" "block"
Scenario: Configure the block on the course page to show 1 high score
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 1 |
| config_showworst | 0 |
| config_gradeformat | Percentages |
| config_nameformat | Display full names |
| config_decimalpoints | 0 |
And I press "Save changes"
Then I should see "Student 1" in the "Activity results" "block"
And I should see "90%" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show 1 high score as a fraction
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 1 |
| config_showworst | 0 |
| config_gradeformat | Fractions |
| config_nameformat | Display full names |
And I press "Save changes"
Then I should see "Student 1" in the "Activity results" "block"
And I should see "90.00/100.00" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show 1 high score as a absolute numbers
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 1 |
| config_showworst | 0 |
| config_gradeformat | Absolute numbers |
| config_nameformat | Display full names |
And I press "Save changes"
Then I should see "Student 1" in the "Activity results" "block"
And I should see "90.00" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show multiple high scores as percentages
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 3 |
| config_showworst | 0 |
| config_gradeformat | Percentages |
| config_nameformat | Display full names |
| config_decimalpoints | 0 |
And I press "Save changes"
Then I should see "Student 1" in the "Activity results" "block"
And I should see "90%" in the "Activity results" "block"
And I should see "Student 2" in the "Activity results" "block"
@ -104,14 +89,11 @@ Feature: The activity results block displays student high scores
And I should see "70%" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show multiple high scores as fractions
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 3 |
| config_showworst | 0 |
| config_gradeformat | Fractions |
| config_nameformat | Display full names |
And I press "Save changes"
Then I should see "Student 1" in the "Activity results" "block"
And I should see "90.00/100.00" in the "Activity results" "block"
And I should see "Student 2" in the "Activity results" "block"
@ -120,14 +102,11 @@ Feature: The activity results block displays student high scores
And I should see "70.00/100.00" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show multiple high scores as absolute numbers
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 3 |
| config_showworst | 0 |
| config_gradeformat | Absolute numbers |
| config_nameformat | Display full names |
And I press "Save changes"
Then I should see "Student 1" in the "Activity results" "block"
And I should see "90.00" in the "Activity results" "block"
And I should see "Student 2" in the "Activity results" "block"
@ -138,14 +117,11 @@ Feature: The activity results block displays student high scores
Scenario: Try to configure the block on the course page to show multiple high scores using ID numbers
Given the following config values are set as admin:
| showuseridentity | idnumber,email |
And I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
And I add the "Activity results" block to the default region with:
| config_showbest | 3 |
| config_showworst | 0 |
| config_gradeformat | Percentages |
| config_nameformat | Display only ID numbers |
And I press "Save changes"
Then I should see "User S1" in the "Activity results" "block"
And I should see "90.00%" in the "Activity results" "block"
And I should see "User S2" in the "Activity results" "block"
@ -154,14 +130,11 @@ Feature: The activity results block displays student high scores
And I should see "70.00%" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show multiple high scores using anonymous names
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 3 |
| config_showworst | 0 |
| config_gradeformat | Percentages |
| config_nameformat | Anonymous results |
And I press "Save changes"
Then I should see "User" in the "Activity results" "block"
And I should see "90.00%" in the "Activity results" "block"
And I should see "80.00%" in the "Activity results" "block"

View File

@ -58,25 +58,19 @@ Feature: The activity results block displays students high scores in group as sc
And I am on "Course 1" course homepage with editing mode on
Scenario: Configure the block on the course page to show 1 high score
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 1 |
| config_showworst | 0 |
| config_nameformat | Display full names |
| config_decimalpoints | 0 |
And I press "Save changes"
Then I should see "Student 1" in the "Activity results" "block"
And I should see "Excellent!" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show multiple high scores using full names
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 3 |
| config_showworst | 0 |
| config_nameformat | Display full names |
And I press "Save changes"
Then I should see "Student 1" in the "Activity results" "block"
And I should see "Excellent!" in the "Activity results" "block"
And I should see "Student 2" in the "Activity results" "block"
@ -87,13 +81,10 @@ Feature: The activity results block displays students high scores in group as sc
Scenario: Try to configure the block on the course page to show multiple high scores using ID numbers
Given the following config values are set as admin:
| showuseridentity | idnumber,email |
And I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
And I add the "Activity results" block to the default region with:
| config_showbest | 3 |
| config_showworst | 0 |
| config_nameformat | Display only ID numbers |
And I press "Save changes"
Then I should see "User S1" in the "Activity results" "block"
And I should see "Excellent!" in the "Activity results" "block"
And I should see "User S2" in the "Activity results" "block"
@ -102,13 +93,10 @@ Feature: The activity results block displays students high scores in group as sc
And I should see "Good" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show multiple high scores using anonymous names
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 3 |
| config_showworst | 0 |
| config_nameformat | Anonymous results |
And I press "Save changes"
Then I should see "User" in the "Activity results" "block"
And I should not see "Student 1" in the "Activity results" "block"
And I should see "Excellent!" in the "Activity results" "block"

View File

@ -44,6 +44,7 @@ Feature: The activity results block displays student in group high scores as sca
And the following "activities" exist:
| activity | name | intro | course | section | idnumber |
| assign | Test assignment | Offline text | C1 | 1 | assign1 |
And I change window size to "large"
And I log in as "teacher1"
And I am on "Course 1" course homepage with editing mode on
And I navigate to "Scales" in the course gradebook
@ -73,14 +74,11 @@ Feature: The activity results block displays student in group high scores as sca
And I am on "Course 1" course homepage
Scenario: Try to configure the block on the course page to show 1 high score
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 1 |
| config_showworst | 0 |
| config_nameformat | Display full names |
| config_usegroups | Yes |
And I press "Save changes"
Then I should see "Group 1" in the "Activity results" "block"
And I should see "Excellent!" in the "Activity results" "block"
And I log out
@ -90,14 +88,11 @@ Feature: The activity results block displays student in group high scores as sca
And I should see "Excellent!" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show multiple high scores using full names
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 3 |
| config_showworst | 0 |
| config_nameformat | Display full names |
| config_usegroups | Yes |
And I press "Save changes"
Then I should see "Group 1" in the "Activity results" "block"
And I should see "Excellent!" in the "Activity results" "block"
And I should see "Group 2" in the "Activity results" "block"
@ -115,14 +110,11 @@ Feature: The activity results block displays student in group high scores as sca
Scenario: Try to configure the block on the course page to show multiple high scores using ID numbers
Given the following config values are set as admin:
| showuseridentity | idnumber,email |
And I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
And I add the "Activity results" block to the default region with:
| config_showbest | 3 |
| config_showworst | 0 |
| config_nameformat | Display only ID numbers |
| config_usegroups | Yes |
And I press "Save changes"
Then I should see "Group" in the "Activity results" "block"
And I should see "Excellent!" in the "Activity results" "block"
And I should see "Very good" in the "Activity results" "block"
@ -138,14 +130,11 @@ Feature: The activity results block displays student in group high scores as sca
And I should see "Very good" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show multiple high scores using anonymous names
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 3 |
| config_showworst | 0 |
| config_nameformat | Anonymous results |
| config_usegroups | Yes |
And I press "Save changes"
Then I should see "Group" in the "Activity results" "block"
And I should see "Excellent!" in the "Activity results" "block"
And I should see "Very good" in the "Activity results" "block"

View File

@ -63,29 +63,23 @@ Feature: The activity results block displays student in separate groups scores
And I am on "Course 1" course homepage
Scenario: Configure the block on the course page to show 1 high score
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 1 |
| config_showworst | 0 |
| config_gradeformat | Percentages |
| config_nameformat | Display full names |
| config_decimalpoints | 0 |
| config_usegroups | Yes |
And I press "Save changes"
Then I should see "Group 1" in the "Activity results" "block"
And I should see "95%" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show 1 high score as a fraction
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 1 |
| config_showworst | 0 |
| config_gradeformat | Fractions |
| config_nameformat | Display full names |
| config_usegroups | Yes |
And I press "Save changes"
Then I should see "Group 1" in the "Activity results" "block"
And I should see "95.00/100.00" in the "Activity results" "block"
And I log out
@ -95,15 +89,12 @@ Feature: The activity results block displays student in separate groups scores
And I should see "100.00/100.00" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show 1 high score as a absolute numbers
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 1 |
| config_showworst | 0 |
| config_gradeformat | Absolute numbers |
| config_nameformat | Display full names |
| config_usegroups | Yes |
And I press "Save changes"
Then I should see "Group 1" in the "Activity results" "block"
And I should see "95.00" in the "Activity results" "block"
And I log out
@ -113,16 +104,13 @@ Feature: The activity results block displays student in separate groups scores
And I should see "100.00" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show multiple high scores as percentages
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 3 |
| config_showworst | 0 |
| config_gradeformat | Percentages |
| config_nameformat | Display full names |
| config_decimalpoints | 0 |
| config_usegroups | Yes |
And I press "Save changes"
Then I should see "Group 1" in the "Activity results" "block"
And I should see "95%" in the "Activity results" "block"
And I should see "Group 2" in the "Activity results" "block"
@ -138,15 +126,12 @@ Feature: The activity results block displays student in separate groups scores
And I should see "90%" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show multiple high scores as fractions
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 3 |
| config_showworst | 0 |
| config_gradeformat | Fractions |
| config_nameformat | Display full names |
| config_usegroups | Yes |
And I press "Save changes"
Then I should see "Group 1" in the "Activity results" "block"
And I should see "95.00/100.00" in the "Activity results" "block"
And I should see "Group 2" in the "Activity results" "block"
@ -162,15 +147,12 @@ Feature: The activity results block displays student in separate groups scores
And I should see "80.00/100.00" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show multiple high scores as absolute numbers
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 3 |
| config_showworst | 0 |
| config_gradeformat | Absolute numbers |
| config_nameformat | Display full names |
| config_usegroups | Yes |
And I press "Save changes"
Then I should see "Group 1" in the "Activity results" "block"
And I should see "95.00" in the "Activity results" "block"
And I should see "Group 2" in the "Activity results" "block"
@ -188,15 +170,12 @@ Feature: The activity results block displays student in separate groups scores
Scenario: Try to configure the block on the course page to show multiple high scores using ID numbers
Given the following config values are set as admin:
| showuseridentity | idnumber,email |
And I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
And I add the "Activity results" block to the default region with:
| config_showbest | 3 |
| config_showworst | 0 |
| config_gradeformat | Percentages |
| config_nameformat | Display only ID numbers |
| config_usegroups | Yes |
And I press "Save changes"
Then I should see "Group" in the "Activity results" "block"
And I should see "95.00%" in the "Activity results" "block"
And I should see "85.00%" in the "Activity results" "block"
@ -212,15 +191,12 @@ Feature: The activity results block displays student in separate groups scores
And I should see "90.00%" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show multiple high scores using anonymous names
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 3 |
| config_showworst | 0 |
| config_gradeformat | Percentages |
| config_nameformat | Anonymous results |
| config_usegroups | Yes |
And I press "Save changes"
Then I should see "Group" in the "Activity results" "block"
And I should see "95.00%" in the "Activity results" "block"
And I should see "85.00%" in the "Activity results" "block"

View File

@ -64,29 +64,23 @@ Feature: The activity results block displays student in visible groups scores
And I am on "Course 1" course homepage
Scenario: Configure the block on the course page to show 1 high score
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 1 |
| config_showworst | 0 |
| config_gradeformat | Percentages |
| config_nameformat | Display full names |
| config_decimalpoints | 0 |
| config_usegroups | Yes |
And I press "Save changes"
Then I should see "Group 1" in the "Activity results" "block"
And I should see "95%" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show 1 high score as a fraction
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 1 |
| config_showworst | 0 |
| config_gradeformat | Fractions |
| config_nameformat | Display full names |
| config_usegroups | Yes |
And I press "Save changes"
And I log out
Then I log in as "student1"
And I am on "Course 1" course homepage
@ -94,15 +88,12 @@ Feature: The activity results block displays student in visible groups scores
And I should see "95.00/100.00" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show 1 high score as a absolute numbers
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 1 |
| config_showworst | 0 |
| config_gradeformat | Absolute numbers |
| config_nameformat | Display full names |
| config_usegroups | Yes |
And I press "Save changes"
And I log out
Then I log in as "student1"
And I am on "Course 1" course homepage
@ -110,16 +101,13 @@ Feature: The activity results block displays student in visible groups scores
And I should see "95.00" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show multiple high scores as percentages
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 3 |
| config_showworst | 0 |
| config_gradeformat | Percentages |
| config_nameformat | Display full names |
| config_decimalpoints | 0 |
| config_usegroups | Yes |
And I press "Save changes"
And I log out
Then I log in as "student1"
And I am on "Course 1" course homepage
@ -131,15 +119,12 @@ Feature: The activity results block displays student in visible groups scores
And I should see "75%" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show multiple high scores as fractions
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 3 |
| config_showworst | 0 |
| config_gradeformat | Fractions |
| config_nameformat | Display full names |
| config_usegroups | Yes |
And I press "Save changes"
And I log out
Then I log in as "student1"
And I am on "Course 1" course homepage
@ -151,15 +136,12 @@ Feature: The activity results block displays student in visible groups scores
And I should see "75.00/100.00" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show multiple high scores as absolute numbers
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 3 |
| config_showworst | 0 |
| config_gradeformat | Absolute numbers |
| config_nameformat | Display full names |
| config_usegroups | Yes |
And I press "Save changes"
And I log out
Then I log in as "student1"
And I am on "Course 1" course homepage
@ -173,15 +155,12 @@ Feature: The activity results block displays student in visible groups scores
Scenario: Try to configure the block on the course page to show multiple high scores using ID numbers
Given the following config values are set as admin:
| showuseridentity | idnumber,email |
And I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
And I add the "Activity results" block to the default region with:
| config_showbest | 3 |
| config_showworst | 0 |
| config_gradeformat | Percentages |
| config_nameformat | Display only ID numbers |
| config_usegroups | Yes |
And I press "Save changes"
And I log out
Then I log in as "student1"
And I am on "Course 1" course homepage
@ -191,15 +170,12 @@ Feature: The activity results block displays student in visible groups scores
And I should see "75.00%" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show multiple high scores using anonymous names
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 3 |
| config_showworst | 0 |
| config_gradeformat | Percentages |
| config_nameformat | Anonymous results |
| config_usegroups | Yes |
And I press "Save changes"
And I log out
Then I log in as "student1"
And I am on "Course 1" course homepage

View File

@ -44,52 +44,40 @@ Feature: The activity results block displays student low scores
And I am on "Course 1" course homepage
Scenario: Configure the block on the course page to show 1 low score
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 0 |
| config_showworst | 1 |
| config_gradeformat | Percentages |
| config_nameformat | Display full names |
| config_decimalpoints | 0 |
And I press "Save changes"
Then I should see "Student 5" in the "Activity results" "block"
And I should see "50%" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show 1 low score as a fraction
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 0 |
| config_showworst | 1 |
| config_gradeformat | Fractions |
| config_nameformat | Display full names |
And I press "Save changes"
Then I should see "Student 5" in the "Activity results" "block"
And I should see "50.00/100.00" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show 1 low score as a absolute number
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 0 |
| config_showworst | 1 |
| config_gradeformat | Absolute numbers |
| config_nameformat | Display full names |
And I press "Save changes"
Then I should see "Student 5" in the "Activity results" "block"
And I should see "50.00" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show multiple low scores as percentages
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 0 |
| config_showworst | 3 |
| config_gradeformat | Percentages |
| config_nameformat | Display full names |
| config_decimalpoints | 0 |
And I press "Save changes"
Then I should see "Student 5" in the "Activity results" "block"
And I should see "50%" in the "Activity results" "block"
And I should see "Student 4" in the "Activity results" "block"
@ -98,14 +86,11 @@ Feature: The activity results block displays student low scores
And I should see "70%" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show multiple low scores as fractions
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 0 |
| config_showworst | 3 |
| config_gradeformat | Fractions |
| config_nameformat | Display full names |
And I press "Save changes"
Then I should see "Student 5" in the "Activity results" "block"
And I should see "50.00/100.00" in the "Activity results" "block"
And I should see "Student 4" in the "Activity results" "block"
@ -114,14 +99,11 @@ Feature: The activity results block displays student low scores
And I should see "70.00/100.00" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show multiple low scores as absolute numbers
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 0 |
| config_showworst | 3 |
| config_gradeformat | Absolute numbers |
| config_nameformat | Display full names |
And I press "Save changes"
Then I should see "Student 5" in the "Activity results" "block"
And I should see "50.00" in the "Activity results" "block"
And I should see "Student 4" in the "Activity results" "block"
@ -132,14 +114,11 @@ Feature: The activity results block displays student low scores
Scenario: Try to configure the block on the course page to show multiple low scores using ID numbers
Given the following config values are set as admin:
| showuseridentity | idnumber,email |
And I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
And I add the "Activity results" block to the default region with:
| config_showbest | 0 |
| config_showworst | 3 |
| config_gradeformat | Percentages |
| config_nameformat | Display only ID numbers |
And I press "Save changes"
Then I should see "User S5" in the "Activity results" "block"
And I should see "50.00%" in the "Activity results" "block"
And I should see "User S4" in the "Activity results" "block"
@ -148,14 +127,11 @@ Feature: The activity results block displays student low scores
And I should see "70.00%" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show multiple low scores using anonymous names
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 0 |
| config_showworst | 3 |
| config_gradeformat | Percentages |
| config_nameformat | Anonymous results |
And I press "Save changes"
Then I should see "User" in the "Activity results" "block"
And I should see "50.00%" in the "Activity results" "block"
And I should see "60.00%" in the "Activity results" "block"

View File

@ -58,26 +58,20 @@ Feature: The activity results block displays student low scores as scales
And I am on "Course 1" course homepage
Scenario: Configure the block on the course page to show 1 low score
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 0 |
| config_showworst | 1 |
| config_gradeformat | Percentages |
| config_nameformat | Display full names |
| config_decimalpoints | 0 |
And I press "Save changes"
Then I should see "Student 5" in the "Activity results" "block"
And I should see "Not good enough" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show multiple low scores using full names
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 0 |
| config_showworst | 3 |
| config_nameformat | Display full names |
And I press "Save changes"
Then I should see "Student 5" in the "Activity results" "block"
And I should see "Not good enough" in the "Activity results" "block"
And I should see "Student 4" in the "Activity results" "block"
@ -88,13 +82,10 @@ Feature: The activity results block displays student low scores as scales
Scenario: Try to configure the block on the course page to show multiple low scores using ID numbers
Given the following config values are set as admin:
| showuseridentity | idnumber,email |
And I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
And I add the "Activity results" block to the default region with:
| config_showbest | 0 |
| config_showworst | 3 |
| config_nameformat | Display only ID numbers |
And I press "Save changes"
Then I should see "User S5" in the "Activity results" "block"
And I should see "Not good enough" in the "Activity results" "block"
And I should see "User S4" in the "Activity results" "block"
@ -103,13 +94,10 @@ Feature: The activity results block displays student low scores as scales
And I should see "Good" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show multiple low scores using anonymous names
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 0 |
| config_showworst | 3 |
| config_nameformat | Anonymous results |
And I press "Save changes"
Then I should see "User" in the "Activity results" "block"
And I should not see "Student 5" in the "Activity results" "block"
And I should see "Not good enough" in the "Activity results" "block"

View File

@ -49,6 +49,7 @@ Feature: The activity results block displays students in groups low scores as sc
| description | Offline text |
| assignsubmission_file_enabled | 0 |
| groupmode | 1 |
And I change window size to "large"
And I log in as "teacher1"
And I am on "Course 1" course homepage
And I navigate to "Scales" in the course gradebook
@ -77,14 +78,11 @@ Feature: The activity results block displays students in groups low scores as sc
And I am on "Course 1" course homepage
Scenario: Try to configure the block on the course page to show 1 low score
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 0 |
| config_showworst | 1 |
| config_nameformat | Display full names |
| config_usegroups | Yes |
And I press "Save changes"
Then I should see "Group 3" in the "Activity results" "block"
And I should see "Good" in the "Activity results" "block"
And I log out
@ -94,14 +92,11 @@ Feature: The activity results block displays students in groups low scores as sc
And I should see "Average" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show multiple high scores using full names
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 0 |
| config_showworst | 2 |
| config_nameformat | Display full names |
| config_usegroups | Yes |
And I press "Save changes"
Then I should see "Group 2" in the "Activity results" "block"
And I should see "Very good" in the "Activity results" "block"
And I should see "Group 3" in the "Activity results" "block"
@ -117,14 +112,11 @@ Feature: The activity results block displays students in groups low scores as sc
Scenario: Try to configure the block on the course page to show multiple high scores using ID numbers
Given the following config values are set as admin:
| showuseridentity | idnumber,email |
And I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
And I add the "Activity results" block to the default region with:
| config_showbest | 0 |
| config_showworst | 2 |
| config_nameformat | Display only ID numbers |
| config_usegroups | Yes |
And I press "Save changes"
Then I should see "Group" in the "Activity results" "block"
And I should see "Very good" in the "Activity results" "block"
And I should see "Good" in the "Activity results" "block"
@ -139,14 +131,11 @@ Feature: The activity results block displays students in groups low scores as sc
And I should see "Average" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show multiple high scores using anonymous names
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 0 |
| config_showworst | 2 |
| config_nameformat | Anonymous results |
| config_usegroups | Yes |
And I press "Save changes"
Then I should see "Group" in the "Activity results" "block"
And I should see "Very good" in the "Activity results" "block"
And I should see "Good" in the "Activity results" "block"

View File

@ -57,29 +57,23 @@ Feature: The activity results block displays students in separate groups scores
And I am on "Course 1" course homepage
Scenario: Configure the block on the course page to show 1 low score
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 0 |
| config_showworst | 1 |
| config_gradeformat | Percentages |
| config_nameformat | Display full names |
| config_decimalpoints | 0 |
| config_usegroups | Yes |
And I press "Save changes"
Then I should see "Group 3" in the "Activity results" "block"
And I should see "75%" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show 1 low score as a fraction
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 0 |
| config_showworst | 1 |
| config_gradeformat | Fractions |
| config_nameformat | Display full names |
| config_usegroups | Yes |
And I press "Save changes"
Then I should see "Group 3" in the "Activity results" "block"
And I should see "75.00/100.00" in the "Activity results" "block"
And I log out
@ -89,15 +83,12 @@ Feature: The activity results block displays students in separate groups scores
And I should see "70.00/100.00" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show 1 low score as a absolute numbers
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 0 |
| config_showworst | 1 |
| config_gradeformat | Absolute numbers |
| config_nameformat | Display full names |
| config_usegroups | Yes |
And I press "Save changes"
Then I should see "Group 3" in the "Activity results" "block"
And I should see "75.00" in the "Activity results" "block"
And I log out
@ -107,16 +98,13 @@ Feature: The activity results block displays students in separate groups scores
And I should see "70.00" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show multiple low scores as percentages
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 0 |
| config_showworst | 2 |
| config_gradeformat | Percentages |
| config_nameformat | Display full names |
| config_decimalpoints | 0 |
| config_usegroups | Yes |
And I press "Save changes"
Then I should see "Group 2" in the "Activity results" "block"
And I should see "85%" in the "Activity results" "block"
And I should see "Group 3" in the "Activity results" "block"
@ -130,15 +118,12 @@ Feature: The activity results block displays students in separate groups scores
And I should see "80%" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show multiple low scores as fractions
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 0 |
| config_showworst | 2 |
| config_gradeformat | Fractions |
| config_nameformat | Display full names |
| config_usegroups | Yes |
And I press "Save changes"
Then I should see "Group 2" in the "Activity results" "block"
And I should see "85.00/100.00" in the "Activity results" "block"
And I should see "Group 3" in the "Activity results" "block"
@ -152,15 +137,12 @@ Feature: The activity results block displays students in separate groups scores
And I should see "80.00/100.00" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show multiple low scores as absolute numbers
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 0 |
| config_showworst | 2 |
| config_gradeformat | Absolute numbers |
| config_nameformat | Display full names |
| config_usegroups | Yes |
And I press "Save changes"
Then I should see "Group 2" in the "Activity results" "block"
And I should see "85.00" in the "Activity results" "block"
And I should see "Group 3" in the "Activity results" "block"
@ -176,15 +158,12 @@ Feature: The activity results block displays students in separate groups scores
Scenario: Try to configure the block on the course page to show multiple low scores using ID numbers
Given the following config values are set as admin:
| showuseridentity | idnumber,email |
And I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
And I add the "Activity results" block to the default region with:
| config_showbest | 0 |
| config_showworst | 2 |
| config_gradeformat | Percentages |
| config_nameformat | Display only ID numbers |
| config_usegroups | Yes |
And I press "Save changes"
Then I should see "Group" in the "Activity results" "block"
And I should see "85.00%" in the "Activity results" "block"
And I should see "75.00%" in the "Activity results" "block"
@ -199,15 +178,12 @@ Feature: The activity results block displays students in separate groups scores
And I should see "90.00%" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show multiple low scores using anonymous names
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 0 |
| config_showworst | 2 |
| config_gradeformat | Percentages |
| config_nameformat | Anonymous results |
| config_usegroups | Yes |
And I press "Save changes"
Then I should see "Group" in the "Activity results" "block"
And I should see "85.00%" in the "Activity results" "block"
And I should see "75.00%" in the "Activity results" "block"

View File

@ -63,29 +63,23 @@ Feature: The activity results block displays student in visible groups low score
And I am on "Course 1" course homepage
Scenario: Configure the block on the course page to show 1 low score
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 0 |
| config_showworst | 1 |
| config_gradeformat | Percentages |
| config_nameformat | Display full names |
| config_decimalpoints | 0 |
| config_usegroups | Yes |
And I press "Save changes"
Then I should see "Group 3" in the "Activity results" "block"
And I should see "75%" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show 1 low score as a fraction
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 0 |
| config_showworst | 1 |
| config_gradeformat | Fractions |
| config_nameformat | Display full names |
| config_usegroups | Yes |
And I press "Save changes"
And I log out
Then I log in as "student1"
And I am on "Course 1" course homepage
@ -93,15 +87,12 @@ Feature: The activity results block displays student in visible groups low score
And I should see "75.00/100.00" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show 1 low score as a absolute numbers
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 0 |
| config_showworst | 1 |
| config_gradeformat | Absolute numbers |
| config_nameformat | Display full names |
| config_usegroups | Yes |
And I press "Save changes"
And I log out
Then I log in as "student1"
And I am on "Course 1" course homepage
@ -109,16 +100,13 @@ Feature: The activity results block displays student in visible groups low score
And I should see "75.00" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show multiple low scores as percentages
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 0 |
| config_showworst | 2 |
| config_gradeformat | Percentages |
| config_nameformat | Display full names |
| config_decimalpoints | 0 |
| config_usegroups | Yes |
And I press "Save changes"
Then I should see "Group 2" in the "Activity results" "block"
And I should see "85%" in the "Activity results" "block"
And I should see "Group 3" in the "Activity results" "block"
@ -132,15 +120,12 @@ Feature: The activity results block displays student in visible groups low score
And I should see "75%" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show multiple low scores as fractions
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 0 |
| config_showworst | 2 |
| config_gradeformat | Fractions |
| config_nameformat | Display full names |
| config_usegroups | Yes |
And I press "Save changes"
And I log out
Then I log in as "student1"
And I am on "Course 1" course homepage
@ -150,15 +135,12 @@ Feature: The activity results block displays student in visible groups low score
And I should see "75.00/100.00" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show multiple low scores as absolute numbers
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 0 |
| config_showworst | 2 |
| config_gradeformat | Absolute numbers |
| config_nameformat | Display full names |
| config_usegroups | Yes |
And I press "Save changes"
And I log out
Then I log in as "student1"
And I am on "Course 1" course homepage
@ -170,15 +152,12 @@ Feature: The activity results block displays student in visible groups low score
Scenario: Try to configure the block on the course page to show multiple low scores using ID numbers
Given the following config values are set as admin:
| showuseridentity | idnumber,email |
And I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
And I add the "Activity results" block to the default region with:
| config_showbest | 0 |
| config_showworst | 2 |
| config_gradeformat | Percentages |
| config_nameformat | Display only ID numbers |
| config_usegroups | Yes |
And I press "Save changes"
And I log out
Then I log in as "student1"
And I am on "Course 1" course homepage
@ -187,15 +166,12 @@ Feature: The activity results block displays student in visible groups low score
And I should see "75.00%" in the "Activity results" "block"
Scenario: Try to configure the block on the course page to show multiple low scores using anonymous names
Given I add the "Activity results" block
When I configure the "Activity results" block
And I set the following fields to these values:
Given I add the "Activity results" block to the default region with:
| config_showbest | 0 |
| config_showworst | 2 |
| config_gradeformat | Percentages |
| config_nameformat | Anonymous results |
| config_usegroups | Yes |
And I press "Save changes"
And I log out
Then I log in as "student1"
And I am on "Course 1" course homepage

10
blocks/amd/build/add_modal.min.js vendored Normal file
View File

@ -0,0 +1,10 @@
define("core_block/add_modal",["exports","core/modal_factory","core/templates","core/str","core/ajax","core_form/modalform"],(function(_exports,_modal_factory,_templates,_str,_ajax,_modalform){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}
/**
* Show an add block modal instead of doing it on a separate page.
*
* @module core_block/add_modal
* @copyright 2016 Damyon Wiese <damyon@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_modal_factory=_interopRequireDefault(_modal_factory),_templates=_interopRequireDefault(_templates),_ajax=_interopRequireDefault(_ajax),_modalform=_interopRequireDefault(_modalform);const SELECTORS_ADD_BLOCK='[data-key="addblock"]',SELECTORS_SHOW_BLOCK_FORM='[data-action="showaddblockform"][data-blockname][data-blockform]';let listenerEventsRegistered=!1;const registerListenerEvents=(addBlockUrl,pagehash)=>{let addBlockModal=null;document.addEventListener("click",(e=>{const showAddBlockForm=e.target.closest(SELECTORS_SHOW_BLOCK_FORM);if(showAddBlockForm){e.preventDefault();const modalForm=new _modalform.default({modalConfig:{title:(0,_str.get_string)("addblock","core_block",showAddBlockForm.getAttribute("data-blocktitle"))},args:{blockname:showAddBlockForm.getAttribute("data-blockname"),pagehash:pagehash,blockregion:showAddBlockForm.getAttribute("data-blockregion")},formClass:showAddBlockForm.getAttribute("data-blockform"),returnFocus:showAddBlockForm});modalForm.addEventListener(modalForm.events.FORM_SUBMITTED,(()=>{addBlockModal.destroy(),window.location.reload()})),modalForm.show()}const addBlock=e.target.closest(SELECTORS_ADD_BLOCK);if(addBlock){e.preventDefault();let addBlockModalUrl=null!=addBlockUrl?addBlockUrl:addBlock.dataset.url;buildAddBlockModal().then((modal=>{addBlockModal=modal;const modalBody=renderBlocks(addBlockModalUrl,pagehash,addBlock.getAttribute("data-blockregion"));return modal.setBody(modalBody),modal.show(),modalBody})).catch((()=>{addBlockModal.destroy()}))}}))},buildAddBlockModal=()=>_modal_factory.default.create({type:_modal_factory.default.types.CANCEL,title:(0,_str.get_string)("addblock")}),renderBlocks=async(addBlockUrl,pagehash,region)=>{const blocks=await getAddableBlocks(pagehash);return _templates.default.render("core/add_block_body",{blocks:blocks,url:addBlockUrl,blockregion:region,pagehash:pagehash})},getAddableBlocks=async pagehash=>{const request={methodname:"core_block_fetch_addable_blocks",args:{pagecontextid:0,pagetype:"",pagelayout:"",subpage:"",pagehash:pagehash}};return _ajax.default.call([request])[0]};_exports.init=function(){let addBlockUrl=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,pagehash=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";listenerEventsRegistered||(registerListenerEvents(addBlockUrl,pagehash),listenerEventsRegistered=!0)}}));
//# sourceMappingURL=add_modal.min.js.map

File diff suppressed because one or more lines are too long

10
blocks/amd/build/edit.min.js vendored Normal file
View File

@ -0,0 +1,10 @@
define("core_block/edit",["exports","core_form/modalform"],(function(_exports,_modalform){var obj;
/**
* Javascript module for editing blocks
*
* @module core_block/edit
* @copyright 2022 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_modalform=(obj=_modalform)&&obj.__esModule?obj:{default:obj};const SELECTORS_EDITBLOCK='[data-action="editblock"][data-blockid][data-blockform]';_exports.init=pagehash=>{document.addEventListener("click",(e=>{const target=e.target.closest(SELECTORS_EDITBLOCK);if(!target||!target.getAttribute("data-blockform"))return;e.preventDefault();const modalForm=new _modalform.default({modalConfig:{title:target.getAttribute("data-header")},args:{blockid:target.getAttribute("data-blockid"),pagehash:pagehash},formClass:target.getAttribute("data-blockform"),returnFocus:target});modalForm.addEventListener(modalForm.events.FORM_SUBMITTED,(()=>{location.reload()})),modalForm.show()}))}}));
//# sourceMappingURL=edit.min.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"edit.min.js","sources":["../src/edit.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Javascript module for editing blocks\n *\n * @module core_block/edit\n * @copyright 2022 Marina Glancy\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport ModalForm from 'core_form/modalform';\n\nconst SELECTORS = {\n EDITBLOCK: '[data-action=\"editblock\"][data-blockid][data-blockform]',\n};\n\n/**\n * Initialize module\n * @param {String} pagehash\n */\nexport const init = (pagehash) => {\n document.addEventListener('click', e => {\n const target = e.target.closest(SELECTORS.EDITBLOCK);\n if (!target || !target.getAttribute('data-blockform')) {\n return;\n }\n e.preventDefault();\n\n const modalForm = new ModalForm({\n modalConfig: {\n title: target.getAttribute('data-header'),\n },\n args: {blockid: target.getAttribute('data-blockid'), pagehash},\n formClass: target.getAttribute('data-blockform'),\n returnFocus: target,\n });\n\n // Reload the page when the form is submitted, there is no possibility\n // currently to request contents update of just one block on the page.\n modalForm.addEventListener(modalForm.events.FORM_SUBMITTED, () => {\n location.reload();\n });\n\n modalForm.show();\n });\n};\n"],"names":["SELECTORS","pagehash","document","addEventListener","e","target","closest","getAttribute","preventDefault","modalForm","ModalForm","modalConfig","title","args","blockid","formClass","returnFocus","events","FORM_SUBMITTED","location","reload","show"],"mappings":";;;;;;;sJAyBMA,oBACS,wEAOMC,WACjBC,SAASC,iBAAiB,SAASC,UACzBC,OAASD,EAAEC,OAAOC,QAAQN,yBAC3BK,SAAWA,OAAOE,aAAa,yBAGpCH,EAAEI,uBAEIC,UAAY,IAAIC,mBAAU,CAC5BC,YAAa,CACTC,MAAOP,OAAOE,aAAa,gBAE/BM,KAAM,CAACC,QAAST,OAAOE,aAAa,gBAAiBN,SAAAA,UACrDc,UAAWV,OAAOE,aAAa,kBAC/BS,YAAaX,SAKjBI,UAAUN,iBAAiBM,UAAUQ,OAAOC,gBAAgB,KACxDC,SAASC,YAGbX,UAAUY"}

163
blocks/amd/src/add_modal.js Normal file
View File

@ -0,0 +1,163 @@
// 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/>.
/**
* Show an add block modal instead of doing it on a separate page.
*
* @module core_block/add_modal
* @copyright 2016 Damyon Wiese <damyon@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import ModalFactory from 'core/modal_factory';
import Templates from 'core/templates';
import {get_string as getString} from 'core/str';
import Ajax from 'core/ajax';
import ModalForm from "core_form/modalform";
const SELECTORS = {
ADD_BLOCK: '[data-key="addblock"]',
SHOW_BLOCK_FORM: '[data-action="showaddblockform"][data-blockname][data-blockform]'
};
// Ensure we only add our listeners once.
let listenerEventsRegistered = false;
/**
* Register related event listeners.
*
* @method registerListenerEvents
* @param {String|null} addBlockUrl The add block URL
* @param {String} pagehash
*/
const registerListenerEvents = (addBlockUrl, pagehash) => {
let addBlockModal = null;
document.addEventListener('click', e => {
const showAddBlockForm = e.target.closest(SELECTORS.SHOW_BLOCK_FORM);
if (showAddBlockForm) {
e.preventDefault();
const modalForm = new ModalForm({
modalConfig: {
title: getString('addblock', 'core_block',
showAddBlockForm.getAttribute('data-blocktitle')),
},
args: {blockname: showAddBlockForm.getAttribute('data-blockname'), pagehash,
blockregion: showAddBlockForm.getAttribute('data-blockregion')},
formClass: showAddBlockForm.getAttribute('data-blockform'),
returnFocus: showAddBlockForm,
});
modalForm.addEventListener(modalForm.events.FORM_SUBMITTED, () => {
addBlockModal.destroy();
window.location.reload();
});
modalForm.show();
}
const addBlock = e.target.closest(SELECTORS.ADD_BLOCK);
if (addBlock) {
e.preventDefault();
let addBlockModalUrl = addBlockUrl ?? addBlock.dataset.url;
buildAddBlockModal()
.then(modal => {
addBlockModal = modal;
const modalBody = renderBlocks(addBlockModalUrl, pagehash,
addBlock.getAttribute('data-blockregion'));
modal.setBody(modalBody);
modal.show();
return modalBody;
})
.catch(() => {
addBlockModal.destroy();
});
}
});
};
/**
* Method that creates the 'add block' modal.
*
* @method buildAddBlockModal
* @returns {Promise} The modal promise (modal's body will be rendered later).
*/
const buildAddBlockModal = () => {
return ModalFactory.create({
type: ModalFactory.types.CANCEL,
title: getString('addblock')
});
};
/**
* Method that renders the list of available blocks.
*
* @method renderBlocks
* @param {String} addBlockUrl The add block URL
* @param {String} pagehash
* @param {String} region
* @return {Promise}
*/
const renderBlocks = async(addBlockUrl, pagehash, region) => {
// Fetch all addable blocks in the given page.
const blocks = await getAddableBlocks(pagehash);
return Templates.render('core/add_block_body', {
blocks: blocks,
url: addBlockUrl,
blockregion: region,
pagehash
});
};
/**
* Method that fetches all addable blocks in a given page.
*
* @method getAddableBlocks
* @param {String} pagehash
* @return {Promise}
*/
const getAddableBlocks = async(pagehash) => {
const request = {
methodname: 'core_block_fetch_addable_blocks',
args: {
pagecontextid: 0,
pagetype: '',
pagelayout: '',
subpage: '',
pagehash: pagehash,
},
};
return Ajax.call([request])[0];
};
/**
* Set up the actions.
*
* @method init
* @param {String} addBlockUrl The add block URL
* @param {String} pagehash
*/
export const init = (addBlockUrl = null, pagehash = '') => {
if (!listenerEventsRegistered) {
registerListenerEvents(addBlockUrl, pagehash);
listenerEventsRegistered = true;
}
};

59
blocks/amd/src/edit.js Normal file
View File

@ -0,0 +1,59 @@
// 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/>.
/**
* Javascript module for editing blocks
*
* @module core_block/edit
* @copyright 2022 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import ModalForm from 'core_form/modalform';
const SELECTORS = {
EDITBLOCK: '[data-action="editblock"][data-blockid][data-blockform]',
};
/**
* Initialize module
* @param {String} pagehash
*/
export const init = (pagehash) => {
document.addEventListener('click', e => {
const target = e.target.closest(SELECTORS.EDITBLOCK);
if (!target || !target.getAttribute('data-blockform')) {
return;
}
e.preventDefault();
const modalForm = new ModalForm({
modalConfig: {
title: target.getAttribute('data-header'),
},
args: {blockid: target.getAttribute('data-blockid'), pagehash},
formClass: target.getAttribute('data-blockform'),
returnFocus: target,
});
// Reload the page when the form is submitted, there is no possibility
// currently to request contents update of just one block on the page.
modalForm.addEventListener(modalForm.events.FORM_SUBMITTED, () => {
location.reload();
});
modalForm.show();
});
};

View File

@ -44,6 +44,7 @@ class fetch_addable_blocks extends external_api {
'pagetype' => new external_value(PARAM_ALPHANUMEXT, 'The type of the page.'),
'pagelayout' => new external_value(PARAM_ALPHA, 'The layout of the page.'),
'subpage' => new external_value(PARAM_TEXT, 'The subpage identifier', VALUE_DEFAULT, ''),
'pagehash' => new external_value(PARAM_ALPHANUMEXT, 'Page hash', VALUE_DEFAULT, ''),
]
);
}
@ -55,9 +56,11 @@ class fetch_addable_blocks extends external_api {
* @param string $pagetype The type of the page
* @param string $pagelayout The layout of the page
* @param string $subpage The subpage identifier
* @param string $pagehash Page hash that can be provided instead of all parameters above
* @return array The blocks list
*/
public static function execute(int $pagecontextid, string $pagetype, string $pagelayout, string $subpage = ''): array {
public static function execute(int $pagecontextid, string $pagetype, string $pagelayout,
string $subpage = '', string $pagehash = ''): array {
global $PAGE;
$params = self::validate_parameters(self::execute_parameters(),
@ -66,28 +69,43 @@ class fetch_addable_blocks extends external_api {
'pagetype' => $pagetype,
'pagelayout' => $pagelayout,
'subpage' => $subpage,
'pagehash' => $pagehash,
]
);
$context = \context::instance_by_id($params['pagecontextid']);
// Validate the context. This will also set the context in $PAGE.
self::validate_context($context);
if ($params['pagehash']) {
// If pagehash is specified, all other parameters are ignored, all information
// about the page is stored in the session.
// We need to manually set the page layout and page type.
$PAGE->set_pagelayout($params['pagelayout']);
$PAGE->set_pagetype($params['pagetype']);
$PAGE->set_subpage($params['subpage']);
$page = \moodle_page::retrieve_edited_page($params['pagehash'], MUST_EXIST);
self::validate_context($page->context);
} else {
// For backward-compatibility and Mobile App instead of pagehash
// we can specify context, pagelayout, pagetype and subtype.
$context = \context::instance_by_id($params['pagecontextid']);
// Validate the context. This will also set the context in $PAGE.
self::validate_context($context);
// We need to manually set the page layout and page type.
$PAGE->set_pagelayout($params['pagelayout']);
$PAGE->set_pagetype($params['pagetype']);
$PAGE->set_subpage($params['subpage']);
$page = $PAGE;
}
// Firstly, we need to load all currently existing page blocks to later determine which blocks are addable.
$PAGE->blocks->load_blocks(false);
$PAGE->blocks->create_all_block_instances();
$page->blocks->load_blocks(false);
$page->blocks->create_all_block_instances();
$addableblocks = $PAGE->blocks->get_addable_blocks();
$addableblocks = $page->blocks->get_addable_blocks();
return array_map(function($block) {
return array_map(function($block) use ($page) {
$classname = \block_manager::get_block_edit_form_class($block->name);
return [
'name' => $block->name,
'title' => get_string('pluginname', "block_{$block->name}")
'title' => get_string('pluginname', "block_{$block->name}"),
'blockform' => $classname::display_form_when_adding() ? $classname : null,
];
}, $addableblocks);
}
@ -103,6 +121,8 @@ class fetch_addable_blocks extends external_api {
[
'name' => new external_value(PARAM_PLUGIN, 'The name of the block.'),
'title' => new external_value(PARAM_RAW, 'The title of the block.'),
'blockform' => new external_value(PARAM_RAW,
'If this block type has a form when it is being added then the classname of the form')
]
),
'List of addable blocks in a given page.'

View File

@ -17,7 +17,7 @@
/**
* Defines the base class form used by blocks/edit.php to edit block instance configuration.
*
* It works with the {@link block_edit_form} class, or rather the particular
* It works with the {@see block_edit_form} class, or rather the particular
* subclass defined by this block, to do the editing.
*
* @package core_block
@ -25,30 +25,27 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
if (!defined('MOODLE_INTERNAL')) {
die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page
}
require_once($CFG->libdir . '/formslib.php');
require_once($CFG->libdir . '/blocklib.php');
/**
* The base class form used by blocks/edit.php to edit block instance configuration.
*
* @property-read block_base $block
* @property-read moodle_page $page
* @copyright 2009 Tim Hunt
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class block_edit_form extends moodleform {
class block_edit_form extends \core_form\dynamic_form {
/**
* The block instance we are editing.
* @var block_base
*/
public $block;
private $_block;
/**
* The page we are editing this block in association with.
* @var moodle_page
*/
public $page;
private $_page;
/**
* Defaults set in set_data() that need to be returned in get_data() if form elements were not created
@ -56,19 +53,95 @@ class block_edit_form extends moodleform {
*/
protected $defaults = [];
function __construct($actionurl, $block, $page) {
global $CFG;
$this->block = $block;
$this->page = $page;
parent::__construct($actionurl);
/**
* Magic getter for backward compatibility
*
* @param string $name
* @return block_base|moodle_page
*/
public function __get(string $name) {
if ($name === 'page') {
return $this->get_page();
} else if ($name === 'block') {
return $this->get_block();
} else {
throw new coding_exception('Property '.$name.' does not exist');
}
}
/**
* Page where we are adding or editing the block
*
* To access you can also use magic property $this->page
*
* @return moodle_page
* @throws moodle_exception
*/
protected function get_page(): moodle_page {
if (!$this->_page && !empty($this->_customdata['page'])) {
$this->_page = $this->_customdata['page'];
} else if (!$this->_page) {
if (!$pagehash = $this->optional_param('pagehash', '', PARAM_ALPHANUMEXT)) {
throw new \moodle_exception('missingparam', '', '', 'pagehash');
}
$this->_page = moodle_page::retrieve_edited_page($pagehash, MUST_EXIST);
$this->_page->blocks->load_blocks();
}
return $this->_page;
}
/**
* Instance of the block that is being added or edited
*
* To access you can also use magic property $this->block
*
* If {{@see self::display_form_when_adding()}} returns true and the configuration
* form is displayed when adding block, the $this->block->id will be null.
*
* @return block_base
* @throws block_not_on_page_exception
* @throws moodle_exception
*/
protected function get_block(): block_base {
if (!$this->_block && !empty($this->_customdata['block'])) {
$this->_block = $this->_customdata['block'];
} else if (!$this->_block) {
$blockid = $this->optional_param('blockid', null, PARAM_INT);
$blockname = $this->optional_param('blockname', null, PARAM_PLUGIN);
if ($blockname && !$blockid) {
$this->_block = block_instance($blockname);
$this->_block->page = $this->page;
$this->_block->context = $this->page->context;
$this->_block->instance = (object)['parentcontextid' => $this->page->context->id, 'id' => null];
} else {
$this->_block = $this->page->blocks->find_instance($blockid);
}
}
return $this->_block;
}
/**
* Form definition
*/
function definition() {
$mform =& $this->_form;
$mform->addElement('hidden', 'blockid', $this->block->instance->id);
$mform->setType('blockid', PARAM_INT);
$mform->addElement('hidden', 'blockname', $this->optional_param('blockname', null, PARAM_PLUGIN));
$mform->setType('blockname', PARAM_PLUGIN);
$mform->addElement('hidden', 'blockregion', $this->optional_param('blockregion', null, PARAM_TEXT));
$mform->setType('blockregion', PARAM_TEXT);
$mform->addElement('hidden', 'pagehash', $this->optional_param('pagehash', null, PARAM_ALPHANUMEXT));
$mform->setType('pagehash', PARAM_ALPHANUMEXT);
// First show fields specific to this type of block.
$this->specific_definition($mform);
if (!$this->block->instance->id) {
return;
}
// Then show the fields about where this block appears.
$mform->addElement('header', 'whereheader', get_string('wherethisblockappears', 'block'));
@ -110,10 +183,10 @@ class block_edit_form extends moodleform {
// First of all, check if we are editing blocks @ front-page or no and
// make some dark magic if so (MDL-30340) because each page context
// implies one (and only one) harcoded page-type that will be set later
// when processing the form data at {@link block_manager::process_url_edit()}
// when processing the form data at {@see block_manager::process_url_edit()}.
// Front page, show the page-contexts element and set $pagetypelist to 'any page' (*)
// as unique option. Processign the form will do any change if needed
// as unique option. Processign the form will do any change if needed.
if ($this->is_editing_the_frontpage()) {
$contextoptions = array();
$contextoptions[BUI_CONTEXTS_FRONTPAGE_ONLY] = get_string('showonfrontpageonly', 'block');
@ -232,7 +305,9 @@ class block_edit_form extends moodleform {
$mform->hardFreeze($pagefields);
}
$this->add_action_buttons();
if (!empty($this->_customdata['actionbuttons'])) {
$this->add_action_buttons();
}
}
/**
@ -248,13 +323,19 @@ class block_edit_form extends moodleform {
return ($ctxconditions && $issiteindex);
}
function set_data($defaults) {
/**
* Prepare block configuration data and add default values when needed
*
* @param stdClass $defaults
* @return stdClass
*/
protected function prepare_defaults(stdClass $defaults): stdClass {
// Prefix bui_ on all the core field names.
$blockfields = array('showinsubcontexts', 'pagetypepattern', 'subpagepattern', 'parentcontextid',
'defaultregion', 'defaultweight', 'visible', 'region', 'weight');
foreach ($blockfields as $field) {
$newname = 'bui_' . $field;
$defaults->$newname = $defaults->$field;
$defaults->$newname = $defaults->$field ?? null;
}
// Copy block config into config_ fields.
@ -284,12 +365,22 @@ class block_edit_form extends moodleform {
'bui_pagetypepattern' => $defaults->bui_pagetypepattern,
'bui_subpagepattern' => $defaults->bui_subpagepattern,
];
parent::set_data($defaults);
return $defaults;
}
/**
* Load in existing data as form defaults
*
* @param stdClass $defaults
* @return void
*/
public function set_data($defaults) {
parent::set_data($this->prepare_defaults($defaults));
}
/**
* Override this to create any form fields specific to this type of block.
* @param object $mform the form being built.
* @param \MoodleQuickForm $mform the form being built.
*/
protected function specific_definition($mform) {
// By default, do nothing.
@ -299,7 +390,7 @@ class block_edit_form extends moodleform {
* Return submitted data if properly submitted or returns NULL if validation fails or
* if there is no submitted data.
*
* @return object submitted data; NULL if not valid or not submitted or cancelled
* @return stdClass submitted data; NULL if not valid or not submitted or cancelled
*/
public function get_data() {
if ($data = parent::get_data()) {
@ -310,4 +401,85 @@ class block_edit_form extends moodleform {
}
return $data;
}
/**
* Returns context where this form is used
*
* @return context
*/
protected function get_context_for_dynamic_submission(): context {
return $this->page->context;
}
/**
* Checks if current user has access to this form, otherwise throws exception
*/
protected function check_access_for_dynamic_submission(): void {
if ($this->block->instance->id) {
if (!$this->page->user_can_edit_blocks() && !$this->block->user_can_edit()) {
throw new moodle_exception('nopermissions', '', $this->page->url->out(), get_string('editblock'));
}
} else {
if (!$this->page->user_can_edit_blocks()) {
throw new moodle_exception('nopermissions', '', $this->page->url->out(), get_string('addblock'));
}
$addableblocks = $this->page->blocks->get_addable_blocks();
$blocktype = $this->block->name();
if (!array_key_exists($blocktype, $addableblocks)) {
throw new moodle_exception('cannotaddthisblocktype', '', $this->page->url->out(), $blocktype);
}
}
}
/**
* Process the form submission, used if form was submitted via AJAX
*/
public function process_dynamic_submission() {
if ($this->block->instance->id) {
$this->page->blocks->save_block_data($this->block, $this->get_data());
} else {
$blockregion = $this->optional_param('blockregion', null, PARAM_TEXT);
$newblock = $this->page->blocks->add_block_at_end_of_default_region($this->block->name(),
empty($blockregion) ? null : $blockregion);
$this->page->blocks->load_blocks();
$newblock = $this->page->blocks->find_instance($newblock->instance->id);
$newdata = $this->prepare_defaults($newblock->instance);
foreach ($this->get_data() as $key => $value) {
$newdata->$key = $value;
}
$this->page->blocks->save_block_data($newblock, $newdata);
}
}
/**
* Load in existing data as form defaults
*/
public function set_data_for_dynamic_submission(): void {
$this->set_data($this->block->instance);
}
/**
* Returns url to set in $PAGE->set_url() when form is being rendered or submitted via AJAX
*
* @return moodle_url
*/
protected function get_page_url_for_dynamic_submission(): moodle_url {
return $this->page->url;
}
/**
* Display the configuration form when block is being added to the page
*
* By default when block is added to the page it is added with the default configuration.
* Some block may require configuration, for example, "glossary random entry" block
* needs a glossary to be selected, "RSS feed" block needs an RSS feed to be selected, etc.
*
* Such blocks can override this function and return true. These blocks must
* ensure that the function specific_definition() will work if there is no current block id.
*
* @return bool
*/
public static function display_form_when_adding(): bool {
return false;
}
}

View File

@ -40,7 +40,8 @@ class block_glossary_random_edit_form extends block_edit_form {
$mform->setType('config_title', PARAM_TEXT);
// Select glossaries to put in dropdown box ...
$glossaries = $DB->get_records_select_menu('glossary', 'course = ? OR globalglossary = ?', array($this->block->course->id, 1), 'name', 'id,name');
$glossaries = $DB->get_records_select_menu('glossary', 'course = ? OR globalglossary = ?',
[$this->get_course_id(), 1], 'name', 'id,name');
foreach($glossaries as $key => $value) {
$glossaries[$key] = strip_tags(format_string($value, true));
}
@ -76,4 +77,28 @@ class block_glossary_random_edit_form extends block_edit_form {
$mform->setDefault('config_invisible', get_string('invisible', 'block_glossary_random'));
$mform->setType('config_invisible', PARAM_NOTAGS);
}
/**
* Returns id of the course where this block is located (or siteid for the dashboard or non-course page)
*
* @return int
*/
protected function get_course_id(): int {
if ($this->block->instance->id) {
return $this->block->course->id;
} else if ($parentcontext = $this->block->context->get_course_context(false)) {
return $parentcontext->instanceid;
} else {
return get_site()->id;
}
}
/**
* Display the configuration form when block is being added to the page
*
* @return bool
*/
public static function display_form_when_adding(): bool {
return true;
}
}

View File

@ -12,7 +12,8 @@ Feature: Add the glossary random block when main feature is disabled
Scenario: The glossary random block is displayed even when glossary module is disabled
Given I turn editing mode on
And I add the "Random glossary entry" block
And I add the "Random glossary entry" block to the default region with:
| Title | Random glossary entry |
When I navigate to "Plugins > Activity modules > Manage activities" in site administration
And I click on "Disable the Glossary plugin" "icon" in the "Glossary" "table_row"
And I am on "Course 1" course homepage with editing mode on
@ -20,7 +21,8 @@ Feature: Add the glossary random block when main feature is disabled
Scenario: The glossary random block can be removed even when glossary module is disabled
Given I turn editing mode on
And I add the "Random glossary entry" block
And I add the "Random glossary entry" block to the default region with:
| Title | Random glossary entry |
And I open the "Random glossary entry" blocks action menu
And I click on "Delete Random glossary entry block" "link" in the "Random glossary entry" "block"
And "Delete block?" "dialogue" should exist

View File

@ -88,4 +88,13 @@ class block_html_edit_form extends block_edit_form {
$this->block->config->title = $title;
}
}
/**
* Display the configuration form when block is being added to the page
*
* @return bool
*/
public static function display_form_when_adding(): bool {
return true;
}
}

View File

@ -9,11 +9,9 @@ Feature: Adding and configuring Text blocks
Given I log in as "admin"
And I am on site homepage
When I turn editing mode on
And I add the "Text" block
And I configure the "(new text block)" block
And I set the field "Content" to "Static text without a header"
Then I should see "Text block title"
And I press "Save changes"
And I add the "Text" block to the default region with:
| Text block title | |
| Content | Static text without a header |
Then I should not see "(new text block)"
And I configure the "block_html" block
And I set the field "Text block title" to "The Text block header"

View File

@ -71,13 +71,13 @@ class block_base {
/**
* An object to contain the information to be displayed in the block.
* @var stdObject $content
* @var stdClass $content
*/
var $content = NULL;
/**
* The initialized instance of this block object.
* @var block $instance
* @var stdClass $instance
*/
var $instance = NULL;
@ -89,13 +89,13 @@ class block_base {
/**
* This blocks's context.
* @var stdClass
* @var context
*/
public $context = NULL;
/**
* An object containing the instance configuration information for the current instance of this block.
* @var stdObject $config
* @var stdClass $config
*/
var $config = NULL;
@ -462,7 +462,7 @@ class block_base {
* table and the current page. (See {@link block_manager::load_blocks()}.)
*
* @param stdClass $instance data from block_insances, block_positions, etc.
* @param moodle_page $the page this block is on.
* @param moodle_page $page the page this block is on.
*/
function _load_instance($instance, $page) {
if (!empty($instance->configdata)) {

View File

@ -52,6 +52,7 @@ Feature: The recently accessed items block allows users to easily access their m
And I click on "Show more items" "button" in the "Recently accessed items" "block"
And I should see "Test forum name" in the "Recently accessed items" "block"
And I turn editing mode on
And I am on homepage
And I configure the "Recently accessed items" block
And I set the following fields to these values:
| Region | content |

View File

@ -89,4 +89,13 @@ class block_rss_client_edit_form extends block_edit_form {
$mform->addElement('selectyesno', 'config_block_rss_client_show_channel_image', get_string('clientshowimagelabel', 'block_rss_client'));
$mform->setDefault('config_block_rss_client_show_channel_image', 0);
}
/**
* Display the configuration form when block is being added to the page
*
* @return bool
*/
public static function display_form_when_adding(): bool {
return true;
}
}

View File

@ -26,6 +26,7 @@
// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
use Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException;
use Behat\Gherkin\Node\TableNode as TableNode;
require_once(__DIR__ . '/../../../lib/behat/behat_base.php');
@ -56,6 +57,48 @@ class behat_blocks extends behat_base {
}
}
/**
* Adds the selected block to the specified region
*
* Editing mode must be previously enabled.
*
* @Given /^I add the "(?P<block_name_string>(?:[^"]|\\")*)" block to the "(?P<region_string>(?:[^"]|\\")*)" region$/
* @param string $blockname
* @param string $region
*/
public function i_add_the_block_to_the_region(string $blockname, string $region) {
if (!$this->running_javascript()) {
throw new coding_exception('Adding block to specific region is not possible with Javascript disabled');
}
if ($region === "default") {
$region = "";
}
$csselement = 'a[data-key="addblock"][data-blockregion='.behat_context_helper::escape($region).']';
$addblock = get_string('addblock');
$this->execute('behat_general::i_click_on', [$csselement, 'css_element']);
$this->execute('behat_general::i_click_on_in_the', [$blockname, 'link_exact', $addblock, 'dialogue']);
}
/**
* Adds the selected block to the specified region and fills configuration form.
*
* Editing mode must be previously enabled.
*
* @Given /^I add the "(?P<block_name_string>(?:[^"]|\\")*)" block to the (?P<region_string>(?:[^"]|\\")*) region with:$/
* @param string $blockname
* @param string $region
* @param TableNode $data
*/
public function i_add_the_block_to_the_region_with(string $blockname, string $region, TableNode $data) {
$blocklabel = get_string('textellipsis', 'moodle', $blockname);
$this->execute('behat_blocks::i_add_the_block_to_the_region', [$blocklabel, $region]);
$this->wait_for_pending_js();
$dialogname = get_string('addblock', 'core_block', $blockname);
$this->execute('behat_forms::i_set_the_following_fields_in_container_to_these_values',
[$dialogname, "dialogue", $data]);
$this->execute('behat_general::i_click_on_in_the', ["Save changes", 'button', $dialogname, 'dialogue']);
}
/**
* Adds the selected block if it is not already present. Editing mode must be previously enabled.
*

View File

@ -64,10 +64,8 @@ Feature: Add and configure blocks throughout the site
Given I log in as "admin"
And I am on homepage
And I turn editing mode on
And I add the "Text" block
And I configure the "(new text block)" block
And I set the following fields to these values:
And I add the "Text" block to the default region with:
| Text block title | Foo " onload="document.getElementsByTagName('body')[0].remove()" alt=" |
| Content | Example |
When I press "Save changes"
Then I should see "Example"
Then I should see "Example" in the "block_html" "block"
Then I should see "document.getElementsByTagName"

View File

@ -1,6 +1,20 @@
This files describes API changes in /blocks/* - activity modules,
information provided here is intended especially for developers.
=== 4.1 ===
* Block configuration form is now displayed in a modal. Class 'block_edit_form' now extends
'\core_form\dynamic_form' and properties $block and $page are read-only. Normally
no changes should be necessary to keep the old behavior of configuration form.
* Block plugins can specify that they want to display configuration form when block is
added to the page by overriding static method block_edit_form::display_form_when_adding().
* Web service 'core_block_fetch_addable_blocks' accepts new parameter 'pagehash'
* JS module 'core/addblockmodal' is deprecated, instead there is new module
'core_block/add_modal' with similar functionality but different arguments.
* Functions in the JS modules 'moodle-core-blockdraganddrop' have changed their parameters.
File lib/ajax/blocks.php takes different arguments.
No backward-compatibility is provided since these files are not part of the blocks API
and not intended to be used by plugins.
=== 4.0 ===
* Block block_quiz_results has been completely removed from core.

View File

@ -221,16 +221,18 @@ Feature: Inline editing H5P content anywhere
Given I am on the "C1" "Course" page logged in as "admin"
# Add H5P content to the block.
And I turn editing mode on
And I add the "Text" block
And I configure the "(new text block)" block
And I click on "Insert H5P" "button" in the "#fitem_id_config_text" "css_element"
And I add the "Text" block to the default region with:
| Text block title | H5PTest |
| Content | - |
And I configure the "H5PTest" block
And I click on "Insert H5P" "button" in the "//div[contains(@id,'fitem_id_config_text')]" "xpath_element"
And I click on "Browse repositories..." "button" in the "Insert H5P" "dialogue"
And I select "Content bank" repository in file picker
And I click on "Greeting card" "file" in repository content area
And I click on "Make a copy of the file" "radio"
And I click on "Select this file" "button"
And I click on "Insert H5P" "button" in the "Insert H5P" "dialogue"
And I press "Save changes"
And I click on "Save changes" "button" in the "Configure H5PTest block" "dialogue"
And I switch to "h5p-iframe" class iframe
And I switch to "h5p-iframe" class iframe
And I should see "Hello world!"

View File

@ -22,6 +22,7 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$string['addblock'] = 'Add {$a} block';
$string['anypagematchingtheabove'] = 'Any page matching the above';
$string['appearsinsubcontexts'] = 'Appears in sub-contexts';
$string['assignrolesinblock'] = 'Assign roles in {$a} block';

View File

@ -240,6 +240,7 @@ $string['duplicateparaminsql'] = 'ERROR: duplicate parameter name in query';
$string['duplicaterolename'] = 'There is already a role with this name!';
$string['duplicateroleshortname'] = 'There is already a role with this short name!';
$string['duplicateusername'] = 'Duplicate username - skipping record';
$string['editedpagenotfound'] = 'Could not determine the current page. Please try refreshing the page and repeating the operation.';
$string['emailfail'] = 'Emailing failed';
$string['encryption_encryptfailed'] = 'Encryption failed';
$string['encryption_decryptfailed'] = 'Decryption failed';

View File

@ -26,52 +26,29 @@ define('AJAX_SCRIPT', true);
require_once(__DIR__ . '/../../config.php');
// Initialise ALL common incoming parameters here, up front.
$courseid = required_param('courseid', PARAM_INT);
$pagelayout = required_param('pagelayout', PARAM_ALPHAEXT);
$pagetype = required_param('pagetype', PARAM_ALPHANUMEXT);
$contextid = required_param('contextid', PARAM_INT);
$subpage = optional_param('subpage', '', PARAM_ALPHANUMEXT);
$cmid = optional_param('cmid', null, PARAM_INT);
$pagehash = required_param('pagehash', PARAM_RAW);
$action = optional_param('action', '', PARAM_ALPHA);
// Params for blocks-move actions.
$buimoveid = optional_param('bui_moveid', 0, PARAM_INT);
$buinewregion = optional_param('bui_newregion', '', PARAM_ALPHAEXT);
$buibeforeid = optional_param('bui_beforeid', 0, PARAM_INT);
// Setting pagetype and URL.
$PAGE->set_pagetype($pagetype);
$PAGE->set_url('/lib/ajax/blocks.php', array('courseid' => $courseid, 'pagelayout' => $pagelayout, 'pagetype' => $pagetype));
$PAGE->set_url('/lib/ajax/blocks.php', ['pagehash' => $pagehash]);
// Retrieve the edited page from the session hash.
$page = moodle_page::retrieve_edited_page($pagehash, MUST_EXIST);
// Verifying login and session.
$cm = null;
if (!is_null($cmid)) {
$cm = get_coursemodule_from_id(null, $cmid, $courseid, false, MUST_EXIST);
if (!is_null($page->cm)) {
$cm = get_coursemodule_from_id(null, $page->cm->id, $page->course->id, false, MUST_EXIST);
}
require_login($courseid, false, $cm);
require_login($page->course, false, $cm);
require_sesskey();
$PAGE->set_context($page->context);
// Set context from ID, so we don't have to guess it from other info.
$PAGE->set_context(context::instance_by_id($contextid));
// Setting layout to replicate blocks configuration for the page we edit.
$PAGE->set_pagelayout($pagelayout);
$PAGE->set_subpage($subpage);
$PAGE->blocks->add_custom_regions_for_pagetype($pagetype);
$pagetype = explode('-', $pagetype);
switch ($pagetype[0]) {
case 'my':
case 'mycourses':
$PAGE->set_blocks_editing_capability('moodle/my:manageblocks');
break;
case 'user':
if ($pagetype[1] === 'profile' && $PAGE->context->contextlevel == CONTEXT_USER
&& $PAGE->context->instanceid == $USER->id) {
// A user can only move blocks on their own site profile.
$PAGE->set_blocks_editing_capability('moodle/user:manageownblocks');
} else {
$PAGE->set_blocks_editing_capability('moodle/user:manageblocks');
}
break;
if (!$page->user_can_edit_blocks() || !$page->user_is_editing()) {
throw new moodle_exception('nopermissions', '', $page->url->out(), get_string('editblock'));
}
// Send headers.
@ -80,8 +57,8 @@ echo $OUTPUT->header();
switch ($action) {
case 'move':
// Loading blocks and instances for the region.
$PAGE->blocks->load_blocks();
$instances = $PAGE->blocks->get_blocks_for_region($buinewregion);
$page->blocks->load_blocks();
$instances = $page->blocks->get_blocks_for_region($buinewregion);
$buinewweight = null;
if ($buibeforeid == 0) {
@ -121,7 +98,7 @@ switch ($action) {
if (isset($buinewweight)) {
// Nasty hack.
$_POST['bui_newweight'] = $buinewweight;
$PAGE->blocks->process_url_move();
$page->blocks->process_url_move();
}
break;
}

View File

@ -3,6 +3,7 @@ define("core/addblockmodal",["exports","core/modal_factory","core/templates","co
* Show an add block modal instead of doing it on a separate page.
*
* @module core/addblockmodal
* @deprecated since Moodle 4.2 - please use core_block/add_modal instead.
* @copyright 2016 Damyon Wiese <damyon@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_modal_factory=_interopRequireDefault(_modal_factory),_templates=_interopRequireDefault(_templates),_ajax=_interopRequireDefault(_ajax);const SELECTORS_ADD_BLOCK='[data-key="addblock"]';let listenerEventsRegistered=!1;const registerListenerEvents=(pageType,pageLayout,addBlockUrl,subPage)=>{document.addEventListener("click",(e=>{const addBlock=e.target.closest(SELECTORS_ADD_BLOCK);if(addBlock){e.preventDefault();let addBlockModal=null,addBlockModalUrl=null!=addBlockUrl?addBlockUrl:addBlock.dataset.url;buildAddBlockModal().then((modal=>{addBlockModal=modal;const modalBody=renderBlocks(addBlockModalUrl,pageType,pageLayout,subPage);return modal.setBody(modalBody),modal.show(),modalBody})).catch((()=>{addBlockModal.destroy()}))}}))},buildAddBlockModal=()=>_modal_factory.default.create({type:_modal_factory.default.types.CANCEL,title:(0,_str.get_string)("addblock")}),renderBlocks=async(addBlockUrl,pageType,pageLayout,subPage)=>{const blocks=await getAddableBlocks(pageType,pageLayout,subPage);return _templates.default.render("core/add_block_body",{blocks:blocks,url:addBlockUrl})},getAddableBlocks=async(pageType,pageLayout,subPage)=>{const request={methodname:"core_block_fetch_addable_blocks",args:{pagecontextid:M.cfg.contextid,pagetype:pageType,pagelayout:pageLayout,subpage:subPage}};return _ajax.default.call([request])[0]};_exports.init=function(pageType,pageLayout){let addBlockUrl=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,subPage=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"";listenerEventsRegistered||(registerListenerEvents(pageType,pageLayout,addBlockUrl,subPage),listenerEventsRegistered=!0)}}));

File diff suppressed because one or more lines are too long

View File

@ -17,6 +17,7 @@
* Show an add block modal instead of doing it on a separate page.
*
* @module core/addblockmodal
* @deprecated since Moodle 4.2 - please use core_block/add_modal instead.
* @copyright 2016 Damyon Wiese <damyon@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

View File

@ -821,6 +821,7 @@ class block_manager {
* @param boolean $showinsubcontexts whether this block appears in subcontexts, or just the current context.
* @param string|null $pagetypepattern which page types this block should appear on. Defaults to just the current page type.
* @param string|null $subpagepattern which subpage this block should appear on. NULL = any (the default), otherwise only the specified subpage.
* @return block_base
*/
public function add_block($blockname, $region, $weight, $showinsubcontexts, $pagetypepattern = NULL, $subpagepattern = NULL) {
global $DB;
@ -853,6 +854,13 @@ class block_manager {
if ($block = block_instance($blockname, $blockinstance)) {
$block->instance_create();
}
if (!is_null($this->birecordsbyregion)) {
// If blocks were already loaded on this page, reload them.
$this->birecordsbyregion = null;
$this->load_blocks();
}
return $block;
}
/**
@ -860,11 +868,12 @@ class block_manager {
*
* @param string $blockname Name of the block to add.
* @param null|string $blockregion If defined add the new block to the specified region.
* @return ?block_base
*/
public function add_block_at_end_of_default_region($blockname, $blockregion = null) {
if (empty($this->birecordsbyregion)) {
// No blocks or block regions exist yet.
return;
return null;
}
if ($blockregion === null) {
@ -911,7 +920,7 @@ class block_manager {
// Surely other pages like course-report will need this too, they just are not important
// enough now. This will be decided in the coming days. (MDL-27829, MDL-28150)
$this->add_block($blockname, $defaulregion, $weight, false, $pagetypepattern, $subpage);
return $this->add_block($blockname, $defaulregion, $weight, false, $pagetypepattern, $subpage);
}
/**
@ -1295,8 +1304,8 @@ class block_manager {
* Get the appropriate list of editing icons for a block. This is used
* to set {@link block_contents::$controls} in {@link block_base::get_contents_for_output()}.
*
* @param $output The core_renderer to use when generating the output. (Need to get icon paths.)
* @return an array in the format for {@link block_contents::$controls}
* @param block_base $block
* @return array an array in the format for {@link block_contents::$controls}
*/
public function edit_controls($block) {
global $CFG;
@ -1335,7 +1344,13 @@ class block_manager {
$editactionurl,
new pix_icon('t/edit', $str, 'moodle', array('class' => 'iconsmall', 'title' => '')),
$str,
array('class' => 'editing_edit')
[
'class' => 'editing_edit',
'data-action' => 'editblock',
'data-blockid' => $block->instance->id,
'data-blockform' => self::get_block_edit_form_class($block->name()),
'data-header' => $str,
]
);
}
@ -1648,6 +1663,31 @@ class block_manager {
}
}
/**
* Returns the name of the class for block editing and makes sure it is autoloaded
*
* @param string $blockname name of the block plugin (without block_ prefix)
* @return string
*/
public static function get_block_edit_form_class(string $blockname): string {
global $CFG;
require_once("$CFG->dirroot/blocks/moodleblock.class.php");
$blockname = clean_param($blockname, PARAM_PLUGIN);
$formfile = $CFG->dirroot . '/blocks/' . $blockname . '/edit_form.php';
if (is_readable($formfile)) {
require_once($CFG->dirroot . '/blocks/edit_form.php');
require_once($formfile);
$classname = 'block_' . $blockname . '_edit_form';
if (!class_exists($classname)) {
$classname = 'block_edit_form';
}
} else {
require_once($CFG->dirroot . '/blocks/edit_form.php');
$classname = 'block_edit_form';
}
return $classname;
}
/**
* Handle showing or hiding a block.
* @return boolean true if anything was done. False if not.
@ -1749,140 +1789,17 @@ class block_manager {
$output = $editpage->get_renderer('core');
$OUTPUT = $output;
$formfile = $CFG->dirroot . '/blocks/' . $block->name() . '/edit_form.php';
if (is_readable($formfile)) {
require_once($formfile);
$classname = 'block_' . $block->name() . '_edit_form';
if (!class_exists($classname)) {
$classname = 'block_edit_form';
}
} else {
$classname = 'block_edit_form';
}
$mform = new $classname($editpage->url, $block, $this->page);
$classname = self::get_block_edit_form_class($block->name());
/** @var block_edit_form $mform */
$mform = new $classname($editpage->url->out(false), ['page' => $this->page, 'block' => $block, 'actionbuttons' => true]);
$mform->set_data($block->instance);
if ($mform->is_cancelled()) {
redirect($this->page->url);
} else if ($data = $mform->get_data()) {
$bi = new stdClass;
$bi->id = $block->instance->id;
// This may get overwritten by the special case handling below.
$bi->pagetypepattern = $data->bui_pagetypepattern;
$bi->showinsubcontexts = (bool) $data->bui_contexts;
if (empty($data->bui_subpagepattern) || $data->bui_subpagepattern == '%@NULL@%') {
$bi->subpagepattern = null;
} else {
$bi->subpagepattern = $data->bui_subpagepattern;
}
$systemcontext = context_system::instance();
$frontpagecontext = context_course::instance(SITEID);
$parentcontext = context::instance_by_id($data->bui_parentcontextid);
// Updating stickiness and contexts. See MDL-21375 for details.
if (has_capability('moodle/site:manageblocks', $parentcontext)) { // Check permissions in destination
// Explicitly set the default context
$bi->parentcontextid = $parentcontext->id;
if ($data->bui_editingatfrontpage) { // The block is being edited on the front page
// The interface here is a special case because the pagetype pattern is
// totally derived from the context menu. Here are the excpetions. MDL-30340
switch ($data->bui_contexts) {
case BUI_CONTEXTS_ENTIRE_SITE:
// The user wants to show the block across the entire site
$bi->parentcontextid = $systemcontext->id;
$bi->showinsubcontexts = true;
$bi->pagetypepattern = '*';
break;
case BUI_CONTEXTS_FRONTPAGE_SUBS:
// The user wants the block shown on the front page and all subcontexts
$bi->parentcontextid = $frontpagecontext->id;
$bi->showinsubcontexts = true;
$bi->pagetypepattern = '*';
break;
case BUI_CONTEXTS_FRONTPAGE_ONLY:
// The user want to show the front page on the frontpage only
$bi->parentcontextid = $frontpagecontext->id;
$bi->showinsubcontexts = false;
$bi->pagetypepattern = 'site-index';
// This is the only relevant page type anyway but we'll set it explicitly just
// in case the front page grows site-index-* subpages of its own later
break;
}
}
}
$bits = explode('-', $bi->pagetypepattern);
// hacks for some contexts
if (($parentcontext->contextlevel == CONTEXT_COURSE) && ($parentcontext->instanceid != SITEID)) {
// For course context
// is page type pattern is mod-*, change showinsubcontext to 1
if ($bits[0] == 'mod' || $bi->pagetypepattern == '*') {
$bi->showinsubcontexts = 1;
} else {
$bi->showinsubcontexts = 0;
}
} else if ($parentcontext->contextlevel == CONTEXT_USER) {
// for user context
// subpagepattern should be null
if ($bits[0] == 'user' or $bits[0] == 'my') {
// we don't need subpagepattern in usercontext
$bi->subpagepattern = null;
}
}
$bi->defaultregion = $data->bui_defaultregion;
$bi->defaultweight = $data->bui_defaultweight;
$bi->timemodified = time();
$DB->update_record('block_instances', $bi);
if (!empty($block->config)) {
$config = clone($block->config);
} else {
$config = new stdClass;
}
foreach ($data as $configfield => $value) {
if (strpos($configfield, 'config_') !== 0) {
continue;
}
$field = substr($configfield, 7);
$config->$field = $value;
}
$block->instance_config_save($config);
$bp = new stdClass;
$bp->visible = $data->bui_visible;
$bp->region = $data->bui_region;
$bp->weight = $data->bui_weight;
$needbprecord = !$data->bui_visible || $data->bui_region != $data->bui_defaultregion ||
$data->bui_weight != $data->bui_defaultweight;
if ($block->instance->blockpositionid && !$needbprecord) {
$DB->delete_records('block_positions', array('id' => $block->instance->blockpositionid));
} else if ($block->instance->blockpositionid && $needbprecord) {
$bp->id = $block->instance->blockpositionid;
$DB->update_record('block_positions', $bp);
} else if ($needbprecord) {
$bp->blockinstanceid = $block->instance->id;
$bp->contextid = $this->page->context->id;
$bp->pagetype = $this->page->pagetype;
if ($this->page->subpage) {
$bp->subpage = $this->page->subpage;
} else {
$bp->subpage = '';
}
$DB->insert_record('block_positions', $bp);
}
$this->save_block_data($block, $data);
redirect($this->page->url);
} else {
@ -1908,6 +1825,132 @@ class block_manager {
}
}
/**
* Updates block configuration in the database
*
* @param block_base $block
* @param stdClass $data data from the block edit form
* @return void
*/
public function save_block_data(block_base $block, stdClass $data): void {
global $DB;
$bi = new stdClass;
$bi->id = $block->instance->id;
// This may get overwritten by the special case handling below.
$bi->pagetypepattern = $data->bui_pagetypepattern;
$bi->showinsubcontexts = (bool) $data->bui_contexts;
if (empty($data->bui_subpagepattern) || $data->bui_subpagepattern == '%@NULL@%') {
$bi->subpagepattern = null;
} else {
$bi->subpagepattern = $data->bui_subpagepattern;
}
$systemcontext = context_system::instance();
$frontpagecontext = context_course::instance(SITEID);
$parentcontext = context::instance_by_id($data->bui_parentcontextid);
// Updating stickiness and contexts. See MDL-21375 for details.
if (has_capability('moodle/site:manageblocks', $parentcontext)) { // Check permissions in destination.
// Explicitly set the default context.
$bi->parentcontextid = $parentcontext->id;
if ($data->bui_editingatfrontpage) { // The block is being edited on the front page.
// The interface here is a special case because the pagetype pattern is
// totally derived from the context menu. Here are the excpetions. MDL-30340 .
switch ($data->bui_contexts) {
case BUI_CONTEXTS_ENTIRE_SITE:
// The user wants to show the block across the entire site.
$bi->parentcontextid = $systemcontext->id;
$bi->showinsubcontexts = true;
$bi->pagetypepattern = '*';
break;
case BUI_CONTEXTS_FRONTPAGE_SUBS:
// The user wants the block shown on the front page and all subcontexts.
$bi->parentcontextid = $frontpagecontext->id;
$bi->showinsubcontexts = true;
$bi->pagetypepattern = '*';
break;
case BUI_CONTEXTS_FRONTPAGE_ONLY:
// The user want to show the front page on the frontpage only.
$bi->parentcontextid = $frontpagecontext->id;
$bi->showinsubcontexts = false;
$bi->pagetypepattern = 'site-index';
// This is the only relevant page type anyway but we'll set it explicitly just
// in case the front page grows site-index-* subpages of its own later.
break;
}
}
}
$bits = explode('-', $bi->pagetypepattern);
// Hacks for some contexts.
if (($parentcontext->contextlevel == CONTEXT_COURSE) && ($parentcontext->instanceid != SITEID)) {
// For course context
// is page type pattern is mod-*, change showinsubcontext to 1.
if ($bits[0] == 'mod' || $bi->pagetypepattern == '*') {
$bi->showinsubcontexts = 1;
} else {
$bi->showinsubcontexts = 0;
}
} else if ($parentcontext->contextlevel == CONTEXT_USER) {
// For user context subpagepattern should be null.
if ($bits[0] == 'user' || $bits[0] == 'my') {
// We don't need subpagepattern in usercontext.
$bi->subpagepattern = null;
}
}
$bi->defaultregion = $data->bui_defaultregion;
$bi->defaultweight = $data->bui_defaultweight;
$bi->timemodified = time();
$DB->update_record('block_instances', $bi);
if (!empty($block->config)) {
$config = clone($block->config);
} else {
$config = new stdClass;
}
foreach ($data as $configfield => $value) {
if (strpos($configfield, 'config_') !== 0) {
continue;
}
$field = substr($configfield, 7);
$config->$field = $value;
}
$block->instance_config_save($config);
$bp = new stdClass;
$bp->visible = $data->bui_visible;
$bp->region = $data->bui_region;
$bp->weight = $data->bui_weight;
$needbprecord = !$data->bui_visible || $data->bui_region != $data->bui_defaultregion ||
$data->bui_weight != $data->bui_defaultweight;
if ($block->instance->blockpositionid && !$needbprecord) {
$DB->delete_records('block_positions', array('id' => $block->instance->blockpositionid));
} else if ($block->instance->blockpositionid && $needbprecord) {
$bp->id = $block->instance->blockpositionid;
$DB->update_record('block_positions', $bp);
} else if ($needbprecord) {
$bp->blockinstanceid = $block->instance->id;
$bp->contextid = $this->page->context->id;
$bp->pagetype = $this->page->pagetype;
if ($this->page->subpage) {
$bp->subpage = $this->page->subpage;
} else {
$bp->subpage = '';
}
$DB->insert_record('block_positions', $bp);
}
}
/**
* Handle showing/processing the submission from the block editing form.
* @return boolean true if the form was submitted and the new config saved. Does not
@ -2081,7 +2124,7 @@ function block_instance_by_id($blockinstanceid) {
* Creates a new instance of the specified block class.
*
* @param string $blockname the name of the block.
* @param $instance block_instances DB table row (optional).
* @param stdClass $instance block_instances DB table row (optional).
* @param moodle_page $page the page this block is appearing on.
* @return block_base the requested block instance.
*/
@ -2090,6 +2133,7 @@ function block_instance($blockname, $instance = NULL, $page = NULL) {
return false;
}
$classname = 'block_'.$blockname;
/** @var block_base $retval */
$retval = new $classname;
if($instance !== NULL) {
if (is_null($page)) {

View File

@ -60,6 +60,8 @@ class dynamic_form extends external_api {
$formclass = $params['form'];
parse_str($params['formdata'], $formdata);
self::autoload_block_edit_form($formclass);
if (!class_exists($formclass) || !is_subclass_of($formclass, \core_form\dynamic_form::class)) {
// For security reason we don't throw exception "class does not exist" but rather an access exception.
throw new \moodle_exception('nopermissionform', 'core_form');
@ -85,6 +87,22 @@ class dynamic_form extends external_api {
return $output;
}
/**
* Special autoloading for block forms.
*
* @param string $formclass
* @return void
*/
protected static function autoload_block_edit_form(string $formclass): void {
global $CFG;
if (preg_match('/^block_([\w_]+)_edit_form$/', $formclass, $matches)) {
\block_manager::get_block_edit_form_class($matches[1]);
}
if ($formclass === 'block_edit_form') {
require_once($CFG->dirroot . '/blocks/edit_form.php');
}
}
/**
* Return for modal
* @return external_single_structure

View File

@ -4229,8 +4229,8 @@ class flat_navigation extends navigation_node_collection {
$addblockurl = "?{$url->get_query_string(false)}";
$PAGE->requires->js_call_amd('core/addblockmodal', 'init',
[$PAGE->pagetype, $PAGE->pagelayout, $addblockurl]);
$PAGE->requires->js_call_amd('core_block/add_modal', 'init',
[$addblockurl, $this->page->get_edited_page_hash()]);
}
}

View File

@ -5088,6 +5088,10 @@ EOD;
[
'link' => $url->out(false),
'escapedlink' => "?{$url->get_query_string(false)}",
'pagehash' => $this->page->get_edited_page_hash(),
'blockregion' => $region,
// The following parameters are not used since Moodle 4.2 but are
// still passed for backward-compatibility.
'pageType' => $this->page->pagetype,
'pageLayout' => $this->page->pagelayout,
'subPage' => $this->page->subpage,

View File

@ -371,12 +371,8 @@ class page_requirements_manager {
// Include block drag/drop if editing is on
if ($page->user_is_editing()) {
$params = array(
'courseid' => $page->course->id,
'pagetype' => $page->pagetype,
'pagelayout' => $page->pagelayout,
'subpage' => $page->subpage,
'regions' => $page->blocks->get_regions(),
'contextid' => $page->context->id,
'pagehash' => $page->get_edited_page_hash(),
);
if (!empty($page->cm->id)) {
$params['cmid'] = $page->cm->id;
@ -387,6 +383,7 @@ class page_requirements_manager {
'emptydragdropregion'),
'moodle');
$page->requires->yui_module('moodle-core-blocks', 'M.core_blocks.init_dragdrop', array($params), null, true);
$page->requires->js_call_amd('core_block/edit', 'init', ['pagehash' => $page->get_edited_page_hash()]);
}
// Include the YUI CSS Modules.

View File

@ -1637,6 +1637,120 @@ class moodle_page {
throw new coding_exception('verify_https_required() cannot be used anymore.');
}
/**
* Allows to 'serialize' the edited page information and store it in the session cache
*
* Due to Moodle architectural decision and non-SPA approach, a lot of page setup is
* happening in the actual page php file, for example, setting course/cm/context,
* setting layout and pagetype, requiring capabilities, setting specific block editing
* capabilities.
*
* When storing this information in the session cache we can pass the pagehash (cache key)
* as an argument to web services in AJAX requests and retrieve all data associated with
* the page without actually executing PHP code on that page.
*
* @return string|null
*/
public function get_edited_page_hash(): ?string {
global $SESSION;
if (!$this->user_is_editing()) {
return null;
}
$url = new moodle_url($this->url);
$url->set_anchor(null);
$data = [
'contextid' => $this->context->id,
'url' => $url->out_as_local_url(false),
];
if (($cm = $this->cm) && $cm->id) {
$data['cmid'] = $cm->id;
} else if (($course = $this->course) && $course->id) {
$data['courseid'] = $course->id;
}
$keys = ['pagelayout', 'pagetype', 'subpage'];
foreach ($keys as $key) {
if ("{$this->$key}" !== "") {
$data[$key] = $this->$key;
}
}
if ($this->_blockseditingcap !== 'moodle/site:manageblocks') {
$data['bcap'] = $this->_blockseditingcap;
}
if (!empty($this->_othereditingcaps)) {
$data['caps'] = $this->_othereditingcaps;
}
if ($this->_forcelockallblocks) {
$data['forcelock'] = true;
}
$hash = md5(json_encode($data + ['sesskey' => sesskey()]));
$SESSION->editedpages = ($SESSION->editedpages ?? []);
$SESSION->editedpages[$hash] = $data;
return $hash;
}
/**
* Retrieves a page that is being edited from the session cache
*
* {@see self::get_edited_page_hash()}
*
* @param string $hash
* @param int $strictness
* @return self|null
*/
public static function retrieve_edited_page(string $hash, $strictness = IGNORE_MISSING): ?self {
global $CFG, $SESSION;
$data = $SESSION->editedpages[$hash] ?? null;
if (!$data || !is_array($data)
|| $hash !== md5(json_encode($data + ['sesskey' => sesskey()]))) {
// This can happen if the session cache becomes corrupt or the user logged out and back
// in in another window and changed their session. Refreshing the page will generate
// and store the correct page hash.
if ($strictness === MUST_EXIST) {
throw new moodle_exception('editedpagenotfound');
}
return null;
}
if (!empty($CFG->moodlepageclass)) {
if (!empty($CFG->moodlepageclassfile)) {
require_once($CFG->moodlepageclassfile);
}
$classname = $CFG->moodlepageclass;
} else {
$classname = self::class;
}
/** @var moodle_page $page */
$page = new $classname();
$page->set_context(context::instance_by_id($data['contextid']));
if (array_key_exists('cmid', $data)) {
[$course, $cm] = get_course_and_cm_from_cmid($data['cmid']);
$page->set_cm($cm, $course);
} else if (array_key_exists('courseid', $data)) {
$page->set_course(get_course($data['courseid']));
}
$page->set_url(new moodle_url($data['url']));
$keys = ['pagelayout', 'pagetype', 'subpage'];
foreach ($keys as $key) {
if (array_key_exists($key, $data)) {
$func = "set_{$key}";
$page->$func($data[$key]);
}
}
if (array_key_exists('bcap', $data)) {
$page->set_blocks_editing_capability($data['bcap']);
}
if (array_key_exists('caps', $data)) {
foreach ($data['caps'] as $cap) {
$page->set_other_editing_capability($cap);
}
}
if (array_key_exists('forcelock', $data)) {
$page->force_lock_all_blocks();
}
$page->blocks->add_custom_regions_for_pagetype($page->pagetype);
return $page;
}
// Initialisation methods =====================================================
// These set various things up in a default way.

View File

@ -25,14 +25,20 @@
Example context (json):
{
"blocks" : [ { "name": "test", "title": "Test block" } ],
"blocks" : [
{ "name": "test", "title": "Test block" },
{ "name": "html", "title": "Block with form", "blockform": "block_edit_form" }
],
"url" : "?a=b"
}
}}
<div class="list-group">
{{#blocks}}
<a href="{{url}}&amp;bui_addblock={{name}}" class="list-group-item list-group-item-action">{{title}}</a>
<a href="{{url}}&amp;bui_addblock={{name}}" class="list-group-item list-group-item-action"
data-blockname="{{name}}" data-blocktitle="{{title}}" data-blockregion="{{blockregion}}"
{{#blockform}}data-action="showaddblockform" data-blockform="{{blockform}}"{{/blockform}}
>{{#blockform}}{{#str}}textellipsis, moodle, {{title}}{{/str}}{{/blockform}}{{^blockform}}{{title}}{{/blockform}}</a>
{{/blocks}}
{{^blocks}}
<div class="alert alert-primary" role="alert">

View File

@ -23,21 +23,21 @@
{
"link" : "/my/index.php?bui_addblock&bui_blockregion=content&sesskey=M3mes",
"escapedlink" : "?bui_addblock&bui_blockregion=content&sesskey=M3mes",
"pageType" : "my-index",
"pageLayout" : "mydashboard",
"subPage": "15"
"pagehash": "abcdefgh",
"blockregion": "side-pre"
}
}}
<div class="add_block_button">
<a href="{{link}}" id="addblock-{{uniqid}}" class="btn btn-link block-add text-left mb-3" data-key="addblock" data-url="{{escapedlink}}">
<a href="{{link}}" id="addblock-{{uniqid}}" class="btn btn-link block-add text-left mb-3" data-key="addblock"
data-url="{{escapedlink}}" data-blockregion="{{blockregion}}">
<i class="fa fa-plus py-2 mr-3" aria-hidden="true"></i>{{#str}}addblock{{/str}}
</a>
</div>
{{#js}}
// Initialise the JS for the modal window which displays the blocks available to add.
require(['core/addblockmodal'], function(addBlockModal) {
addBlockModal.init('{{pageType}}', '{{pageLayout}}', null, '{{subPage}}');
require(['core_block/add_modal'], function(addBlockModal) {
addBlockModal.init(null, '{{pagehash}}');
});
{{/js}}

View File

@ -261,11 +261,7 @@ Y.extend(DRAGBLOCK, M.core.dragdrop, {
// Prepare request parameters
var params = {
sesskey: M.cfg.sesskey,
courseid: this.get('courseid'),
pagelayout: this.get('pagelayout'),
pagetype: this.get('pagetype'),
subpage: this.get('subpage'),
contextid: this.get('contextid'),
pagehash: this.get('pagehash'),
action: 'move',
bui_moveid: this.get_block_id(dragnode),
bui_newregion: this.get_block_region(dropnode)
@ -311,22 +307,7 @@ Y.extend(DRAGBLOCK, M.core.dragdrop, {
}, {
NAME: 'core-blocks-dragdrop',
ATTRS: {
courseid: {
value: null
},
cmid: {
value: null
},
contextid: {
value: null
},
pagelayout: {
value: null
},
pagetype: {
value: null
},
subpage: {
pagehash: {
value: null
},
regions: {
@ -706,11 +687,7 @@ MANAGER.prototype = {
// Prepare request parameters
var params = {
sesskey: M.cfg.sesskey,
courseid: this.get('courseid'),
pagelayout: this.get('pagelayout'),
pagetype: this.get('pagetype'),
subpage: this.get('subpage'),
contextid: this.get('contextid'),
pagehash: this.get('pagehash'),
action: 'move',
bui_moveid: this.get_block_id(dragnode),
bui_newregion: this.get_block_region(dropnode)
@ -761,62 +738,12 @@ Y.extend(MANAGER, M.core.dragdrop, MANAGER.prototype, {
NAME: 'core-blocks-dragdrop-manager',
ATTRS: {
/**
* The Course ID if there is one.
* @attribute courseid
* @type int|null
* @default null
*/
courseid: {
value: null
},
/**
* The Course Module ID if there is one.
* @attribute cmid
* @type int|null
* @default null
*/
cmid: {
value: null
},
/**
* The Context ID.
* @attribute contextid
* @type int|null
* @default null
*/
contextid: {
value: null
},
/**
* The current page layout.
* @attribute pagelayout
* The page identifier.
* @attribute pagehash
* @type string|null
* @default null
*/
pagelayout: {
value: null
},
/**
* The page type string, should be used as the id for the body tag in the theme.
* @attribute pagetype
* @type string|null
* @default null
*/
pagetype: {
value: null
},
/**
* The subpage identifier, if any.
* @attribute subpage
* @type string|null
* @default null
*/
subpage: {
pagehash: {
value: null
},

File diff suppressed because one or more lines are too long

View File

@ -261,11 +261,7 @@ Y.extend(DRAGBLOCK, M.core.dragdrop, {
// Prepare request parameters
var params = {
sesskey: M.cfg.sesskey,
courseid: this.get('courseid'),
pagelayout: this.get('pagelayout'),
pagetype: this.get('pagetype'),
subpage: this.get('subpage'),
contextid: this.get('contextid'),
pagehash: this.get('pagehash'),
action: 'move',
bui_moveid: this.get_block_id(dragnode),
bui_newregion: this.get_block_region(dropnode)
@ -311,22 +307,7 @@ Y.extend(DRAGBLOCK, M.core.dragdrop, {
}, {
NAME: 'core-blocks-dragdrop',
ATTRS: {
courseid: {
value: null
},
cmid: {
value: null
},
contextid: {
value: null
},
pagelayout: {
value: null
},
pagetype: {
value: null
},
subpage: {
pagehash: {
value: null
},
regions: {
@ -701,11 +682,7 @@ MANAGER.prototype = {
// Prepare request parameters
var params = {
sesskey: M.cfg.sesskey,
courseid: this.get('courseid'),
pagelayout: this.get('pagelayout'),
pagetype: this.get('pagetype'),
subpage: this.get('subpage'),
contextid: this.get('contextid'),
pagehash: this.get('pagehash'),
action: 'move',
bui_moveid: this.get_block_id(dragnode),
bui_newregion: this.get_block_region(dropnode)
@ -756,62 +733,12 @@ Y.extend(MANAGER, M.core.dragdrop, MANAGER.prototype, {
NAME: 'core-blocks-dragdrop-manager',
ATTRS: {
/**
* The Course ID if there is one.
* @attribute courseid
* @type int|null
* @default null
*/
courseid: {
value: null
},
/**
* The Course Module ID if there is one.
* @attribute cmid
* @type int|null
* @default null
*/
cmid: {
value: null
},
/**
* The Context ID.
* @attribute contextid
* @type int|null
* @default null
*/
contextid: {
value: null
},
/**
* The current page layout.
* @attribute pagelayout
* The page identifier.
* @attribute pagehash
* @type string|null
* @default null
*/
pagelayout: {
value: null
},
/**
* The page type string, should be used as the id for the body tag in the theme.
* @attribute pagetype
* @type string|null
* @default null
*/
pagetype: {
value: null
},
/**
* The subpage identifier, if any.
* @attribute subpage
* @type string|null
* @default null
*/
subpage: {
pagehash: {
value: null
},

View File

@ -256,11 +256,7 @@ Y.extend(DRAGBLOCK, M.core.dragdrop, {
// Prepare request parameters
var params = {
sesskey: M.cfg.sesskey,
courseid: this.get('courseid'),
pagelayout: this.get('pagelayout'),
pagetype: this.get('pagetype'),
subpage: this.get('subpage'),
contextid: this.get('contextid'),
pagehash: this.get('pagehash'),
action: 'move',
bui_moveid: this.get_block_id(dragnode),
bui_newregion: this.get_block_region(dropnode)
@ -306,22 +302,7 @@ Y.extend(DRAGBLOCK, M.core.dragdrop, {
}, {
NAME: 'core-blocks-dragdrop',
ATTRS: {
courseid: {
value: null
},
cmid: {
value: null
},
contextid: {
value: null
},
pagelayout: {
value: null
},
pagetype: {
value: null
},
subpage: {
pagehash: {
value: null
},
regions: {

View File

@ -313,11 +313,7 @@ MANAGER.prototype = {
// Prepare request parameters
var params = {
sesskey: M.cfg.sesskey,
courseid: this.get('courseid'),
pagelayout: this.get('pagelayout'),
pagetype: this.get('pagetype'),
subpage: this.get('subpage'),
contextid: this.get('contextid'),
pagehash: this.get('pagehash'),
action: 'move',
bui_moveid: this.get_block_id(dragnode),
bui_newregion: this.get_block_region(dropnode)
@ -368,62 +364,12 @@ Y.extend(MANAGER, M.core.dragdrop, MANAGER.prototype, {
NAME: 'core-blocks-dragdrop-manager',
ATTRS: {
/**
* The Course ID if there is one.
* @attribute courseid
* @type int|null
* @default null
*/
courseid: {
value: null
},
/**
* The Course Module ID if there is one.
* @attribute cmid
* @type int|null
* @default null
*/
cmid: {
value: null
},
/**
* The Context ID.
* @attribute contextid
* @type int|null
* @default null
*/
contextid: {
value: null
},
/**
* The current page layout.
* @attribute pagelayout
* The page identifier.
* @attribute pagehash
* @type string|null
* @default null
*/
pagelayout: {
value: null
},
/**
* The page type string, should be used as the id for the body tag in the theme.
* @attribute pagetype
* @type string|null
* @default null
*/
pagetype: {
value: null
},
/**
* The subpage identifier, if any.
* @attribute subpage
* @type string|null
* @default null
*/
subpage: {
pagehash: {
value: null
},

View File

@ -92,14 +92,14 @@ Feature: Run tests over my courses.
Given I log in as "admin"
And I am on site homepage
And I turn editing mode on
And I add the "Text" block
And I configure the "(new text block)" block
And I set the following fields to these values:
| Page contexts | Display throughout the entire site |
And I add the "Text" block to the default region with:
| Text block title | Text on all pages |
| Content | This is visible on all pages |
And I configure the "Text on all pages" block
And I set the following fields to these values:
| Page contexts | Display throughout the entire site |
| Default region | Right |
And I press "Save changes"
And I click on "Save changes" "button" in the "Configure Text on all pages block" "dialogue"
And I should see "This is visible on all pages"
And "Move Text on all pages block" "menuitem" should exist in the "Text on all pages" "block"
When I am on the "My courses" page

View File

@ -11,14 +11,14 @@ Feature: My courses page block layout in Boost theme
And I log in as "admin"
And I am on site homepage
And I turn editing mode on
And I add the "Text" block
And I configure the "(new text block)" block
And I set the following fields to these values:
| Page contexts | Display throughout the entire site |
And I add the "Text" block to the default region with:
| Text block title | Text on all pages |
| Content | This is visible on all pages |
And I configure the "Text on all pages" block
And I set the following fields to these values:
| Page contexts | Display throughout the entire site |
| Default region | Right |
And I press "Save changes"
And I click on "Save changes" "button" in the "Configure Text on all pages block" "dialogue"
Scenario: Student can see relevant blocks with correct placement on my courses page
When I log in as "student1"

View File

@ -1,4 +1,5 @@
<?php
use Behat\Gherkin\Node\TableNode;
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
@ -56,6 +57,38 @@ class behat_theme_classic_behat_blocks extends behat_blocks {
}
}
/**
* Adds the selected block to the specified region
*
* Editing mode must be previously enabled.
*
* @param string $blockname
* @param string $region
*/
public function i_add_the_block_to_the_region(string $blockname, string $region) {
$this->execute('behat_blocks::i_add_the_block', [$blockname]);
}
/**
* Adds the selected block to the specified region and fills configuration form.
*
* Editing mode must be previously enabled.
*
* @param string $blockname
* @param string $region
* @param TableNode $data
*/
public function i_add_the_block_to_the_region_with(string $blockname, string $region, TableNode $data) {
$this->execute('behat_blocks::i_add_the_block_to_the_region', [$blockname, $region]);
$this->wait_for_pending_js();
$blocktitle = $blockname === 'Text' ? '(new text block)' : $blockname;
$this->execute('behat_blocks::i_configure_the_block', [$blocktitle]);
$dialogname = get_string('configureblock', 'core_block', $blocktitle);
$this->execute('behat_forms::i_set_the_following_fields_in_container_to_these_values',
[$dialogname, "dialogue", $data]);
$this->execute('behat_general::i_click_on_in_the', ["Save changes", 'button', $dialogname, 'dialogue']);
}
/**
* Ensures that block can be added to the page, but does not add it.
*