MDL-74129 h5p: Preserve metadata information

The metadata information was not restored when an H5P file was uploaded
(it was saved when it was edited directly from the Content bank, but the
original information in the H5P file was lost).
This patch includes all the metadata fields and its values in the original
H5P file to preserve this information too.
This commit is contained in:
Sara Arjona 2023-11-06 14:04:03 +01:00
parent 8ad9114050
commit 8974392cfa
No known key found for this signature in database
6 changed files with 156 additions and 22 deletions

View File

@ -910,6 +910,13 @@ class framework implements H5PFrameworkInterface {
$params->title = $content['title'];
$content['params'] = json_encode($params);
}
// Add metadata to 'params'.
if (!empty($content['metadata'])) {
$params = json_decode($content['params']);
$params->metadata = $content['metadata'];
$content['params'] = json_encode($params);
}
$data = [
'jsoncontent' => $content['params'],
'displayoptions' => $content['disable'],

View File

@ -66,6 +66,32 @@ class helper {
if (!empty($h5pvalidator->h5pC->mainJsonData['title'])) {
$content['title'] = $h5pvalidator->h5pC->mainJsonData['title'];
}
// If exists, add the metadata from 'h5p.json' to avoid loosing this information.
$data = $h5pvalidator->h5pC->mainJsonData;
if (!empty($data)) {
// The metadata fields are defined in 'joubel/core/h5p-metadata.class.php'.
$metadatafields = [
'title',
'a11yTitle',
'changes',
'authors',
'source',
'license',
'licenseVersion',
'licenseExtras',
'authorComments',
'yearFrom',
'yearTo',
'defaultLanguage',
];
$content['metadata'] = array_reduce($metadatafields, function ($array, $field) use ($data) {
if (array_key_exists($field, $data)) {
$array[$field] = $data[$field];
}
return $array;
}, []);
}
$h5pstorage->savePackage($content, null, $skipcontent, $options);
return $h5pstorage->contentId;

Binary file not shown.

View File

@ -20,6 +20,8 @@ use core_collator;
use Moodle\H5PCore;
use Moodle\H5PDisplayOptionBehaviour;
// phpcs:disable moodle.NamingConventions.ValidFunctionName.LowercaseMethod
/**
*
* Test class covering the H5PFrameworkInterface interface implementation.
@ -28,6 +30,7 @@ use Moodle\H5PDisplayOptionBehaviour;
* @category test
* @copyright 2019 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \core_h5p\framework
* @runTestsInSeparateProcesses
*/
class framework_test extends \advanced_testcase {
@ -1090,6 +1093,55 @@ class framework_test extends \advanced_testcase {
$this->assertEquals($content['disable'], $h5pcontent->displayoptions);
}
/**
* Test the behaviour of updateContent() with metadata.
*
* @covers ::updateContent
*/
public function test_updateContent_withmetadata(): void {
global $DB;
$this->resetAfterTest();
/** @var \core_h5p_generator $generator */
$generator = $this->getDataGenerator()->get_plugin_generator('core_h5p');
// Create a library record.
$lib = $generator->create_library_record('TestLibrary', 'Test', 1, 1, 2);
// Create an h5p content with 'TestLibrary' as it's main library.
$contentid = $generator->create_h5p_record($lib->id);
$params = ['param2' => 'Test2'];
$metadata = [
'license' => 'CC BY',
'licenseVersion' => '4.0',
'yearFrom' => 2000,
'yearTo' => 2023,
'defaultLanguage' => 'ca',
];
$content = [
'id' => $contentid,
'params' => json_encode($params),
'library' => [
'libraryId' => $lib->id,
],
'disable' => 8,
'metadata' => $metadata,
];
// Update the h5p content.
$this->framework->updateContent($content);
$h5pcontent = $DB->get_record('h5p', ['id' => $contentid]);
// Make sure the h5p content was properly updated.
$this->assertNotEmpty($h5pcontent);
$this->assertEquals(json_encode(array_merge($params, ['metadata' => $metadata])), $h5pcontent->jsoncontent);
$this->assertEquals($content['library']['libraryId'], $h5pcontent->mainlibraryid);
$this->assertEquals($content['disable'], $h5pcontent->displayoptions);
}
/**
* Test the behaviour of saveLibraryDependencies().
*/

View File

@ -200,6 +200,57 @@ class helper_test extends \advanced_testcase {
$this->assertStringContainsString('Hello world!', $h5p->jsoncontent);
}
/**
* Test the behaviour of save_h5p() when the H5P file contains metadata.
*
* @runInSeparateProcess
* @covers ::save_h5p
*/
public function test_save_h5p_metadata(): void {
global $DB;
$this->resetAfterTest();
$factory = new \core_h5p\factory();
// Create a user.
$user = $this->getDataGenerator()->create_user();
$this->setUser($user);
// This is a valid .H5P file.
$path = __DIR__ . '/fixtures/guess-the-answer.h5p';
$file = helper::create_fake_stored_file_from_path($path, (int)$user->id);
$factory->get_framework()->set_file($file);
$config = (object)[
'frame' => 1,
'export' => 1,
'embed' => 0,
'copyright' => 1,
];
// The required libraries exist in the system before saving the .h5p file.
$generator = $this->getDataGenerator()->get_plugin_generator('core_h5p');
$lib = $generator->create_library_record('H5P.GuessTheAnswer', 'Guess the Answer', 1, 5);
$generator->create_library_record('H5P.Image', 'Image', 1, 1);
$generator->create_library_record('FontAwesome', 'Font Awesome', 4, 5);
$h5pid = helper::save_h5p($factory, $file, $config);
$this->assertNotEmpty($h5pid);
// No errors are raised.
$errors = $factory->get_framework()->getMessages('error');
$this->assertCount(0, $errors);
// And the content in the .h5p file has been saved as expected.
$h5p = $DB->get_record('h5p', ['id' => $h5pid]);
$this->assertEquals($lib->id, $h5p->mainlibraryid);
$this->assertEquals(helper::get_display_options($factory->get_core(), $config), $h5p->displayoptions);
$this->assertStringContainsString('Which fruit is this?', $h5p->jsoncontent);
// Metadata has been also saved.
$this->assertStringContainsString('This is licence extras information added for testing purposes.', $h5p->jsoncontent);
$this->assertStringContainsString('H5P Author', $h5p->jsoncontent);
$this->assertStringContainsString('Add metadata information', $h5p->jsoncontent);
}
/**
* Test the behaviour of save_h5p() when the .h5p file is invalid.
* @runInSeparateProcess

View File

@ -21,7 +21,7 @@ Feature: Add H5P activity
And I am on "Course 1" course homepage with editing mode on
@javascript
Scenario: Add a h5pactivity activity to a course
Scenario: Add an h5pactivity to a course
Given the following "activity" exists:
| activity | h5pactivity |
| course | C1 |
@ -36,10 +36,9 @@ Feature: Add H5P activity
And I should not see "Reuse"
And I should not see "Rights of use"
And I should not see "Embed"
And I switch to the main frame
@javascript
Scenario: Add a h5pactivity activity with download
Scenario: Add an h5pactivity with download display option
Given the following "activity" exists:
| activity | h5pactivity |
| course | C1 |
@ -47,16 +46,14 @@ Feature: Add H5P activity
| displayoptions | 12 |
| packagefilepath | h5p/tests/fixtures/ipsums.h5p |
When I am on the "Awesome H5P package" "h5pactivity activity" page
And I wait until the page is ready
Then I switch to "h5p-player" class iframe
And I switch to "h5p-iframe" class iframe
And I should see "Reuse"
And "Reuse" "text" should exist in the ".h5p-actions" "css_element"
And I should not see "Rights of use"
And I should not see "Embed"
And I switch to the main frame
@javascript
Scenario: Add a h5pactivity activity with embed
Scenario: Add an h5pactivity with embed display option
Given the following "activity" exists:
| activity | h5pactivity |
| course | C1 |
@ -64,33 +61,38 @@ Feature: Add H5P activity
| displayoptions | 10 |
| packagefilepath | h5p/tests/fixtures/ipsums.h5p |
When I am on the "Awesome H5P package" "h5pactivity activity" page
And I wait until the page is ready
Then I switch to "h5p-player" class iframe
And I switch to "h5p-iframe" class iframe
And I should not see "Reuse"
And "Reuse" "text" should not exist in the ".h5p-actions" "css_element"
And I should not see "Rights of use"
And I should see "Embed"
And I switch to the main frame
@javascript
Scenario: Add a h5pactivity activity with copyright
Scenario: Add an h5pactivity with copyright display option using a content with copyright
Given the following "activity" exists:
| activity | h5pactivity |
| course | C1 |
| name | Awesome H5P package |
| displayoptions | 6 |
| packagefilepath | h5p/tests/fixtures/guess-the-answer.h5p |
And I change window size to "large"
When I am on the "Awesome H5P package" "h5pactivity activity" page
And I wait until the page is ready
Then I switch to "h5p-player" class iframe
And I switch to "h5p-iframe" class iframe
And I should not see "Reuse"
And "Reuse" "text" should not exist in the ".h5p-actions" "css_element"
And I should see "Rights of use"
And I should not see "Embed"
And I switch to the main frame
And I click on "Rights of use" "button" in the ".h5p-actions" "css_element"
And I should see "Fruits"
And I should see "Attribution (CC BY) 4.0 International (CC BY 4.0)"
And I should see "H5P Author"
And I should see "https://h5p.org (Originator)"
And I should see "2000-2023"
And I should see "This is licence extras information added for testing purposes."
And I should see "Add metadata information, Another user, 01-11-23"
@javascript
Scenario: Add a h5pactivity activity with copyright in a content without copyright
Scenario: Add an h5pactivity with copyright display option using a content without copyright
Given the following "activity" exists:
| activity | h5pactivity |
| course | C1 |
@ -98,16 +100,14 @@ Feature: Add H5P activity
| displayoptions | 6 |
| packagefilepath | h5p/tests/fixtures/ipsums.h5p |
When I am on the "Awesome H5P package" "h5pactivity activity" page
And I wait until the page is ready
Then I switch to "h5p-player" class iframe
And I switch to "h5p-iframe" class iframe
And I should not see "Reuse"
And "Reuse" "text" should not exist in the ".h5p-actions" "css_element"
And I should not see "Rights of use"
And I should not see "Embed"
And I switch to the main frame
@javascript
Scenario: Add a h5pactivity activity to a course with all display options enabled
Scenario: Add an h5pactivity with all display options enabled
Given the following "activity" exists:
| activity | h5pactivity |
| course | C1 |
@ -115,10 +115,8 @@ Feature: Add H5P activity
| displayoptions | 0 |
| packagefilepath | h5p/tests/fixtures/guess-the-answer.h5p |
When I am on the "Awesome H5P package" "h5pactivity activity" page
And I wait until the page is ready
Then I switch to "h5p-player" class iframe
And I switch to "h5p-iframe" class iframe
And I should see "Reuse"
And "Reuse" "text" should exist in the ".h5p-actions" "css_element"
And I should see "Rights of use"
And I should see "Embed"
And I switch to the main frame