mirror of
https://github.com/moodle/moodle.git
synced 2025-04-21 08:22:07 +02:00
Merge branch 'MDL-69331-master' of git://github.com/sarjona/moodle
This commit is contained in:
commit
95e9ccea79
@ -1,11 +1,15 @@
|
||||
@core @core_backup @core_contentbank
|
||||
@core @core_backup @core_contentbank @core_h5p @contenttype_h5p @_file_upload @javascript
|
||||
Feature: Import course content bank content
|
||||
In order to import content from a course contentbank
|
||||
As a teacher
|
||||
I need to confirm that errors will not happen
|
||||
|
||||
Background:
|
||||
Given the following "courses" exist:
|
||||
Given I log in as "admin"
|
||||
And I navigate to "H5P > Manage H5P content types" in site administration
|
||||
And I upload "h5p/tests/fixtures/ipsums.h5p" file to "H5P content type" filemanager
|
||||
And I click on "Upload H5P content types" "button" in the "#fitem_id_uploadlibraries" "css_element"
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname | category |
|
||||
| Course 1 | C1 | 0 |
|
||||
| Course 2 | C2 | 0 |
|
||||
@ -17,8 +21,9 @@ Feature: Import course content bank content
|
||||
| teacher1 | C1 | editingteacher |
|
||||
| teacher1 | C2 | editingteacher |
|
||||
And the following "contentbank content" exist:
|
||||
| contextlevel | reference | contenttype | user | contentname |
|
||||
| Course | C1 | contenttype_h5p | teacher1 | ipsums.h5p |
|
||||
| contextlevel | reference | contenttype | user | contentname | filepath |
|
||||
| Course | C1 | contenttype_h5p | teacher1 | ipsums.h5p | /h5p/tests/fixtures/ipsums.h5p |
|
||||
And I log out
|
||||
And I log in as "teacher1"
|
||||
|
||||
Scenario: Import content bank content to another course
|
||||
|
@ -151,16 +151,35 @@ class upload_files extends \core_form\dynamic_form {
|
||||
if (!empty($files)) {
|
||||
$file = reset($files);
|
||||
$cb = new \core_contentbank\contentbank();
|
||||
if ($this->get_data()->id) {
|
||||
$content = $cb->get_content_from_id($this->get_data()->id);
|
||||
$contenttype = $content->get_content_type_instance();
|
||||
$content = $contenttype->replace_content($file, $content);
|
||||
} else {
|
||||
$content = $cb->create_content_from_file($this->get_context_for_dynamic_submission(), $USER->id, $file);
|
||||
try {
|
||||
if ($this->get_data()->id) {
|
||||
$content = $cb->get_content_from_id($this->get_data()->id);
|
||||
$contenttype = $content->get_content_type_instance();
|
||||
$content = $contenttype->replace_content($file, $content);
|
||||
} else {
|
||||
$content = $cb->create_content_from_file($this->get_context_for_dynamic_submission(), $USER->id, $file);
|
||||
}
|
||||
$params = ['id' => $content->get_id(), 'contextid' => $this->get_context_for_dynamic_submission()->id];
|
||||
$url = new \moodle_url('/contentbank/view.php', $params);
|
||||
} catch (\Exception $e) {
|
||||
// Redirect to the right page (depending on if content is new or existing) and display an error.
|
||||
if ($this->get_data()->id) {
|
||||
$content = $cb->get_content_from_id($this->get_data()->id);
|
||||
$params = [
|
||||
'id' => $content->get_id(),
|
||||
'contextid' => $this->get_context_for_dynamic_submission()->id,
|
||||
'errormsg' => 'notvalidpackage',
|
||||
];
|
||||
$url = new \moodle_url('/contentbank/view.php', $params);
|
||||
} else {
|
||||
$url = new \moodle_url('/contentbank/index.php', [
|
||||
'contextid' => $this->get_context_for_dynamic_submission()->id,
|
||||
'errormsg' => 'notvalidpackage'],
|
||||
);
|
||||
}
|
||||
}
|
||||
$params = ['id' => $content->get_id(), 'contextid' => $this->get_context_for_dynamic_submission()->id];
|
||||
$viewurl = new \moodle_url('/contentbank/view.php', $params);
|
||||
return ['returnurl' => $viewurl->out(false)];
|
||||
|
||||
return ['returnurl' => $url->out(false)];
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -24,9 +24,6 @@
|
||||
|
||||
namespace contenttype_h5p;
|
||||
|
||||
use stdClass;
|
||||
use html_writer;
|
||||
|
||||
/**
|
||||
* H5P Content manager class
|
||||
*
|
||||
@ -36,4 +33,59 @@ use html_writer;
|
||||
*/
|
||||
class content extends \core_contentbank\content {
|
||||
|
||||
/**
|
||||
* Returns user has access permission for the content itself.
|
||||
* If the H5P content-type library is disabled, the user won't have access to it.
|
||||
*
|
||||
* @return bool True if content could be accessed. False otherwise.
|
||||
*/
|
||||
public function is_view_allowed(): bool {
|
||||
// Force H5P content to be deployed.
|
||||
$fileurl = $this->get_file_url();
|
||||
// Skip capability check when creating the H5P content (because it has been created by trusted users).
|
||||
$h5pplayer = new \core_h5p\player($fileurl, new \stdClass(), true, '', true);
|
||||
// Flush error messages.
|
||||
$h5pplayer->get_messages();
|
||||
|
||||
// Check if the H5P entry has been created and if the main library is enabled.
|
||||
$file = $this->get_file();
|
||||
if (!empty($file)) {
|
||||
$h5p = \core_h5p\api::get_content_from_pathnamehash($file->get_pathnamehash());
|
||||
if (empty($h5p)) {
|
||||
// If there is no H5P entry for this content, it won't be displayed unless the user has the manageanycontent
|
||||
// capability. Reasons for contents without a proper H5P entry in DB:
|
||||
// - Invalid H5P package (it won't be never deployed).
|
||||
// - Disabled content-type library (it can't be deployed so there is no way to know the mainlibraryid).
|
||||
$context = \context::instance_by_id($this->content->contextid);
|
||||
if (!has_capability('moodle/contentbank:manageanycontent', $context)) {
|
||||
return false;
|
||||
}
|
||||
} else if (!\core_h5p\api::is_library_enabled((object) ['id' => $h5p->mainlibraryid])) {
|
||||
// If the main library is disabled, it won't be displayed.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return parent::is_view_allowed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Import a file as a valid content.
|
||||
* Before importing the file, this method will check if the file is a valid H5P package. If it's not valid, it will thrown
|
||||
* an exception.
|
||||
*
|
||||
* @throws \file_exception If file operations fail
|
||||
* @param \stored_file $file File to store in the content file area.
|
||||
* @return \stored_file|null the stored content file or null if the file is discarted.
|
||||
*/
|
||||
public function import_file(\stored_file $file): ?\stored_file {
|
||||
// The H5P content can be only deployed if the author of the .h5p file can update libraries or if all the
|
||||
// content-type libraries exist, to avoid users without the h5p:updatelibraries capability upload malicious content.
|
||||
$onlyupdatelibs = !\core_h5p\helper::can_update_library($file);
|
||||
|
||||
if (!\core_h5p\api::is_valid_package($file, $onlyupdatelibs)) {
|
||||
throw new \file_exception('invalidpackage');
|
||||
}
|
||||
return parent::import_file($file);
|
||||
}
|
||||
}
|
||||
|
@ -148,22 +148,25 @@ class contenttype extends \core_contentbank\contenttype {
|
||||
$types = [];
|
||||
$h5pfilestorage = new file_storage();
|
||||
foreach ($h5pcontenttypes as $h5pcontenttype) {
|
||||
$library = [
|
||||
'name' => $h5pcontenttype->machine_name,
|
||||
'majorVersion' => $h5pcontenttype->major_version,
|
||||
'minorVersion' => $h5pcontenttype->minor_version,
|
||||
];
|
||||
$key = H5PCore::libraryToString($library);
|
||||
$type = new stdClass();
|
||||
$type->key = $key;
|
||||
$type->typename = $h5pcontenttype->title;
|
||||
$type->typeeditorparams = 'library=' . $key;
|
||||
$type->typeicon = $h5pfilestorage->get_icon_url(
|
||||
$h5pcontenttype->id,
|
||||
$h5pcontenttype->machine_name,
|
||||
$h5pcontenttype->major_version,
|
||||
$h5pcontenttype->minor_version);
|
||||
$types[] = $type;
|
||||
if ($h5pcontenttype->enabled) {
|
||||
// Only enabled content-types will be displayed.
|
||||
$library = [
|
||||
'name' => $h5pcontenttype->machine_name,
|
||||
'majorVersion' => $h5pcontenttype->major_version,
|
||||
'minorVersion' => $h5pcontenttype->minor_version,
|
||||
];
|
||||
$key = H5PCore::libraryToString($library);
|
||||
$type = new stdClass();
|
||||
$type->key = $key;
|
||||
$type->typename = $h5pcontenttype->title;
|
||||
$type->typeeditorparams = 'library=' . $key;
|
||||
$type->typeicon = $h5pfilestorage->get_icon_url(
|
||||
$h5pcontenttype->id,
|
||||
$h5pcontenttype->machine_name,
|
||||
$h5pcontenttype->major_version,
|
||||
$h5pcontenttype->minor_version);
|
||||
$types[] = $type;
|
||||
}
|
||||
}
|
||||
|
||||
return $types;
|
||||
|
@ -1,4 +1,4 @@
|
||||
@core @core_contentbank @contenttype_h5p @_file_upload @_switch_iframe @javascript
|
||||
@core @core_contentbank @core_h5p @contenttype_h5p @_file_upload @_switch_iframe @javascript
|
||||
Feature: Replace H5P file from an existing content
|
||||
In order to replace an H5P content from the content bank
|
||||
As an admin
|
||||
|
@ -1,4 +1,4 @@
|
||||
@core @core_contentbank @contenttype_h5p @_file_upload @_switch_iframe @javascript
|
||||
@core @core_contentbank @core_h5p @contenttype_h5p @_file_upload @_switch_iframe @javascript
|
||||
Feature: H5P file upload to content bank for admins
|
||||
In order import new H5P content to content bank
|
||||
As an admin
|
||||
|
@ -0,0 +1,101 @@
|
||||
@core @core_contentbank @core_h5p @contenttype_h5p @_file_upload @javascript
|
||||
Feature: Disable H5P content-types from the content bank
|
||||
In order to disable H5P content-types
|
||||
As an admin
|
||||
I need to be able to check they are not displayed in the content bank
|
||||
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com |
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname | category |
|
||||
| Course 1 | C1 | 0 |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
And the following "contentbank contents" exist:
|
||||
| contextlevel | reference | contenttype | user | contentname | filepath |
|
||||
| Course | C1 | contenttype_h5p | admin | filltheblanks | /h5p/tests/fixtures/filltheblanks.h5p |
|
||||
| Course | C1 | contenttype_h5p | admin | accordion | /h5p/tests/fixtures/ipsums.h5p |
|
||||
| Course | C1 | contenttype_h5p | admin | invalidh5p | /h5p/tests/fixtures/h5ptest.zip |
|
||||
And I log in as "admin"
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
And I add the "Navigation" block if not present
|
||||
And I log out
|
||||
|
||||
Scenario: Teachers cannot view disabled or invalid content-types
|
||||
Given I log in as "teacher1"
|
||||
And I am on "Course 1" course homepage
|
||||
And I expand "Site pages" node
|
||||
And I click on "Content bank" "link"
|
||||
And I should see "accordion"
|
||||
And I should see "filltheblanks"
|
||||
And I should not see "invalidh5p"
|
||||
And I log out
|
||||
And I log in as "admin"
|
||||
And I navigate to "H5P > Manage H5P content types" in site administration
|
||||
And I click on "Disable" "link" in the "Accordion" "table_row"
|
||||
And I log out
|
||||
When I log in as "teacher1"
|
||||
And I am on "Course 1" course homepage
|
||||
And I expand "Site pages" node
|
||||
And I click on "Content bank" "link"
|
||||
Then I should not see "accordion"
|
||||
And I should see "filltheblanks"
|
||||
And I should not see "invalidh5p"
|
||||
|
||||
Scenario: Admins cannot view disabled content-types
|
||||
Given I log in as "admin"
|
||||
And I am on "Course 1" course homepage
|
||||
And I expand "Site pages" node
|
||||
And I click on "Content bank" "link"
|
||||
And I should see "accordion"
|
||||
And I should see "filltheblanks"
|
||||
And I should see "invalidh5p"
|
||||
And I navigate to "H5P > Manage H5P content types" in site administration
|
||||
And I click on "Disable" "link" in the "Accordion" "table_row"
|
||||
When I am on "Course 1" course homepage
|
||||
And I expand "Site pages" node
|
||||
And I click on "Content bank" "link"
|
||||
Then I should not see "accordion"
|
||||
And I should see "filltheblanks"
|
||||
And I should see "invalidh5p"
|
||||
|
||||
Scenario: Teachers cannot create disabled content-types
|
||||
Given I log in as "teacher1"
|
||||
And I am on "Course 1" course homepage
|
||||
And I expand "Site pages" node
|
||||
And I click on "Content bank" "link"
|
||||
And I click on "[data-action=Add-content]" "css_element"
|
||||
And I should see "Accordion"
|
||||
And I should see "Fill in the Blanks"
|
||||
And I log out
|
||||
And I log in as "admin"
|
||||
And I navigate to "H5P > Manage H5P content types" in site administration
|
||||
And I click on "Disable" "link" in the "Accordion" "table_row"
|
||||
And I log out
|
||||
When I log in as "teacher1"
|
||||
And I am on "Course 1" course homepage
|
||||
And I expand "Site pages" node
|
||||
And I click on "Content bank" "link"
|
||||
And I click on "[data-action=Add-content]" "css_element"
|
||||
Then I should not see "Accordion"
|
||||
And I should see "Fill in the Blanks"
|
||||
|
||||
Scenario: Admins cannot create disabled content-types
|
||||
Given I log in as "admin"
|
||||
And I am on "Course 1" course homepage
|
||||
And I expand "Site pages" node
|
||||
And I click on "Content bank" "link"
|
||||
And I click on "[data-action=Add-content]" "css_element"
|
||||
And I should see "Accordion"
|
||||
And I should see "Fill in the Blanks"
|
||||
And I navigate to "H5P > Manage H5P content types" in site administration
|
||||
And I click on "Disable" "link" in the "Accordion" "table_row"
|
||||
When I am on "Course 1" course homepage
|
||||
And I expand "Site pages" node
|
||||
And I click on "Content bank" "link"
|
||||
And I click on "[data-action=Add-content]" "css_element"
|
||||
Then I should not see "Accordion"
|
||||
And I should see "Fill in the Blanks"
|
@ -1,11 +1,17 @@
|
||||
@core @core_contentbank @contenttype_h5p @_file_upload @javascript
|
||||
@core @core_contentbank @core_h5p @contenttype_h5p @_file_upload @javascript
|
||||
Feature: Manage H5P content from the content bank
|
||||
In order to manage H5P content in the content bank
|
||||
As an admin
|
||||
I need to be able to edit any H5P content in the content bank
|
||||
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
Given I log in as "admin"
|
||||
And I navigate to "H5P > Manage H5P content types" in site administration
|
||||
And I upload "h5p/tests/fixtures/filltheblanks.h5p" file to "H5P content type" filemanager
|
||||
And I click on "Upload H5P content types" "button" in the "#fitem_id_uploadlibraries" "css_element"
|
||||
And I upload "h5p/tests/fixtures/ipsums.h5p" file to "H5P content type" filemanager
|
||||
And I click on "Upload H5P content types" "button" in the "#fitem_id_uploadlibraries" "css_element"
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com |
|
||||
And the following "courses" exist:
|
||||
@ -15,10 +21,9 @@ Feature: Manage H5P content from the content bank
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
And the following "contentbank content" exist:
|
||||
| contextlevel | reference | contenttype | user | contentname |
|
||||
| Course | C1 | contenttype_h5p | admin | filltheblanks.h5p |
|
||||
| Course | C1 | contenttype_h5p | teacher1 | ipsums.h5p |
|
||||
And I log in as "admin"
|
||||
| contextlevel | reference | contenttype | user | contentname | filepath |
|
||||
| Course | C1 | contenttype_h5p | admin | filltheblanks.h5p | /h5p/tests/fixtures/filltheblanks.h5p |
|
||||
| Course | C1 | contenttype_h5p | teacher1 | ipsums.h5p | /h5p/tests/fixtures/ipsums.h5p |
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
And I add the "Navigation" block if not present
|
||||
And I log out
|
||||
|
@ -1,11 +1,17 @@
|
||||
@core @core_contentbank @contenttype_h5p @_file_upload @_switch_iframe @javascript
|
||||
@core @core_contentbank @core_h5p @contenttype_h5p @_file_upload @_switch_iframe @javascript
|
||||
Feature: Replace H5P file from an existing content requires special capabilities
|
||||
In order replace an H5P content from the content bank
|
||||
As a teacher
|
||||
I need to be able to replace the content only if certain capabilities are allowed
|
||||
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
Given I log in as "admin"
|
||||
And I navigate to "H5P > Manage H5P content types" in site administration
|
||||
And I upload "h5p/tests/fixtures/ipsums.h5p" file to "H5P content type" filemanager
|
||||
And I click on "Upload H5P content types" "button" in the "#fitem_id_uploadlibraries" "css_element"
|
||||
And I upload "h5p/tests/fixtures/filltheblanks.h5p" file to "H5P content type" filemanager
|
||||
And I click on "Upload H5P content types" "button" in the "#fitem_id_uploadlibraries" "css_element"
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com |
|
||||
And the following "categories" exist:
|
||||
@ -21,6 +27,7 @@ Feature: Replace H5P file from an existing content requires special capabilities
|
||||
| contextlevel | reference | contenttype | user | contentname | filepath |
|
||||
| Course | C1 | contenttype_h5p | admin | admincontent | /h5p/tests/fixtures/ipsums.h5p |
|
||||
| Course | C1 | contenttype_h5p | teacher1 | teachercontent | /h5p/tests/fixtures/filltheblanks.h5p |
|
||||
And I log out
|
||||
And I log in as "teacher1"
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
And I add the "Navigation" block if not present
|
||||
|
@ -1,4 +1,4 @@
|
||||
@core @core_contentbank @contenttype_h5p @_file_upload @_switch_iframe @javascript
|
||||
@core @core_contentbank @core_h5p @contenttype_h5p @_file_upload @_switch_iframe @javascript
|
||||
Feature: H5P file upload to content bank for non admins
|
||||
In order import new H5P content to content bank
|
||||
As an admin
|
||||
@ -37,7 +37,14 @@ Feature: H5P file upload to content bank for non admins
|
||||
Then I should see "Content bank"
|
||||
|
||||
Scenario: Teachers can upload .h5p extension files to course content bank
|
||||
Given I am on "Course 1" course homepage with editing mode on
|
||||
Given I log out
|
||||
And I log in as "admin"
|
||||
And I navigate to "H5P > Manage H5P content types" in site administration
|
||||
And I upload "h5p/tests/fixtures/filltheblanks.h5p" file to "H5P content type" filemanager
|
||||
And I click on "Upload H5P content types" "button" in the "#fitem_id_uploadlibraries" "css_element"
|
||||
And I log out
|
||||
And I log in as "teacher1"
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
And I add the "Navigation" block if not present
|
||||
When I expand "Site pages" node
|
||||
And I click on "Content bank" "link"
|
||||
@ -52,7 +59,14 @@ Feature: H5P file upload to content bank for non admins
|
||||
And I should see "filltheblanks.h5p"
|
||||
|
||||
Scenario: Other teachers can see uploaded H5P contents
|
||||
Given I am on "Course 1" course homepage with editing mode on
|
||||
Given I log out
|
||||
And I log in as "admin"
|
||||
And I navigate to "H5P > Manage H5P content types" in site administration
|
||||
And I upload "h5p/tests/fixtures/filltheblanks.h5p" file to "H5P content type" filemanager
|
||||
And I click on "Upload H5P content types" "button" in the "#fitem_id_uploadlibraries" "css_element"
|
||||
And I log out
|
||||
And I log in as "teacher1"
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
And I add the "Navigation" block if not present
|
||||
When I expand "Site pages" node
|
||||
And I click on "Content bank" "link"
|
||||
@ -72,7 +86,7 @@ Feature: H5P file upload to content bank for non admins
|
||||
And I click on "Content bank" "link"
|
||||
Then I should see "filltheblanks.h5p"
|
||||
|
||||
Scenario: Teachers can not upload and deployed content types when libraries are not installed
|
||||
Scenario: Teachers can not upload and deploy content types when libraries are not installed
|
||||
Given I log out
|
||||
And I log in as "admin"
|
||||
And I navigate to "H5P > Manage H5P content types" in site administration
|
||||
@ -89,14 +103,14 @@ Feature: H5P file upload to content bank for non admins
|
||||
And I click on "filltheblanks.h5p" "link"
|
||||
And I click on "Select this file" "button"
|
||||
And I click on "Save changes" "button"
|
||||
And I switch to "h5p-player" class iframe
|
||||
Then I should not see "Of which countries"
|
||||
And I should see "missing-required-library"
|
||||
And I switch to the main frame
|
||||
Then I should see "Sorry, this file is not valid."
|
||||
And I should not see "filltheblanks.h5p"
|
||||
And I log out
|
||||
And I log in as "admin"
|
||||
And I navigate to "H5P > Manage H5P content types" in site administration
|
||||
And I should not see "Fill in the Blanks"
|
||||
And I am on "Course 1" course homepage
|
||||
And I expand "Site pages" node
|
||||
And I click on "Content bank" "link"
|
||||
And I should not see "filltheblanks.h5p"
|
||||
|
||||
Scenario: Teachers can not see existing contents when libraries are not installed
|
||||
Given I log out
|
||||
@ -138,8 +152,13 @@ Feature: H5P file upload to content bank for non admins
|
||||
Given I am on "Course 1" course homepage
|
||||
When I expand "Site pages" node
|
||||
And I click on "Content bank" "link"
|
||||
Then I should not see "filltheblanks.h5p"
|
||||
And I log out
|
||||
And I log in as "admin"
|
||||
And I am on "Course 1" course homepage
|
||||
And I expand "Site pages" node
|
||||
And I click on "Content bank" "link"
|
||||
And I should see "filltheblanks.h5p"
|
||||
And I click on "filltheblanks.h5p" "link"
|
||||
And I switch to "h5p-player" class iframe
|
||||
Then I should not see "Of which countries"
|
||||
Then I should see "missing-required-library"
|
||||
And I should see "missing-required-library"
|
||||
|
@ -66,4 +66,132 @@ class contenttype_h5p_content_plugin_testcase extends advanced_testcase {
|
||||
$this->assertInstanceOf(\stored_file::class, $file);
|
||||
$this->assertEquals($filename, $file->get_filename());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for is view allowed content.
|
||||
*
|
||||
* @covers ::is_view_allowed
|
||||
* @dataProvider is_view_allowed_provider
|
||||
*
|
||||
* @param string $role User role to use for create and view contents.
|
||||
* @param array $disabledlibraries Library names to disable.
|
||||
* @param array $expected Array with the expected values for the contents in the following order:
|
||||
* ['H5P.Blanks deployed', 'H5P.Accordion deployed', 'H5P.Accordion undeployed', 'Invalid content'].
|
||||
*/
|
||||
public function test_is_view_allowed(string $role, array $disabledlibraries, array $expected): void {
|
||||
global $CFG, $USER, $DB;
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Create a course.
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$coursecontext = \context_course::instance($course->id);
|
||||
|
||||
// Set user.
|
||||
if ($role == 'admin') {
|
||||
$this->setAdminUser();
|
||||
} else {
|
||||
// Enrol user to the course.
|
||||
$user = $this->getDataGenerator()->create_and_enrol($course, $role);
|
||||
$this->setUser($user);
|
||||
}
|
||||
|
||||
// Add contents to the content bank.
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
|
||||
$filepath = $CFG->dirroot . '/h5p/tests/fixtures/filltheblanks.h5p';
|
||||
$contents = $generator->generate_contentbank_data('contenttype_h5p', 1, $USER->id, $coursecontext, true, $filepath);
|
||||
$filltheblanks = array_shift($contents);
|
||||
$filepath = $CFG->dirroot . '/h5p/tests/fixtures/ipsums.h5p';
|
||||
$contents = $generator->generate_contentbank_data('contenttype_h5p', 2, $USER->id, $coursecontext, true, $filepath);
|
||||
$accordion1 = array_shift($contents);
|
||||
$accordion2 = array_shift($contents);
|
||||
$filepath = $CFG->dirroot . '/h5p/tests/fixtures/invalid.zip';
|
||||
$contents = $generator->generate_contentbank_data('contenttype_h5p', 1, $USER->id, $coursecontext, true, $filepath);
|
||||
$invalid = array_shift($contents);
|
||||
|
||||
// Load some of these H5P files though the player to create the H5P DB entries.
|
||||
$h5pplayer = new \core_h5p\player($filltheblanks->get_file_url(), new \stdClass(), true);
|
||||
$h5pplayer = new \core_h5p\player($accordion1->get_file_url(), new \stdClass(), true);
|
||||
|
||||
// Check the expected H5P content has been created.
|
||||
$this->assertEquals(2, $DB->count_records('h5p'));
|
||||
$this->assertEquals(4, $DB->count_records('contentbank_content'));
|
||||
|
||||
// Disable libraries.
|
||||
foreach ($disabledlibraries as $libraryname) {
|
||||
$libraryid = $DB->get_field('h5p_libraries', 'id', ['machinename' => $libraryname]);
|
||||
\core_h5p\api::set_library_enabled((int) $libraryid, false);
|
||||
}
|
||||
|
||||
$this->assertEquals($expected[0], $filltheblanks->is_view_allowed());
|
||||
$this->assertEquals($expected[1], $accordion1->is_view_allowed());
|
||||
$this->assertEquals($expected[2], $accordion2->is_view_allowed());
|
||||
$this->assertEquals($expected[3], $invalid->is_view_allowed());
|
||||
|
||||
// Check that after enabling libraries again, all the content return true (but the invalid package).
|
||||
foreach ($disabledlibraries as $libraryname) {
|
||||
$libraryid = $DB->get_field('h5p_libraries', 'id', ['machinename' => $libraryname]);
|
||||
\core_h5p\api::set_library_enabled((int) $libraryid, true);
|
||||
}
|
||||
|
||||
$this->assertEquals(true, $filltheblanks->is_view_allowed());
|
||||
$this->assertEquals(true, $accordion1->is_view_allowed());
|
||||
$this->assertEquals(true, $accordion2->is_view_allowed()); // It will be deployed, so now it will always return true.
|
||||
$this->assertEquals($expected[3], $invalid->is_view_allowed());
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for test_is_view_allowed.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function is_view_allowed_provider(): array {
|
||||
return [
|
||||
'Editing teacher with all libraries enabled' => [
|
||||
'role' => 'editingteacher',
|
||||
'disabledlibraries' => [],
|
||||
'expected' => [true, true, true, false],
|
||||
],
|
||||
'Manager with all libraries enabled' => [
|
||||
'role' => 'manager',
|
||||
'disabledlibraries' => [],
|
||||
'expected' => [true, true, true, true],
|
||||
],
|
||||
'Admin with all libraries enabled' => [
|
||||
'role' => 'admin',
|
||||
'disabledlibraries' => [],
|
||||
'expected' => [true, true, true, true],
|
||||
],
|
||||
'Editing teacher with H5P.Accordion disabled' => [
|
||||
'role' => 'editingteacher',
|
||||
'disabledlibraries' => ['H5P.Accordion'],
|
||||
'expected' => [true, false, false, false],
|
||||
],
|
||||
'Manager with H5P.Accordion disabled' => [
|
||||
'role' => 'manager',
|
||||
'disabledlibraries' => ['H5P.Accordion'],
|
||||
'expected' => [true, false, true, true],
|
||||
],
|
||||
'Admin with H5P.Accordion disabled' => [
|
||||
'role' => 'admin',
|
||||
'disabledlibraries' => ['H5P.Accordion'],
|
||||
'expected' => [true, false, true, true],
|
||||
],
|
||||
'Editing teacher with all libraries disabled' => [
|
||||
'role' => 'editingteacher',
|
||||
'disabledlibraries' => ['H5P.Accordion', 'H5P.Blanks'],
|
||||
'expected' => [false, false, false, false],
|
||||
],
|
||||
'Manager with all libraries disabled' => [
|
||||
'role' => 'manager',
|
||||
'disabledlibraries' => ['H5P.Accordion', 'H5P.Blanks'],
|
||||
'expected' => [false, false, true, true],
|
||||
],
|
||||
'Admin with all libraries disabled' => [
|
||||
'role' => 'admin',
|
||||
'disabledlibraries' => ['H5P.Accordion', 'H5P.Blanks'],
|
||||
'expected' => [false, false, true, true],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
@core @core_contentbank @contentbank_h5p @_file_upload @javascript
|
||||
@core @core_contentbank @core_h5p @contentbank_h5p @_file_upload @javascript
|
||||
Feature: Delete H5P file from the content bank
|
||||
In order remove H5P content from the content bank
|
||||
As an admin
|
||||
|
@ -1,4 +1,4 @@
|
||||
@core @core_contentbank @contentbank_h5p @_file_upload @javascript
|
||||
@core @core_contentbank @core_h5p @contentbank_h5p @_file_upload @javascript
|
||||
Feature: Download H5P content from the content bank
|
||||
In order export H5P content from the content bank
|
||||
As an admin
|
||||
|
@ -1,4 +1,4 @@
|
||||
@core @core_contentbank @contentbank_h5p @_file_upload @javascript
|
||||
@core @core_contentbank @core_h5p @contentbank_h5p @_file_upload @javascript
|
||||
Feature: Content bank use editor feature
|
||||
In order to add/edit content
|
||||
As a user
|
||||
@ -117,7 +117,12 @@ Feature: Content bank use editor feature
|
||||
Then the field "Title" matches value "New title"
|
||||
|
||||
Scenario: Teachers can edit their own content in the content bank
|
||||
Given the following "users" exist:
|
||||
Given I navigate to "H5P > Manage H5P content types" in site administration
|
||||
And I upload "h5p/tests/fixtures/filltheblanks.h5p" file to "H5P content type" filemanager
|
||||
And I click on "Upload H5P content types" "button" in the "#fitem_id_uploadlibraries" "css_element"
|
||||
And I upload "h5p/tests/fixtures/ipsums.h5p" file to "H5P content type" filemanager
|
||||
And I click on "Upload H5P content types" "button" in the "#fitem_id_uploadlibraries" "css_element"
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com |
|
||||
And the following "courses" exist:
|
||||
|
@ -1,18 +1,22 @@
|
||||
@core @core_contentbank @_file_upload @_switch_iframe @javascript
|
||||
@core @core_contentbank @core_h5p @contentbank_h5p @_file_upload @_switch_iframe @javascript
|
||||
Feature: Confirm content bank events are triggered
|
||||
In order to log content bank actions
|
||||
As an admin
|
||||
I need to be able to check triggered events
|
||||
|
||||
Background:
|
||||
Given I log in as "admin"
|
||||
And I navigate to "H5P > Manage H5P content types" in site administration
|
||||
And I upload "h5p/tests/fixtures/filltheblanks.h5p" file to "H5P content type" filemanager
|
||||
And I click on "Upload H5P content types" "button" in the "#fitem_id_uploadlibraries" "css_element"
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname | category |
|
||||
| Course 1 | C1 | 0 |
|
||||
And the following "contentbank content" exist:
|
||||
| contextlevel | reference | contenttype | user | contentname |
|
||||
| Course | C1 | contenttype_h5p | admin | Existing |
|
||||
And I log in as "admin"
|
||||
And I follow "Manage private files..."
|
||||
| contextlevel | reference | contenttype | user | contentname | filepath |
|
||||
| Course | C1 | contenttype_h5p | admin | Existing | /h5p/tests/fixtures/filltheblanks.h5p |
|
||||
And I am on site homepage
|
||||
And I follow "Private files"
|
||||
And I upload "h5p/tests/fixtures/filltheblanks.h5p" file to "Files" filemanager
|
||||
And I click on "Save changes" "button"
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
|
@ -1,24 +1,27 @@
|
||||
@core @core_contentbank @contentbank_h5p @_file_upload @javascript
|
||||
@core @core_contentbank @core_h5p @contentbank_h5p @_file_upload @javascript
|
||||
Feature: Search content in the content bank
|
||||
In order to find easily content in the content bank
|
||||
As an admin
|
||||
I need to be able to search content in the content bank
|
||||
|
||||
Background:
|
||||
Given the following "contentbank content" exist:
|
||||
| contextlevel | reference | contenttype | user | contentname |
|
||||
| System | | contenttype_h5p | admin | santjordi.h5p |
|
||||
| System | | contenttype_h5p | admin | santjordi_rose.h5p |
|
||||
| System | | contenttype_h5p | admin | SantJordi_book |
|
||||
| System | | contenttype_h5p | admin | Dragon_santjordi.h5p |
|
||||
| System | | contenttype_h5p | admin | princess.h5p |
|
||||
| System | | contenttype_h5p | admin | mathsbook.h5p |
|
||||
| System | | contenttype_h5p | admin | historybook.h5p |
|
||||
| System | | contenttype_h5p | admin | santvicenc.h5p |
|
||||
Given I log in as "admin"
|
||||
And I navigate to "H5P > Manage H5P content types" in site administration
|
||||
And I upload "h5p/tests/fixtures/filltheblanks.h5p" file to "H5P content type" filemanager
|
||||
And I click on "Upload H5P content types" "button" in the "#fitem_id_uploadlibraries" "css_element"
|
||||
And the following "contentbank content" exist:
|
||||
| contextlevel | reference | contenttype | user | contentname | filepath |
|
||||
| System | | contenttype_h5p | admin | santjordi.h5p | /h5p/tests/fixtures/filltheblanks.h5p |
|
||||
| System | | contenttype_h5p | admin | santjordi_rose.h5p | /h5p/tests/fixtures/filltheblanks.h5p |
|
||||
| System | | contenttype_h5p | admin | SantJordi_book | /h5p/tests/fixtures/filltheblanks.h5p |
|
||||
| System | | contenttype_h5p | admin | Dragon_santjordi.h5p | /h5p/tests/fixtures/filltheblanks.h5p |
|
||||
| System | | contenttype_h5p | admin | princess.h5p | /h5p/tests/fixtures/filltheblanks.h5p |
|
||||
| System | | contenttype_h5p | admin | mathsbook.h5p | /h5p/tests/fixtures/filltheblanks.h5p |
|
||||
| System | | contenttype_h5p | admin | historybook.h5p | /h5p/tests/fixtures/filltheblanks.h5p |
|
||||
| System | | contenttype_h5p | admin | santvicenc.h5p | /h5p/tests/fixtures/filltheblanks.h5p |
|
||||
|
||||
Scenario: Admins can search content in the content bank
|
||||
Given I log in as "admin"
|
||||
And I am on site homepage
|
||||
Given I am on site homepage
|
||||
And I turn editing mode on
|
||||
And I add the "Navigation" block if not present
|
||||
And I expand "Site pages" node
|
||||
|
@ -1,28 +1,31 @@
|
||||
@core @core_contentbank @contentbank_h5p @javascript
|
||||
@core @core_contentbank @core_h5p @contentbank_h5p @_file_upload @javascript
|
||||
Feature: Sort content in the content bank
|
||||
In order to temporarily organise the content of the content bank
|
||||
As an admin
|
||||
I need to be able to sort the content bank in various ways
|
||||
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
Given I log in as "admin"
|
||||
And I navigate to "H5P > Manage H5P content types" in site administration
|
||||
And I upload "h5p/tests/fixtures/filltheblanks.h5p" file to "H5P content type" filemanager
|
||||
And I click on "Upload H5P content types" "button" in the "#fitem_id_uploadlibraries" "css_element"
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| manager | Max | Manager | man@example.com |
|
||||
And the following "role assigns" exist:
|
||||
| user | role | contextlevel | reference |
|
||||
| manager | manager | System | |
|
||||
And the following "contentbank content" exist:
|
||||
| contextlevel | reference | contenttype | user | contentname |
|
||||
| System | | contenttype_h5p | admin | Dragon_santjordi.h5p |
|
||||
| System | | contenttype_h5p | admin | mathsbook.h5p |
|
||||
| System | | contenttype_h5p | manager | historybook.h5p |
|
||||
| System | | contenttype_h5p | admin | santjordi.h5p |
|
||||
| System | | contenttype_h5p | admin | santjordi_rose.h5p |
|
||||
| System | | contenttype_h5p | admin | SantJordi_book |
|
||||
| contextlevel | reference | contenttype | user | contentname | filepath |
|
||||
| System | | contenttype_h5p | admin | Dragon_santjordi.h5p | /h5p/tests/fixtures/filltheblanks.h5p |
|
||||
| System | | contenttype_h5p | admin | mathsbook.h5p | /h5p/tests/fixtures/filltheblanks.h5p |
|
||||
| System | | contenttype_h5p | manager | historybook.h5p | /h5p/tests/fixtures/filltheblanks.h5p |
|
||||
| System | | contenttype_h5p | admin | santjordi.h5p | /h5p/tests/fixtures/filltheblanks.h5p |
|
||||
| System | | contenttype_h5p | admin | santjordi_rose.h5p | /h5p/tests/fixtures/filltheblanks.h5p |
|
||||
| System | | contenttype_h5p | admin | SantJordi_book | /h5p/tests/fixtures/filltheblanks.h5p |
|
||||
|
||||
Scenario: Admins can order content in the content bank
|
||||
Given I log in as "admin"
|
||||
And I am on site homepage
|
||||
Given I am on site homepage
|
||||
And I turn editing mode on
|
||||
And I add the "Navigation" block if not present
|
||||
And I expand "Site pages" node
|
||||
@ -38,8 +41,7 @@ Feature: Sort content in the content bank
|
||||
Then "santjordi_rose.h5p" "text" should appear before "SantJordi_book" "text"
|
||||
|
||||
Scenario: Admins can order content depending on the author
|
||||
Given I log in as "admin"
|
||||
And I am on site homepage
|
||||
Given I am on site homepage
|
||||
And I turn editing mode on
|
||||
And I add the "Navigation" block if not present
|
||||
And I expand "Site pages" node
|
||||
|
@ -1,4 +1,4 @@
|
||||
@core @core_contentbank @contentbank_h5p @_file_upload @javascript
|
||||
@core @core_contentbank @core_h5p @contentbank_h5p @_file_upload @javascript
|
||||
Feature: Store the content bank view preference
|
||||
In order to consistantly view the content bank in icons or details view
|
||||
As an admin
|
||||
|
@ -1,4 +1,4 @@
|
||||
@core @core_contentbank @contentbank_h5p @javascript
|
||||
@core @core_contentbank @core_h5p @contentbank_h5p @_file_upload @javascript
|
||||
Feature: Make content public or unlisted
|
||||
In order to make content public or unlisted
|
||||
As a user
|
||||
@ -13,6 +13,9 @@ Feature: Make content public or unlisted
|
||||
And I set the following fields to these values:
|
||||
| Page contexts | Display throughout the entire site |
|
||||
And I press "Save changes"
|
||||
And I navigate to "H5P > Manage H5P content types" in site administration
|
||||
And I upload "h5p/tests/fixtures/filltheblanks.h5p" file to "H5P content type" filemanager
|
||||
And I click on "Upload H5P content types" "button" in the "#fitem_id_uploadlibraries" "css_element"
|
||||
|
||||
Scenario: Users can make their content public or unlisted
|
||||
Given the following "contentbank content" exist:
|
||||
|
@ -46,7 +46,7 @@ require_once($CFG->dirroot . '/contentbank/tests/fixtures/testable_content.php')
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @coversDefaultClass \core_contentbank\contentbank
|
||||
*/
|
||||
class core_contentbank_testcase extends advanced_testcase {
|
||||
class contentbank_test extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Setup to ensure that fixtures are loaded.
|
||||
@ -206,9 +206,10 @@ class core_contentbank_testcase extends advanced_testcase {
|
||||
*/
|
||||
public function test_search_contents(?string $search, string $where, int $expectedresult, array $contexts = [],
|
||||
array $contenttypes = null): void {
|
||||
global $DB;
|
||||
global $DB, $CFG;
|
||||
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
// Create users.
|
||||
$managerroleid = $DB->get_field('role', 'id', ['shortname' => 'manager']);
|
||||
@ -230,11 +231,12 @@ class core_contentbank_testcase extends advanced_testcase {
|
||||
}
|
||||
|
||||
// Add some content to the content bank.
|
||||
$filepath = $CFG->dirroot . '/h5p/tests/fixtures/filltheblanks.h5p';
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
|
||||
foreach ($contexts as $context) {
|
||||
$contextinstance = $existingcontexts[$context];
|
||||
$records = $generator->generate_contentbank_data('contenttype_h5p', 3,
|
||||
$manager->id, $contextinstance, false);
|
||||
$manager->id, $contextinstance, false, $filepath);
|
||||
}
|
||||
|
||||
// Search for some content.
|
||||
@ -357,12 +359,12 @@ class core_contentbank_testcase extends advanced_testcase {
|
||||
* @covers ::create_content_from_file
|
||||
*/
|
||||
public function test_create_content_from_file() {
|
||||
global $USER;
|
||||
global $USER, $CFG;
|
||||
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
$systemcontext = \context_system::instance();
|
||||
$name = 'dummy_h5p.h5p';
|
||||
$name = 'greeting-card-887.h5p';
|
||||
|
||||
// Create a dummy H5P file.
|
||||
$dummyh5p = array(
|
||||
@ -374,8 +376,8 @@ class core_contentbank_testcase extends advanced_testcase {
|
||||
'filename' => $name,
|
||||
'userid' => $USER->id
|
||||
);
|
||||
$fs = get_file_storage();
|
||||
$dummyh5pfile = $fs->create_file_from_string($dummyh5p, 'Dummy H5Pcontent');
|
||||
$path = $CFG->dirroot . '/h5p/tests/fixtures/' . $name;
|
||||
$dummyh5pfile = \core_h5p\helper::create_fake_stored_file_from_path($path);
|
||||
|
||||
$cb = new contentbank();
|
||||
$content = $cb->create_content_from_file($systemcontext, $USER->id, $dummyh5pfile);
|
||||
|
@ -58,7 +58,8 @@ $contenttype = $content->get_content_type_instance();
|
||||
$pageheading = $record->name;
|
||||
|
||||
if (!$content->is_view_allowed()) {
|
||||
print_error('notavailable', 'contentbank');
|
||||
$cburl = new \moodle_url('/contentbank/index.php', ['contextid' => $context->id, 'errormsg' => 'notavailable']);
|
||||
redirect($cburl);
|
||||
}
|
||||
|
||||
if ($content->get_visibility() == content::VISIBILITY_UNLISTED) {
|
||||
|
@ -181,3 +181,53 @@ Feature: Render H5P content using filters
|
||||
And I switch to "h5p-iframe" class iframe
|
||||
Then I should not see "missing-required-library"
|
||||
And I should see "Lorum ipsum"
|
||||
|
||||
@javascript
|
||||
Scenario: Render local H5P file with a disabled main library
|
||||
Given I log in as "admin"
|
||||
# Upload H5P file to private files.
|
||||
And I follow "Private files"
|
||||
And I upload "h5p/tests/fixtures/ipsums.h5p" file to "Files" filemanager
|
||||
And I click on "Save changes" "button"
|
||||
# Upload manually the H5P content-type library and disable it.
|
||||
And I navigate to "H5P > Manage H5P content types" in site administration
|
||||
And I upload "h5p/tests/fixtures/ipsums.h5p" file to "H5P content type" filemanager
|
||||
And I click on "Upload H5P content types" "button" in the "#fitem_id_uploadlibraries" "css_element"
|
||||
And I click on "Disable" "link" in the "Accordion" "table_row"
|
||||
# Add H5P content to the page.
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
And I follow "PageName1"
|
||||
And I navigate to "Edit settings" in current page administration
|
||||
When I click on "Insert H5P" "button" in the "#fitem_id_page" "css_element"
|
||||
And I click on "Browse repositories..." "button" in the "Insert H5P" "dialogue"
|
||||
And I click on "Private files" "link" in the ".fp-repo-area" "css_element"
|
||||
And I click on "ipsums.h5p" "link"
|
||||
And I click on "Select this file" "button"
|
||||
And I click on "Insert H5P" "button" in the "Insert H5P" "dialogue"
|
||||
And I click on "Save and display" "button"
|
||||
And I switch to "h5p-iframe" class iframe
|
||||
# Library is disabled, so an error should be displayed.
|
||||
Then I should see "This file can't be displayed because its content-type is disabled."
|
||||
And I should not see "Lorum ipsum"
|
||||
And I switch to the main frame
|
||||
And I navigate to "H5P > Manage H5P content types" in site administration
|
||||
And I click on "Enable" "link" in the "Accordion" "table_row"
|
||||
And I am on "Course 1" course homepage
|
||||
# Content should be deployed now that main library is enabled.
|
||||
And I follow "PageName1"
|
||||
# Switch to iframe created by filter.
|
||||
And I switch to "h5p-iframe" class iframe
|
||||
# Switch to iframe created by embed.php page.
|
||||
And I switch to "h5p-iframe" class iframe
|
||||
And I should see "Lorum ipsum"
|
||||
And I should not see "This file can't be displayed because its content-type is disabled."
|
||||
And I switch to the main frame
|
||||
And I navigate to "H5P > Manage H5P content types" in site administration
|
||||
And I click on "Disable" "link" in the "Accordion" "table_row"
|
||||
And I am on "Course 1" course homepage
|
||||
# Library is disabled again, so an error should be displayed.
|
||||
And I follow "PageName1"
|
||||
And I switch to "h5p-iframe" class iframe
|
||||
And I should see "This file can't be displayed because its content-type is disabled."
|
||||
And I should not see "Lorum ipsum"
|
||||
And I switch to the main frame
|
||||
|
@ -185,16 +185,20 @@ class api {
|
||||
*
|
||||
* @param string $url H5P pluginfile URL.
|
||||
* @param bool $preventredirect Set to true in scripts that can not redirect (CLI, RSS feeds, etc.), throws exceptions
|
||||
* @param bool $skipcapcheck Whether capabilities should be checked or not to get the pluginfile URL because sometimes they
|
||||
* might be controlled before calling this method.
|
||||
*
|
||||
* @return array of [file, stdClass|false]:
|
||||
* - file local file for this $url.
|
||||
* - stdClass is an H5P object or false if there isn't any H5P with this URL.
|
||||
*/
|
||||
public static function get_content_from_pluginfile_url(string $url, bool $preventredirect = true): array {
|
||||
public static function get_content_from_pluginfile_url(string $url, bool $preventredirect = true,
|
||||
bool $skipcapcheck = false): array {
|
||||
|
||||
global $DB;
|
||||
|
||||
// Deconstruct the URL and get the pathname associated.
|
||||
if (self::can_access_pluginfile_hash($url, $preventredirect)) {
|
||||
if ($skipcapcheck || self::can_access_pluginfile_hash($url, $preventredirect)) {
|
||||
$pathnamehash = self::get_pluginfile_hash($url);
|
||||
}
|
||||
|
||||
@ -223,17 +227,19 @@ class api {
|
||||
* @param factory $factory The \core_h5p\factory object
|
||||
* @param stdClass $messages The error, exception and info messages, raised while preparing and running an H5P content.
|
||||
* @param bool $preventredirect Set to true in scripts that can not redirect (CLI, RSS feeds, etc.), throws exceptions
|
||||
* @param bool $skipcapcheck Whether capabilities should be checked or not to get the pluginfile URL because sometimes they
|
||||
* might be controlled before calling this method.
|
||||
*
|
||||
* @return array of [file, h5pid]:
|
||||
* - file local file for this $url.
|
||||
* - h5pid is the H5P identifier or false if there isn't any H5P with this URL.
|
||||
*/
|
||||
public static function create_content_from_pluginfile_url(string $url, \stdClass $config, factory $factory,
|
||||
\stdClass &$messages, bool $preventredirect = true): array {
|
||||
\stdClass &$messages, bool $preventredirect = true, bool $skipcapcheck = false): array {
|
||||
global $USER;
|
||||
|
||||
$core = $factory->get_core();
|
||||
list($file, $h5p) = self::get_content_from_pluginfile_url($url, $preventredirect);
|
||||
list($file, $h5p) = self::get_content_from_pluginfile_url($url, $preventredirect, $skipcapcheck);
|
||||
|
||||
if (!$file) {
|
||||
$core->h5pF->setErrorMessage(get_string('h5pfilenotfound', 'core_h5p'));
|
||||
@ -251,13 +257,21 @@ class api {
|
||||
$context = \context::instance_by_id($file->get_contextid());
|
||||
if ($h5p) {
|
||||
// The H5P content has been deployed previously.
|
||||
$displayoptions = helper::get_display_options($core, $config);
|
||||
// Check if the user can set the displayoptions.
|
||||
if ($displayoptions != $h5p->displayoptions && has_capability('moodle/h5p:setdisplayoptions', $context)) {
|
||||
// If the displayoptions has changed and the user has permission to modify it, update this information in the DB.
|
||||
$core->h5pF->updateContentFields($h5p->id, ['displayoptions' => $displayoptions]);
|
||||
|
||||
// If the main library for this H5P content is disabled, the content won't be displayed.
|
||||
$mainlibrary = (object) ['id' => $h5p->mainlibraryid];
|
||||
if (!self::is_library_enabled($mainlibrary)) {
|
||||
$core->h5pF->setErrorMessage(get_string('mainlibrarydisabled', 'core_h5p'));
|
||||
return [$file, false];
|
||||
} else {
|
||||
$displayoptions = helper::get_display_options($core, $config);
|
||||
// Check if the user can set the displayoptions.
|
||||
if ($displayoptions != $h5p->displayoptions && has_capability('moodle/h5p:setdisplayoptions', $context)) {
|
||||
// If displayoptions has changed and user has permission to modify it, update this information in DB.
|
||||
$core->h5pF->updateContentFields($h5p->id, ['displayoptions' => $displayoptions]);
|
||||
}
|
||||
return [$file, $h5p->id];
|
||||
}
|
||||
return [$file, $h5p->id];
|
||||
} else {
|
||||
// The H5P content hasn't been deployed previously.
|
||||
|
||||
@ -593,4 +607,116 @@ class api {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable a library.
|
||||
*
|
||||
* @param int $libraryid The id of the library to enable/disable.
|
||||
* @param bool $isenabled True if the library should be enabled; false otherwise.
|
||||
*/
|
||||
public static function set_library_enabled(int $libraryid, bool $isenabled): void {
|
||||
global $DB;
|
||||
|
||||
$library = $DB->get_record('h5p_libraries', ['id' => $libraryid], '*', MUST_EXIST);
|
||||
if ($library->runnable) {
|
||||
// For now, only runnable libraries can be enabled/disabled.
|
||||
$record = [
|
||||
'id' => $libraryid,
|
||||
'enabled' => $isenabled,
|
||||
];
|
||||
$DB->update_record('h5p_libraries', $record);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a library is enabled or not. When machinename is passed, it will return false if any of the versions
|
||||
* for this machinename is disabled.
|
||||
* If the library doesn't exist, it will return true.
|
||||
*
|
||||
* @param \stdClass $librarydata Supported fields for library: 'id' and 'machichename'.
|
||||
* @return bool
|
||||
* @throws \moodle_exception
|
||||
*/
|
||||
public static function is_library_enabled(\stdClass $librarydata): bool {
|
||||
global $DB;
|
||||
|
||||
$params = [];
|
||||
if (property_exists($librarydata, 'machinename')) {
|
||||
$params['machinename'] = $librarydata->machinename;
|
||||
}
|
||||
if (property_exists($librarydata, 'id')) {
|
||||
$params['id'] = $librarydata->id;
|
||||
}
|
||||
|
||||
if (empty($params)) {
|
||||
throw new \moodle_exception("Missing 'machinename' or 'id' in librarydata parameter");
|
||||
}
|
||||
|
||||
$libraries = $DB->get_records('h5p_libraries', $params);
|
||||
|
||||
// If any of the libraries with these values have been disabled, return false.
|
||||
foreach ($libraries as $id => $library) {
|
||||
if (!$library->enabled) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether an H5P package is valid or not.
|
||||
*
|
||||
* @param \stored_file $file The file with the H5P content.
|
||||
* @param bool $onlyupdatelibs Whether new libraries can be installed or only the existing ones can be updated
|
||||
* @param bool $skipcontent Should the content be skipped (so only the libraries will be saved)?
|
||||
* @param factory|null $factory The \core_h5p\factory object
|
||||
* @param bool $deletefiletree Should the temporary files be deleted before returning?
|
||||
* @return bool True if the H5P file is valid (expected format, valid libraries...); false otherwise.
|
||||
*/
|
||||
public static function is_valid_package(\stored_file $file, bool $onlyupdatelibs, bool $skipcontent = false,
|
||||
?factory $factory = null, bool $deletefiletree = true): bool {
|
||||
|
||||
// This may take a long time.
|
||||
\core_php_time_limit::raise();
|
||||
|
||||
$isvalid = false;
|
||||
|
||||
if (empty($factory)) {
|
||||
$factory = new factory();
|
||||
}
|
||||
$core = $factory->get_core();
|
||||
$h5pvalidator = $factory->get_validator();
|
||||
|
||||
// Set the H5P file path.
|
||||
$core->h5pF->set_file($file);
|
||||
$path = $core->fs->getTmpPath();
|
||||
$core->h5pF->getUploadedH5pFolderPath($path);
|
||||
// Add manually the extension to the file to avoid the validation fails.
|
||||
$path .= '.h5p';
|
||||
$core->h5pF->getUploadedH5pPath($path);
|
||||
// Copy the .h5p file to the temporary folder.
|
||||
$file->copy_content_to($path);
|
||||
|
||||
if ($h5pvalidator->isValidPackage($skipcontent, $onlyupdatelibs)) {
|
||||
if ($skipcontent) {
|
||||
$isvalid = true;
|
||||
} else if (!empty($h5pvalidator->h5pC->mainJsonData['mainLibrary'])) {
|
||||
$mainlibrary = (object) ['machinename' => $h5pvalidator->h5pC->mainJsonData['mainLibrary']];
|
||||
if (self::is_library_enabled($mainlibrary)) {
|
||||
$isvalid = true;
|
||||
} else {
|
||||
// If the main library of the package is disabled, the H5P content will be considered invalid.
|
||||
$core->h5pF->setErrorMessage(get_string('mainlibrarydisabled', 'core_h5p'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($deletefiletree) {
|
||||
// Remove temp content folder.
|
||||
\H5PCore::deleteFileTree($path);
|
||||
}
|
||||
|
||||
return $isvalid;
|
||||
}
|
||||
}
|
||||
|
@ -179,6 +179,11 @@ class core extends \H5PCore {
|
||||
$framework = $factory->get_framework();
|
||||
|
||||
foreach ($contenttypes->contentTypes as $type) {
|
||||
// Don't fetch content types if any of the versions is disabled.
|
||||
$librarydata = (object) ['machinename' => $type->id];
|
||||
if (!api::is_library_enabled($librarydata)) {
|
||||
continue;
|
||||
}
|
||||
// Don't fetch content types that require a higher H5P core API version.
|
||||
if (!$this->is_required_core_api($type->coreApiVersionNeeded)) {
|
||||
continue;
|
||||
|
@ -51,7 +51,8 @@ class editor_ajax implements H5PEditorAjaxInterface {
|
||||
global $DB;
|
||||
|
||||
$sql = "SELECT hl2.id, hl2.machinename as machine_name, hl2.title, hl2.majorversion as major_version,
|
||||
hl2.minorversion AS minor_version, hl2.patchversion as patch_version, '' as has_icon, 0 as restricted
|
||||
hl2.minorversion AS minor_version, hl2.patchversion as patch_version, '' as has_icon, 0 as restricted,
|
||||
hl2.enabled
|
||||
FROM {h5p_libraries} hl2
|
||||
LEFT JOIN {h5p_libraries} hl1
|
||||
ON hl1.machinename = hl2.machinename
|
||||
|
@ -520,7 +520,7 @@ class framework implements \H5PFrameworkInterface {
|
||||
|
||||
$results = $DB->get_records('h5p_libraries', [], 'title ASC, majorversion ASC, minorversion ASC',
|
||||
'id, machinename AS machine_name, majorversion AS major_version, minorversion AS minor_version,
|
||||
patchversion AS patch_version, runnable, title');
|
||||
patchversion AS patch_version, runnable, title, enabled');
|
||||
|
||||
$libraries = array();
|
||||
foreach ($results as $library) {
|
||||
|
@ -50,23 +50,10 @@ class helper {
|
||||
*/
|
||||
public static function save_h5p(factory $factory, \stored_file $file, \stdClass $config, bool $onlyupdatelibs = false,
|
||||
bool $skipcontent = false) {
|
||||
// This may take a long time.
|
||||
\core_php_time_limit::raise();
|
||||
|
||||
$core = $factory->get_core();
|
||||
$core->h5pF->set_file($file);
|
||||
$path = $core->fs->getTmpPath();
|
||||
$core->h5pF->getUploadedH5pFolderPath($path);
|
||||
// Add manually the extension to the file to avoid the validation fails.
|
||||
$path .= '.h5p';
|
||||
$core->h5pF->getUploadedH5pPath($path);
|
||||
|
||||
// Copy the .h5p file to the temporary folder.
|
||||
$file->copy_content_to($path);
|
||||
|
||||
// Check if the h5p file is valid before saving it.
|
||||
$h5pvalidator = $factory->get_validator();
|
||||
if ($h5pvalidator->isValidPackage($skipcontent, $onlyupdatelibs)) {
|
||||
if (api::is_valid_package($file, $onlyupdatelibs, $skipcontent, $factory, false)) {
|
||||
$core = $factory->get_core();
|
||||
$h5pvalidator = $factory->get_validator();
|
||||
$h5pstorage = $factory->get_storage();
|
||||
|
||||
$content = [
|
||||
@ -83,6 +70,7 @@ class helper {
|
||||
|
||||
return $h5pstorage->contentId;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -89,6 +89,17 @@ class libraries implements renderable, templatable {
|
||||
get_string('deletelibraryversion', 'core_h5p')
|
||||
));
|
||||
$version->actionmenu = $actionmenu->export_for_template($output);
|
||||
if ($version->enabled) {
|
||||
$version->toggleenabledurl = new moodle_url('/h5p/libraries.php', [
|
||||
'id' => $version->id,
|
||||
'action' => 'disable',
|
||||
]);
|
||||
} else {
|
||||
$version->toggleenabledurl = new moodle_url('/h5p/libraries.php', [
|
||||
'id' => $version->id,
|
||||
'action' => 'enable',
|
||||
]);
|
||||
}
|
||||
$installed[] = $version;
|
||||
}
|
||||
}
|
||||
|
@ -105,8 +105,11 @@ class player {
|
||||
* @param stdClass $config Configuration for H5P buttons.
|
||||
* @param bool $preventredirect Set to true in scripts that can not redirect (CLI, RSS feeds, etc.), throws exceptions
|
||||
* @param string $component optional moodle component to sent xAPI tracking
|
||||
* @param bool $skipcapcheck Whether capabilities should be checked or not to get the pluginfile URL because sometimes they
|
||||
* might be controlled before calling this method.
|
||||
*/
|
||||
public function __construct(string $url, \stdClass $config, bool $preventredirect = true, string $component = '') {
|
||||
public function __construct(string $url, \stdClass $config, bool $preventredirect = true, string $component = '',
|
||||
bool $skipcapcheck = false) {
|
||||
if (empty($url)) {
|
||||
throw new \moodle_exception('h5pinvalidurl', 'core_h5p');
|
||||
}
|
||||
@ -128,7 +131,8 @@ class player {
|
||||
$config,
|
||||
$this->factory,
|
||||
$this->messages,
|
||||
$this->preventredirect
|
||||
$this->preventredirect,
|
||||
$skipcapcheck
|
||||
);
|
||||
if ($file) {
|
||||
$this->context = \context::instance_by_id($file->get_contextid());
|
||||
|
@ -28,6 +28,7 @@ require_login(null, false);
|
||||
|
||||
$deletelibrary = optional_param('deletelibrary', null, PARAM_INT);
|
||||
$confirm = optional_param('confirm', false, PARAM_BOOL);
|
||||
$action = optional_param('action', null, PARAM_ALPHANUMEXT);
|
||||
|
||||
$context = context_system::instance();
|
||||
require_capability('moodle/h5p:updatelibraries', $context);
|
||||
@ -64,6 +65,15 @@ if ($deletelibrary) {
|
||||
die();
|
||||
}
|
||||
|
||||
if (!is_null($action)) {
|
||||
if ($action == 'enable' || $action == 'disable') {
|
||||
// If action is enable or disable, library id is required too.
|
||||
$libraryid = required_param('id', PARAM_INT);
|
||||
|
||||
\core_h5p\api::set_library_enabled($libraryid, ($action == 'enable'));
|
||||
}
|
||||
}
|
||||
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->heading($pagetitle);
|
||||
echo $OUTPUT->box(get_string('librariesmanagerdescription', 'core_h5p'));
|
||||
|
@ -26,14 +26,18 @@
|
||||
"minor_version:": 0,
|
||||
"patch_version:": 0,
|
||||
"runnable": 1,
|
||||
"icon": "icon.svg"
|
||||
"icon": "icon.svg",
|
||||
"enabled": true,
|
||||
"toggleenabledurl": "http://myserver.cat/h5p/libraries.php?id=26&action=disable"
|
||||
},
|
||||
{
|
||||
"title": "Collage",
|
||||
"major_version": 0,
|
||||
"minor_version:": 3,
|
||||
"patch_version:": 1,
|
||||
"runnable": 1
|
||||
"runnable": 1,
|
||||
"enabled": true,
|
||||
"toggleenabledurl": "http://myserver.cat/h5p/libraries.php?id=37&action=disable"
|
||||
},
|
||||
{
|
||||
"title": "FontAwesome",
|
||||
@ -41,7 +45,9 @@
|
||||
"minor_version:": 5,
|
||||
"patch_version:": 0,
|
||||
"runnable": 1,
|
||||
"icon": "icon.svg"
|
||||
"icon": "icon.svg",
|
||||
"enabled": false,
|
||||
"toggleenabledurl": "http://myserver.cat/h5p/libraries.php?id=54&action=enable"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -67,6 +73,7 @@
|
||||
<table class="admintable generaltable" id="h5pcontenttypes">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 5%">{{#str}}enable, core{{/str}}</th>
|
||||
<th>{{#str}}description, core{{/str}}</th>
|
||||
<th>{{#str}}version, core{{/str}}</th>
|
||||
<th aria-label="{{#str}}actions, core_h5p{{/str}}"></th>
|
||||
@ -76,6 +83,14 @@
|
||||
{{#contenttypes}}
|
||||
{{#runnable}}
|
||||
<tr class="">
|
||||
<td class="text-center">
|
||||
{{#enabled}}
|
||||
<a href="{{{toggleenabledurl}}}" aria-label="{{#str}}disable, core{{/str}}">{{#pix}}t/hide, core,{{#str}}disable{{/str}}{{/pix}}</a>
|
||||
{{/enabled}}
|
||||
{{^enabled}}
|
||||
<a href="{{{toggleenabledurl}}}" aria-label="{{#str}}enable, core{{/str}}">{{#pix}}t/show, core,{{#str}}enable{{/str}}{{/pix}}</a>
|
||||
{{/enabled}}
|
||||
</td>
|
||||
<td>
|
||||
{{#icon}}
|
||||
<img alt=""
|
||||
@ -130,4 +145,4 @@
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -35,8 +35,9 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @package core_h5p
|
||||
* @copyright 2020 Sara Arjona <sara@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @coversDefaultClass \core_h5p\api
|
||||
*/
|
||||
class api_testcase extends \advanced_testcase {
|
||||
class api_test extends \advanced_testcase {
|
||||
|
||||
/**
|
||||
* Test the behaviour of delete_library().
|
||||
@ -503,4 +504,339 @@ class api_testcase extends \advanced_testcase {
|
||||
\core_h5p\file_storage::EXPORT_FILEAREA);
|
||||
$this->assertNull($exportfile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the behaviour of set_library_enabled().
|
||||
*
|
||||
* @covers ::set_library_enabled
|
||||
* @dataProvider set_library_enabled_provider
|
||||
*
|
||||
* @param string $libraryname Library name to enable/disable.
|
||||
* @param string $action Action to be done with the library. Supported values: enable, disable.
|
||||
* @param int $expected Expected value for the enabled library field. -1 will be passed if the library doesn't exist.
|
||||
*/
|
||||
public function test_set_library_enabled(string $libraryname, string $action, int $expected): void {
|
||||
global $DB;
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Create libraries.
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_h5p');
|
||||
$generator->generate_h5p_data();
|
||||
|
||||
// Check by default the library is enabled.
|
||||
$library = $DB->get_record('h5p_libraries', ['machinename' => $libraryname]);
|
||||
if ($expected >= 0) {
|
||||
$this->assertEquals(1, $library->enabled);
|
||||
$libraryid = (int) $library->id;
|
||||
} else {
|
||||
// Unexisting library. Set libraryid to some unexisting id.
|
||||
$libraryid = -1;
|
||||
$this->expectException('dml_missing_record_exception');
|
||||
}
|
||||
|
||||
\core_h5p\api::set_library_enabled($libraryid, ($action == 'enable'));
|
||||
|
||||
// Check the value of the "enabled" field after calling enable/disable method.
|
||||
$libraries = $DB->get_records('h5p_libraries');
|
||||
foreach ($libraries as $libraryid => $library) {
|
||||
if ($library->machinename == $libraryname) {
|
||||
$this->assertEquals($expected, $library->enabled);
|
||||
} else {
|
||||
// Check that only $libraryname has been enabled/disabled.
|
||||
$this->assertEquals(1, $library->enabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for test_set_library_enabled().
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function set_library_enabled_provider(): array {
|
||||
return [
|
||||
'Disable existing library' => [
|
||||
'libraryname' => 'MainLibrary',
|
||||
'action' => 'disable',
|
||||
'expected' => 0,
|
||||
],
|
||||
'Enable existing library' => [
|
||||
'libraryname' => 'MainLibrary',
|
||||
'action' => 'enable',
|
||||
'expected' => 1,
|
||||
],
|
||||
'Disable existing library (not main)' => [
|
||||
'libraryname' => 'Library1',
|
||||
'action' => 'disable',
|
||||
'expected' => 0,
|
||||
],
|
||||
'Enable existing library (not main)' => [
|
||||
'libraryname' => 'Library1',
|
||||
'action' => 'enable',
|
||||
'expected' => 1,
|
||||
],
|
||||
'Disable existing library (not runnable)' => [
|
||||
'libraryname' => 'Library3',
|
||||
'action' => 'disable',
|
||||
'expected' => 1, // Not runnable libraries can't be disabled.
|
||||
],
|
||||
'Enable existing library (not runnable)' => [
|
||||
'libraryname' => 'Library3',
|
||||
'action' => 'enable',
|
||||
'expected' => 1,
|
||||
],
|
||||
'Enable unexisting library' => [
|
||||
'libraryname' => 'Unexisting library',
|
||||
'action' => 'enable',
|
||||
'expected' => -1,
|
||||
],
|
||||
'Disable unexisting library' => [
|
||||
'libraryname' => 'Unexisting library',
|
||||
'action' => 'disable',
|
||||
'expected' => -1,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the behaviour of is_library_enabled().
|
||||
*
|
||||
* @covers ::is_library_enabled
|
||||
* @dataProvider is_library_enabled_provider
|
||||
*
|
||||
* @param string $libraryname Library name to check.
|
||||
* @param bool $expected Expected result after calling the method.
|
||||
* @param bool $exception Exception expected or not.
|
||||
* @param bool $useid Whether to use id for calling is_library_enabled method.
|
||||
* @param bool $uselibraryname Whether to use libraryname for calling is_library_enabled method.
|
||||
*/
|
||||
public function test_is_library_enabled(string $libraryname, bool $expected, bool $exception = false,
|
||||
bool $useid = false, bool $uselibraryname = true): void {
|
||||
global $DB;
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Create the following libraries:
|
||||
// - H5P.Lib1: 1 version enabled, 1 version disabled.
|
||||
// - H5P.Lib2: 2 versions enabled.
|
||||
// - H5P.Lib3: 2 versions disabled.
|
||||
// - H5P.Lib4: 1 version disabled.
|
||||
// - H5P.Lib5: 1 version enabled.
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_h5p');
|
||||
$libraries = [
|
||||
'H5P.Lib1.1' => $generator->create_library_record('H5P.Lib1', 'Lib1', 1, 1, 0, '', null, null, null, false),
|
||||
'H5P.Lib1.2' => $generator->create_library_record('H5P.Lib1', 'Lib1', 1, 2),
|
||||
'H5P.Lib2.1' => $generator->create_library_record('H5P.Lib2', 'Lib2', 2, 1),
|
||||
'H5P.Lib2.2' => $generator->create_library_record('H5P.Lib2', 'Lib2', 2, 2),
|
||||
'H5P.Lib3.1' => $generator->create_library_record('H5P.Lib3', 'Lib3', 3, 1, 0, '', null, null, null, false),
|
||||
'H5P.Lib3.2' => $generator->create_library_record('H5P.Lib3', 'Lib3', 3, 2, 0, '', null, null, null, false),
|
||||
'H5P.Lib4.1' => $generator->create_library_record('H5P.Lib4', 'Lib4', 4, 1, 0, '', null, null, null, false),
|
||||
'H5P.Lib5.1' => $generator->create_library_record('H5P.Lib5', 'Lib5', 5, 1),
|
||||
];
|
||||
|
||||
$countenabledlibraries = $DB->count_records('h5p_libraries', ['enabled' => 1]);
|
||||
$this->assertEquals(4, $countenabledlibraries);
|
||||
|
||||
if ($useid) {
|
||||
$librarydata = ['id' => $libraries[$libraryname]->id];
|
||||
} else if ($uselibraryname) {
|
||||
$librarydata = ['machinename' => $libraryname];
|
||||
} else {
|
||||
$librarydata = ['invalid' => true];
|
||||
}
|
||||
|
||||
if ($exception) {
|
||||
$this->expectException(\moodle_exception::class);
|
||||
}
|
||||
|
||||
$result = api::is_library_enabled((object) $librarydata);
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for test_is_library_enabled().
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function is_library_enabled_provider(): array {
|
||||
return [
|
||||
'Library with 2 versions, one of them disabled' => [
|
||||
'libraryname' => 'H5P.Lib1',
|
||||
'expected' => false,
|
||||
],
|
||||
'Library with 2 versions, all enabled' => [
|
||||
'libraryname' => 'H5P.Lib2',
|
||||
'expected' => true,
|
||||
],
|
||||
'Library with 2 versions, all disabled' => [
|
||||
'libraryname' => 'H5P.Lib3',
|
||||
'expected' => false,
|
||||
],
|
||||
'Library with only one version, disabled' => [
|
||||
'libraryname' => 'H5P.Lib4',
|
||||
'expected' => false,
|
||||
],
|
||||
'Library with only one version, enabled' => [
|
||||
'libraryname' => 'H5P.Lib5',
|
||||
'expected' => true,
|
||||
],
|
||||
'Library with 2 versions, one of them disabled (using id) - 1.1 (disabled)' => [
|
||||
'libraryname' => 'H5P.Lib1.1',
|
||||
'expected' => false,
|
||||
'exception' => false,
|
||||
'useid' => true,
|
||||
],
|
||||
'Library with 2 versions, one of them disabled (using id) - 1.2 (enabled)' => [
|
||||
'libraryname' => 'H5P.Lib1.2',
|
||||
'expected' => true,
|
||||
'exception' => false,
|
||||
'useid' => true,
|
||||
],
|
||||
'Library with 2 versions, all enabled (using id) - 2.1' => [
|
||||
'libraryname' => 'H5P.Lib2.1',
|
||||
'expected' => true,
|
||||
'exception' => false,
|
||||
'useid' => true,
|
||||
],
|
||||
'Library with 2 versions, all enabled (using id) - 2.2' => [
|
||||
'libraryname' => 'H5P.Lib2.2',
|
||||
'expected' => true,
|
||||
'exception' => false,
|
||||
'useid' => true,
|
||||
],
|
||||
'Library with 2 versions, all disabled (using id) - 3.1' => [
|
||||
'libraryname' => 'H5P.Lib3.1',
|
||||
'expected' => false,
|
||||
'exception' => false,
|
||||
'useid' => true,
|
||||
],
|
||||
'Library with 2 versions, all disabled (using id) - 3.2' => [
|
||||
'libraryname' => 'H5P.Lib3.2',
|
||||
'expected' => false,
|
||||
'exception' => false,
|
||||
'useid' => true,
|
||||
],
|
||||
'Library with only one version, disabled (using id)' => [
|
||||
'libraryname' => 'H5P.Lib4.1',
|
||||
'expected' => false,
|
||||
'exception' => false,
|
||||
'useid' => true,
|
||||
],
|
||||
'Library with only one version, enabled (using id)' => [
|
||||
'libraryname' => 'H5P.Lib5.1',
|
||||
'expected' => true,
|
||||
'exception' => false,
|
||||
'useid' => true,
|
||||
],
|
||||
'Unexisting library' => [
|
||||
'libraryname' => 'H5P.Unexisting',
|
||||
'expected' => true,
|
||||
],
|
||||
'Missing required parameters' => [
|
||||
'libraryname' => 'H5P.Unexisting',
|
||||
'expected' => false,
|
||||
'exception' => true,
|
||||
'useid' => false,
|
||||
'uselibraryname' => false,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the behaviour of is_valid_package().
|
||||
* @runInSeparateProcess
|
||||
*
|
||||
* @covers ::is_valid_package
|
||||
* @dataProvider is_valid_package_provider
|
||||
*
|
||||
* @param string $filename The H5P content to validate.
|
||||
* @param bool $expected Expected result after calling the method.
|
||||
* @param bool $isadmin Whether the user calling the method will be admin or not.
|
||||
* @param bool $onlyupdatelibs Whether new libraries can be installed or only the existing ones can be updated.
|
||||
* @param bool $skipcontent Should the content be skipped (so only the libraries will be saved)?
|
||||
*/
|
||||
public function test_is_valid_package(string $filename, bool $expected, bool $isadmin = false, bool $onlyupdatelibs = false,
|
||||
bool $skipcontent = false): void {
|
||||
global $USER;
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
if ($isadmin) {
|
||||
$this->setAdminUser();
|
||||
$user = $USER;
|
||||
} else {
|
||||
// Create a user.
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$this->setUser($user);
|
||||
}
|
||||
|
||||
// Prepare the file.
|
||||
$path = __DIR__ . $filename;
|
||||
$file = helper::create_fake_stored_file_from_path($path, (int)$user->id);
|
||||
|
||||
// Check if the H5P content is valid or not.
|
||||
$result = api::is_valid_package($file, $onlyupdatelibs, $skipcontent);
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for test_is_valid_package().
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function is_valid_package_provider(): array {
|
||||
return [
|
||||
'Valid H5P file (as admin)' => [
|
||||
'filename' => '/fixtures/greeting-card-887.h5p',
|
||||
'expected' => true,
|
||||
'isadmin' => true,
|
||||
],
|
||||
'Valid H5P file (as user) without library update and checking content' => [
|
||||
'filename' => '/fixtures/greeting-card-887.h5p',
|
||||
'expected' => false, // Libraries are missing and user hasn't the right permissions to upload them.
|
||||
'isadmin' => false,
|
||||
'onlyupdatelibs' => false,
|
||||
'skipcontent' => false,
|
||||
],
|
||||
'Valid H5P file (as user) with library update and checking content' => [
|
||||
'filename' => '/fixtures/greeting-card-887.h5p',
|
||||
'expected' => false, // Libraries are missing and user hasn't the right permissions to upload them.
|
||||
'isadmin' => false,
|
||||
'onlyupdatelibs' => true,
|
||||
'skipcontent' => false,
|
||||
],
|
||||
'Valid H5P file (as user) without library update and skipping content' => [
|
||||
'filename' => '/fixtures/greeting-card-887.h5p',
|
||||
'expected' => true, // Content check is skipped so the package will be considered valid.
|
||||
'isadmin' => false,
|
||||
'onlyupdatelibs' => false,
|
||||
'skipcontent' => true,
|
||||
],
|
||||
'Valid H5P file (as user) with library update and skipping content' => [
|
||||
'filename' => '/fixtures/greeting-card-887.h5p',
|
||||
'expected' => true, // Content check is skipped so the package will be considered valid.
|
||||
'isadmin' => false,
|
||||
'onlyupdatelibs' => true,
|
||||
'skipcontent' => true,
|
||||
],
|
||||
'Invalid H5P file (as admin)' => [
|
||||
'filename' => '/fixtures/h5ptest.zip',
|
||||
'expected' => false,
|
||||
'isadmin' => true,
|
||||
],
|
||||
'Invalid H5P file (as user)' => [
|
||||
'filename' => '/fixtures/h5ptest.zip',
|
||||
'expected' => false,
|
||||
'isadmin' => false,
|
||||
],
|
||||
'Invalid H5P file (as user) skipping content' => [
|
||||
'filename' => '/fixtures/h5ptest.zip',
|
||||
'expected' => true, // Content check is skipped so the package will be considered valid.
|
||||
'isadmin' => false,
|
||||
'onlyupdatelibs' => false,
|
||||
'skipcontent' => true,
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -61,3 +61,16 @@ Feature: Upload and list H5P libraries and content types installed
|
||||
And I should not see "H5P.FontIcons"
|
||||
And I should not see "Joubel UI"
|
||||
And I should see "Transition"
|
||||
|
||||
@javascript
|
||||
Scenario: Enable/disable H5P library
|
||||
Given I log in as "admin"
|
||||
And I navigate to "H5P > Manage H5P content types" in site administration
|
||||
And I upload "h5p/tests/fixtures/filltheblanks.h5p" file to "H5P content type" filemanager
|
||||
And I click on "Upload H5P content types" "button" in the "#fitem_id_uploadlibraries" "css_element"
|
||||
When I click on "Disable" "link" in the "Fill in the Blanks" "table_row"
|
||||
Then "Enable" "icon" should exist in the "Fill in the Blanks" "table_row"
|
||||
And "Disable" "icon" should not exist in the "Fill in the Blanks" "table_row"
|
||||
And I click on "Enable" "link" in the "Fill in the Blanks" "table_row"
|
||||
And "Disable" "icon" should exist in the "Fill in the Blanks" "table_row"
|
||||
And "Enable" "icon" should not exist in the "Fill in the Blanks" "table_row"
|
||||
|
@ -37,19 +37,24 @@ use core_h5p\local\library\autoloader;
|
||||
*
|
||||
* @runTestsInSeparateProcesses
|
||||
*/
|
||||
class editor_framework_testcase extends \advanced_testcase {
|
||||
class editor_framework_test extends \advanced_testcase {
|
||||
|
||||
/** @var editor_framework H5P editor_framework instance */
|
||||
protected $editorframework;
|
||||
|
||||
/**
|
||||
* Setup to ensure that fixtures are loaded.
|
||||
*/
|
||||
public static function setupBeforeClass(): void {
|
||||
autoloader::register();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up function for tests.
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
autoloader::register();
|
||||
|
||||
$this->editorframework = new editor_framework();
|
||||
}
|
||||
|
||||
@ -362,7 +367,7 @@ class editor_framework_testcase extends \advanced_testcase {
|
||||
|
||||
$expectedlibraries = [];
|
||||
foreach ($data as $key => $value) {
|
||||
if (isset($value->data)) {
|
||||
if (isset($value->data) && $value->data->runnable) {
|
||||
$value->data->name = $value->data->machinename;
|
||||
$value->data->majorVersion = $value->data->majorversion;
|
||||
$value->data->minorVersion = $value->data->minorversion;
|
||||
|
@ -177,7 +177,7 @@ class core_h5p_generator extends \component_generator_base {
|
||||
'http://tutorial.org', 'http://example.org');
|
||||
$lib1 = $libraries[] = $this->create_library_record('Library1', 'Lib1', 2, 0, 1, '', null, null, 'http://example.org');
|
||||
$lib2 = $libraries[] = $this->create_library_record('Library2', 'Lib2', 2, 1, 1, '', null, 'http://tutorial.org');
|
||||
$lib3 = $libraries[] = $this->create_library_record('Library3', 'Lib3', 3, 2);
|
||||
$lib3 = $libraries[] = $this->create_library_record('Library3', 'Lib3', 3, 2, 1, '', null, null, null, true, 0);
|
||||
$lib4 = $libraries[] = $this->create_library_record('Library4', 'Lib4', 1, 1);
|
||||
$lib5 = $libraries[] = $this->create_library_record('Library5', 'Lib5', 1, 3);
|
||||
|
||||
@ -251,20 +251,22 @@ class core_h5p_generator extends \component_generator_base {
|
||||
* @param string $addto The plugin configuration data
|
||||
* @param string $tutorial The tutorial URL
|
||||
* @param string $examlpe The example URL
|
||||
* @param bool $enabled Whether the library is enabled or not
|
||||
* @param int $runnable Whether the library is runnable (1) or not (0)
|
||||
* @return stdClass An object representing the added library record
|
||||
*/
|
||||
public function create_library_record(string $machinename, string $title, int $majorversion = 1,
|
||||
int $minorversion = 0, int $patchversion = 1, string $semantics = '', string $addto = null,
|
||||
string $tutorial = null, string $example = null): stdClass {
|
||||
string $tutorial = null, string $example = null, bool $enabled = true, int $runnable = 1): stdClass {
|
||||
global $DB;
|
||||
|
||||
$content = array(
|
||||
$content = [
|
||||
'machinename' => $machinename,
|
||||
'title' => $title,
|
||||
'majorversion' => $majorversion,
|
||||
'minorversion' => $minorversion,
|
||||
'patchversion' => $patchversion,
|
||||
'runnable' => 1,
|
||||
'runnable' => $runnable,
|
||||
'fullscreen' => 1,
|
||||
'preloadedjs' => 'js/example.js',
|
||||
'preloadedcss' => 'css/example.css',
|
||||
@ -272,8 +274,9 @@ class core_h5p_generator extends \component_generator_base {
|
||||
'semantics' => $semantics,
|
||||
'addto' => $addto,
|
||||
'tutorial' => $tutorial,
|
||||
'example' => $example
|
||||
);
|
||||
'example' => $example,
|
||||
'enabled' => $enabled,
|
||||
];
|
||||
|
||||
$libraryid = $DB->insert_record('h5p_libraries', $content);
|
||||
|
||||
|
@ -251,6 +251,7 @@ class generator_testcase extends \advanced_testcase {
|
||||
'coremajor' => null,
|
||||
'coreminor' => null,
|
||||
'metadatasettings' => null,
|
||||
'enabled' => 1,
|
||||
];
|
||||
|
||||
$this->assertEquals($expected, $data);
|
||||
|
@ -1,6 +1,17 @@
|
||||
This files describes API changes in core libraries and APIs,
|
||||
information provided here is intended especially for developers.
|
||||
|
||||
=== 3.11 ===
|
||||
* Added $skipcapcheck parameter to H5P constructor, api::create_content_from_pluginfile_url() and
|
||||
api::get_content_from_pluginfile_url() to let skip capabilities check to get the pluginfile URL.
|
||||
* Added new field "enabled" to h5p_libraries to let define if a content type is enabled (1) or not (0).
|
||||
For now, only runnable content-types can be disabled/enabled. When a content-type is disabled, their
|
||||
contents are not displayed and no new contents using it can be created/uploaded.
|
||||
Some extra methods have been added to the api too in order to support this field:
|
||||
- set_library_enabled
|
||||
- is_library_enabled
|
||||
- is_valid_package
|
||||
|
||||
=== 3.10 ===
|
||||
* Added a new cache for h5p_library_files (MDL-69207)
|
||||
|
||||
|
@ -61,6 +61,7 @@ $string['nocontenttypes'] = 'No content types available';
|
||||
$string['notavailable'] = 'Sorry, this content is not available.';
|
||||
$string['nopermissiontodelete'] = 'You do not have permission to delete content.';
|
||||
$string['nopermissiontomanage'] = 'You do not have permission to manage content.';
|
||||
$string['notvalidpackage'] = 'Sorry, this file is not valid.';
|
||||
$string['privacy:metadata:content:contenttype'] = 'The contenttype plugin of the content in the content bank.';
|
||||
$string['privacy:metadata:content:name'] = 'Name of the content in the content bank.';
|
||||
$string['privacy:metadata:content:timecreated'] = 'The time when the content was created.';
|
||||
|
@ -138,6 +138,8 @@ $string['licensee'] = 'Licensee';
|
||||
$string['licenseextras'] = 'Licence extras';
|
||||
$string['licenseversion'] = 'Licence version';
|
||||
$string['lockh5pdeploy'] = 'This H5P content cannot be accessed because it is being deployed. Please try again later.';
|
||||
$string['mainlibrarydisabled'] = 'This file can\'t be displayed because its content-type is disabled. Please contact your administrator to ask for the content type to
|
||||
be enabled.';
|
||||
$string['missingcontentfolder'] = 'A valid content folder is missing';
|
||||
$string['missingcoreversion'] = 'The system was unable to install the {$a->%component} component from the package, as it requires a newer version of the H5P plugin. This site is currently running version {$a->%current}, whereas the required version is {$a->%required} or higher. Please upgrade and then try again.';
|
||||
$string['missingdependency'] = 'Missing dependency {$a->@dep} required by {$a->@lib}.';
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<XMLDB PATH="lib/db" VERSION="20210222" COMMENT="XMLDB file for core Moodle tables"
|
||||
<XMLDB PATH="lib/db" VERSION="20210415" COMMENT="XMLDB file for core Moodle tables"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="../../lib/xmldb/xmldb.xsd"
|
||||
>
|
||||
@ -4203,6 +4203,7 @@
|
||||
<FIELD NAME="metadatasettings" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="Library metadata settings"/>
|
||||
<FIELD NAME="tutorial" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="Tutorial URL"/>
|
||||
<FIELD NAME="example" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="Example URL"/>
|
||||
<FIELD NAME="enabled" TYPE="int" LENGTH="1" NOTNULL="false" DEFAULT="1" SEQUENCE="false" COMMENT="Defines if this library is enabled (1) or not (0)"/>
|
||||
</FIELDS>
|
||||
<KEYS>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
|
||||
|
@ -2545,5 +2545,20 @@ function xmldb_main_upgrade($oldversion) {
|
||||
upgrade_main_savepoint(true, 2021052500.75);
|
||||
}
|
||||
|
||||
if ($oldversion < 2021052500.78) {
|
||||
|
||||
// Define field enabled to be added to h5p_libraries.
|
||||
$table = new xmldb_table('h5p_libraries');
|
||||
$field = new xmldb_field('enabled', XMLDB_TYPE_INTEGER, '1', null, null, null, '1', 'example');
|
||||
|
||||
// Conditionally launch add field enabled.
|
||||
if (!$dbman->field_exists($table, $field)) {
|
||||
$dbman->add_field($table, $field);
|
||||
}
|
||||
|
||||
// Main savepoint reached.
|
||||
upgrade_main_savepoint(true, 2021052500.78);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ use core_contentbank\contentbank;
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @coversDefaultClass \core\event\contentbank_content_uploaded
|
||||
*/
|
||||
class contentbank_content_uploaded_testcase extends \advanced_testcase {
|
||||
class contentbank_content_uploaded_test extends \advanced_testcase {
|
||||
|
||||
/**
|
||||
* Setup to ensure that fixtures are loaded.
|
||||
@ -54,7 +54,7 @@ class contentbank_content_uploaded_testcase extends \advanced_testcase {
|
||||
* @covers ::create_from_record
|
||||
*/
|
||||
public function test_content_created() {
|
||||
global $USER;
|
||||
global $USER, $CFG;
|
||||
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
@ -69,8 +69,8 @@ class contentbank_content_uploaded_testcase extends \advanced_testcase {
|
||||
'filepath' => '/',
|
||||
'filename' => 'dummy_h5p.h5p'
|
||||
);
|
||||
$fs = get_file_storage();
|
||||
$dummyh5pfile = $fs->create_file_from_string($dummyh5p, 'Dummy H5Pcontent');
|
||||
$path = $CFG->dirroot . '/h5p/tests/fixtures/greeting-card-887.h5p';
|
||||
$dummyh5pfile = \core_h5p\helper::create_fake_stored_file_from_path($path);
|
||||
|
||||
// Trigger and capture the event when creating content from a file.
|
||||
$sink = $this->redirectEvents();
|
||||
|
@ -43,7 +43,7 @@ class repository_contentbank_browser_testcase extends advanced_testcase {
|
||||
* the system context.
|
||||
*/
|
||||
public function test_get_content_system_context_user_has_capabilities() {
|
||||
global $DB;
|
||||
global $DB, $CFG;
|
||||
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
@ -66,8 +66,9 @@ class repository_contentbank_browser_testcase extends advanced_testcase {
|
||||
// Add some content to the content bank.
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
|
||||
// Add some content bank files in the system context.
|
||||
$filepath = $CFG->dirroot . '/h5p/tests/fixtures/filltheblanks.h5p';
|
||||
$contentbankcontents = $generator->generate_contentbank_data('contenttype_h5p', 3, $admin->id,
|
||||
$systemcontext, true);
|
||||
$systemcontext, true, $filepath);
|
||||
|
||||
// Log in as admin.
|
||||
$this->setUser($admin);
|
||||
@ -156,6 +157,8 @@ class repository_contentbank_browser_testcase extends advanced_testcase {
|
||||
* any category course should be able to access/view the content in the course category context.
|
||||
*/
|
||||
public function test_get_content_course_category_context_user_has_capabilities() {
|
||||
global $CFG;
|
||||
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
// Create a course category.
|
||||
@ -175,8 +178,9 @@ class repository_contentbank_browser_testcase extends advanced_testcase {
|
||||
// Add some content to the content bank.
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
|
||||
// Add some content bank files in the course category context.
|
||||
$filepath = $CFG->dirroot . '/h5p/tests/fixtures/filltheblanks.h5p';
|
||||
$contentbankcontents = $generator->generate_contentbank_data('contenttype_h5p', 3, $admin->id,
|
||||
$coursecatcontext, true);
|
||||
$coursecatcontext, true, $filepath);
|
||||
|
||||
$this->setUser($admin);
|
||||
// Get the content bank nodes displayed to the admin in the course category context.
|
||||
@ -277,6 +281,8 @@ class repository_contentbank_browser_testcase extends advanced_testcase {
|
||||
* in the course should be able to access/view the content.
|
||||
*/
|
||||
public function test_get_content_course_context_user_has_capabilities() {
|
||||
global $CFG;
|
||||
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
// Create course1.
|
||||
@ -290,8 +296,9 @@ class repository_contentbank_browser_testcase extends advanced_testcase {
|
||||
// Add some content to the content bank.
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
|
||||
// Add some content bank files in the course context.
|
||||
$filepath = $CFG->dirroot . '/h5p/tests/fixtures/filltheblanks.h5p';
|
||||
$contentbankcontents = $generator->generate_contentbank_data('contenttype_h5p', 3, $admin->id,
|
||||
$coursecontext, true);
|
||||
$coursecontext, true, $filepath);
|
||||
|
||||
$this->setUser($admin);
|
||||
// Get the content bank nodes displayed to the admin in the course context.
|
||||
|
@ -182,6 +182,8 @@ class repository_contentbank_search_testcase extends advanced_testcase {
|
||||
* and system content. Other authenticated users should be able to access only the system content.
|
||||
*/
|
||||
public function test_get_search_contents_user_can_access_certain_content() {
|
||||
global $CFG;
|
||||
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
$systemcontext = \context_system::instance();
|
||||
@ -201,16 +203,17 @@ class repository_contentbank_search_testcase extends advanced_testcase {
|
||||
// Add some content to the content bank in different contexts.
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
|
||||
// Add a content bank file in the system context.
|
||||
$filepath = $CFG->dirroot . '/h5p/tests/fixtures/ipsums.h5p';
|
||||
$systemcontents = $generator->generate_contentbank_data('contenttype_h5p', 1, $admin->id,
|
||||
$systemcontext, true, 'file.h5p', 'systemcontentfile');
|
||||
$systemcontext, true, $filepath, 'systemcontentfile');
|
||||
$systemcontent = reset($systemcontents);
|
||||
// Add a content bank file in the course1 context.
|
||||
$course1contents = $generator->generate_contentbank_data('contenttype_h5p', 1, $admin->id,
|
||||
$course1context, true, 'file.h5p', 'coursecontentfile1');
|
||||
$course1context, true, $filepath, 'coursecontentfile1');
|
||||
$course1content = reset($course1contents);
|
||||
// Add a content bank file in the course2 context.
|
||||
$generator->generate_contentbank_data('contenttype_h5p', 1, $admin->id,
|
||||
$course2context, true, 'file.h5p', 'coursecontentfile2');
|
||||
$course2context, true, $filepath, 'coursecontentfile2');
|
||||
|
||||
// Log in as an editing teacher.
|
||||
$this->setUser($editingteacher);
|
||||
|
@ -2466,6 +2466,10 @@ body.h5p-embed {
|
||||
}
|
||||
}
|
||||
|
||||
#h5pcontenttypes td {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.text-decoration-none {
|
||||
text-decoration: none !important; /* stylelint-disable-line declaration-no-important */
|
||||
}
|
||||
|
@ -11660,6 +11660,9 @@ body.h5p-embed #maincontent {
|
||||
body.h5p-embed .h5pmessages {
|
||||
min-height: 230px; }
|
||||
|
||||
#h5pcontenttypes td {
|
||||
vertical-align: middle; }
|
||||
|
||||
.text-decoration-none {
|
||||
text-decoration: none !important;
|
||||
/* stylelint-disable-line declaration-no-important */ }
|
||||
|
@ -11878,6 +11878,9 @@ body.h5p-embed #maincontent {
|
||||
body.h5p-embed .h5pmessages {
|
||||
min-height: 230px; }
|
||||
|
||||
#h5pcontenttypes td {
|
||||
vertical-align: middle; }
|
||||
|
||||
.text-decoration-none {
|
||||
text-decoration: none !important;
|
||||
/* stylelint-disable-line declaration-no-important */ }
|
||||
|
Loading…
x
Reference in New Issue
Block a user