MDL-69087 core_h5p: add renderer to let personalize styles
authorSara Arjona <sara@moodle.com>
Fri, 4 Sep 2020 16:53:32 +0000 (18:53 +0200)
committerSara Arjona <sara@moodle.com>
Thu, 24 Sep 2020 17:56:42 +0000 (19:56 +0200)
Existing mod_hvp pluging has a renderer to let Moodle instances
alter styles, Javascript, semantics (fields in the editor) and
content: https://github.com/h5p/moodle-mod_hvp/blob/stable/renderer.php

The approach for core_h5p is exactly the same, to let people
to reuse their existing code.

h5p/ajax.php
h5p/classes/editor_framework.php
h5p/classes/framework.php
h5p/classes/output/renderer.php
h5p/classes/player.php
h5p/tests/framework_test.php

index 2291e2f..929d518 100644 (file)
@@ -44,6 +44,9 @@ $action = required_param('action', PARAM_ALPHA);
 $factory = new factory();
 $editor = $factory->get_editor();
 
+// Set context to default system context.
+$PAGE->set_context(null);
+
 switch ($action) {
     // Load list of libraries or details for library.
     case 'libraries':
index 8d7f9b4..8f97a36 100644 (file)
@@ -265,7 +265,22 @@ class editor_framework implements H5peditorStorage {
      *     minorVersion as properties.
      */
     public function alterLibraryFiles(&$files, $libraries): void {
-        // This is to be implemented when the renderer is used.
+        global $PAGE;
+
+        // Refactor dependency list.
+        $librarylist = [];
+        foreach ($libraries as $dependency) {
+            $librarylist[$dependency['machineName']] = [
+                'majorVersion' => $dependency['majorVersion'],
+                'minorVersion' => $dependency['minorVersion']
+            ];
+        }
+
+        $renderer = $PAGE->get_renderer('core_h5p');
+
+        $embedtype = 'editor';
+        $renderer->h5p_alter_scripts($files['scripts'], $librarylist, $embedtype);
+        $renderer->h5p_alter_styles($files['styles'], $librarylist, $embedtype);
     }
 
     /**
index 4b05422..fa8fa6b 100644 (file)
@@ -1093,20 +1093,10 @@ class framework implements \H5PFrameworkInterface {
      * @param int $minorversion The library's minor version
      */
     public function alterLibrarySemantics(&$semantics, $name, $majorversion, $minorversion) {
-        global $DB;
+        global $PAGE;
 
-        $library = $DB->get_record('h5p_libraries',
-            array(
-                'machinename' => $name,
-                'majorversion' => $majorversion,
-                'minorversion' => $minorversion,
-            )
-        );
-
-        if ($library) {
-            $library->semantics = json_encode($semantics);
-            $DB->update_record('h5p_libraries', $library);
-        }
+        $renderer = $PAGE->get_renderer('core_h5p');
+        $renderer->h5p_alter_semantics($semantics, $name, $majorversion, $minorversion);
     }
 
     /**
index e5720c5..0d25f2a 100644 (file)
@@ -37,4 +37,49 @@ use plugin_renderer_base;
  */
 class renderer extends plugin_renderer_base {
 
-}
\ No newline at end of file
+    /**
+     * Alter which stylesheets are loaded for H5P.
+     * This is useful for adding custom styles or replacing existing ones.
+     *
+     * @param array|object $scripts List of stylesheets that will be loaded
+     * @param array $libraries Array of libraries indexed by the library's machineName
+     * @param string $embedtype Possible values: div, iframe, external, editor
+     */
+    public function h5p_alter_styles(&$scripts, array $libraries, string $embedtype) {
+    }
+
+    /**
+     * Alter which scripts are loaded for H5P.
+     * This is useful for adding custom scripts or replacing existing ones.
+     *
+     * @param array|object $scripts List of JavaScripts that will be loaded
+     * @param array $libraries Array of libraries indexed by the library's machineName
+     * @param string $embedtype Possible values: div, iframe, external, editor
+     */
+    public function h5p_alter_scripts(&$scripts, array $libraries, string $embedtype) {
+    }
+
+    /**
+     * Alter semantics before they are processed. This is useful for changing
+     * how the editor looks and how content parameters are filtered.
+     *
+     * @param object|object $semantics Semantics as object
+     * @param string $name Machine name of library
+     * @param int $majorversion Major version of library
+     * @param int $minorversion Minor version of library
+     */
+    public function h5p_alter_semantics(&$semantics, $name, $majorversion, $minorversion) {
+    }
+
+    /**
+     * Alter parameters of H5P content after it has been filtered through semantics.
+     * This is useful for adapting the content to the current context.
+     *
+     * @param array|object $parameters The content parameters for the library
+     * @param string $name The machine readable name of the library
+     * @param int $majorversion Major version of the library
+     * @param int $minorversion Minor version of the library
+     */
+    public function h5p_alter_filtered_parameters(&$parameters, string $name, int $majorversion, int $minorversion) {
+    }
+}
index a94d9b1..6647594 100644 (file)
@@ -357,7 +357,7 @@ class player {
         $cid = $this->get_cid();
         // The filterParameters function should be called before getting the dependencyfiles because it rebuild content
         // dependency cache and export file.
-        $settings['contents'][$cid]['jsonContent'] = $this->core->filterParameters($this->content);
+        $settings['contents'][$cid]['jsonContent'] = $this->get_filtered_parameters();
 
         $files = $this->get_dependency_files();
         if ($this->embedtype === 'div') {
@@ -398,15 +398,44 @@ class player {
         return $settings;
     }
 
+    /**
+     * Get filtered parameters, modifying them by the renderer if the theme implements the h5p_alter_filtered_parameters function.
+     *
+     * @return string Filtered parameters.
+     */
+    private function get_filtered_parameters(): string {
+        global $PAGE;
+
+        $safeparams = $this->core->filterParameters($this->content);
+        $decodedparams = json_decode($safeparams);
+        $h5poutput = $PAGE->get_renderer('core_h5p');
+        $h5poutput->h5p_alter_filtered_parameters(
+            $decodedparams,
+            $this->content['library']['name'],
+            $this->content['library']['majorVersion'],
+            $this->content['library']['minorVersion']
+        );
+        $safeparams = json_encode($decodedparams);
+
+        return $safeparams;
+    }
+
     /**
      * Finds library dependencies of view
      *
      * @return array Files that the view has dependencies to
      */
     private function get_dependency_files(): array {
+        global $PAGE;
+
         $preloadeddeps = $this->core->loadContentDependencies($this->h5pid, 'preloaded');
         $files = $this->core->getDependenciesFiles($preloadeddeps);
 
+        // Add additional asset files if required.
+        $h5poutput = $PAGE->get_renderer('core_h5p');
+        $h5poutput->h5p_alter_scripts($files['scripts'], $preloadeddeps, $this->embedtype);
+        $h5poutput->h5p_alter_styles($files['styles'], $preloadeddeps, $this->embedtype);
+
         return $files;
     }
 
index de4be46..1a2c18b 100644 (file)
@@ -1457,8 +1457,8 @@ class framework_testcase extends \advanced_testcase {
         // Get the semantics of 'Library1' from the DB.
         $currentsemantics = $DB->get_field('h5p_libraries', 'semantics', array('id' => $library1->id));
 
-        // The semantics for Library1 should be successfully updated.
-        $this->assertEquals(json_encode($updatedsemantics), $currentsemantics);
+        // The semantics for Library1 shouldn't be updated.
+        $this->assertEquals($semantics, $currentsemantics);
     }
 
     /**