function __construct($interface, $files_directory)
 {
     $field = filter_input(INPUT_POST, 'field', FILTER_SANITIZE_STRING, FILTER_FLAG_NO_ENCODE_QUOTES);
     // Check for file upload.
     if ($field === NULL || empty($_FILES) || !isset($_FILES['file'])) {
         return;
     }
     $this->interface = $interface;
     // Create a new result object.
     $this->result = new stdClass();
     // Set directory.
     $this->files_directory = $files_directory;
     // Create the temporary directory if it doesn't exist.
     $dirs = array('', '/files', '/images', '/videos', '/audios');
     foreach ($dirs as $dir) {
         if (!H5PCore::dirReady($this->files_directory . $dir)) {
             $this->result->error = $this->interface->t('Unable to create directory.');
             return;
         }
     }
     // Get the field.
     $this->field = json_decode($field);
     if (function_exists('finfo_file')) {
         $finfo = finfo_open(FILEINFO_MIME_TYPE);
         $this->type = finfo_file($finfo, $_FILES['file']['tmp_name']);
         finfo_close($finfo);
     } elseif (function_exists('mime_content_type')) {
         // Deprecated, only when finfo isn't available.
         $this->type = mime_content_type($_FILES['file']['tmp_name']);
     } else {
         $this->type = $_FILES['file']['type'];
     }
     $this->extension = pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION);
     $this->size = $_FILES['file']['size'];
 }
Пример #2
0
 public static function handle_ajax()
 {
     global $DB, $USER;
     if (!\H5PCore::validToken('result', required_param('token', PARAM_RAW))) {
         \H5PCore::ajaxError(get_string('invalidtoken', 'hvp'));
         exit;
     }
     // Content parameters
     $content_id = required_param('contentId', PARAM_INT);
     $score = required_param('score', PARAM_INT);
     $max_score = required_param('maxScore', PARAM_INT);
     // Time values not usable by gradebook
     // $opened = required_param('opened', PARAM_INT);
     // $finished = required_param('finished', PARAM_INT);
     // Get hvp data from contentId
     $hvp = $DB->get_record('hvp', array('id' => $content_id));
     // Check permissions
     $context = \context_course::instance($hvp->course);
     if (!has_capability('mod/hvp:saveresults', $context)) {
         \H5PCore::ajaxError(get_string('nopermissiontosaveresult', 'hvp'));
         http_response_code(403);
         exit;
     }
     // Create grade object and set grades
     $grade = (object) array('userid' => $USER->id);
     // Get course module id from db, required for grade item
     $cm_id_sql = "SELECT cm.id, h.name\n            FROM {course_modules} cm, {hvp} h, {modules} m\n            WHERE cm.instance = h.id AND h.id = ? AND m.name = 'hvp' AND m.id = cm.module";
     $result = $DB->get_record_sql($cm_id_sql, array($content_id));
     // Set grade using Gradebook API
     $hvp->cmidnumber = $result->id;
     $hvp->name = $result->name;
     $hvp->rawgrade = $score;
     $hvp->rawgrademax = $max_score;
     hvp_grade_item_update($hvp, $grade);
     // Get content info for log
     $content = $DB->get_record_sql("SELECT c.name AS title, l.machine_name AS name, l.major_version, l.minor_version\n                   FROM {hvp} c\n                   JOIN {hvp_libraries} l ON l.id = c.main_library_id\n                  WHERE c.id = ?", array($content_id));
     // Log view
     new \mod_hvp\event('results', 'set', $content_id, $content->title, $content->name, $content->major_version . '.' . $content->minor_version);
     \H5PCore::ajaxSuccess();
     exit;
 }
Пример #3
0
 /**
  * Print results data
  */
 public function print_results()
 {
     global $DB;
     // Check permission
     $course = $DB->get_field('hvp', 'course', array('id' => $this->content_id));
     $context = \context_course::instance($course);
     if (!has_capability('mod/hvp:viewresults', $context)) {
         \H5PCore::ajaxError(get_string('nopermissiontoviewresult', 'hvp'));
         http_response_code(403);
         exit;
     }
     $results = $this->get_results();
     // Make data readable for humans
     $rows = array();
     foreach ($results as $result) {
         $rows[] = array(\html_writer::link(new \moodle_url('/user/view.php', array('id' => $result->user_id, 'course' => $course)), \fullname($result)), $result->rawgrade === null ? '—' : (int) $result->rawgrade, $result->rawgrade === null ? '—' : (int) $result->rawgrademax, empty($result->timemodified) ? '—' : date('Y/m/d – H:i', $result->timemodified));
     }
     // Print
     header('Cache-Control: no-cache');
     header('Content-type: application/json');
     print json_encode(array('num' => $this->get_results_num(), 'rows' => $rows));
 }
Пример #4
0
 /**
  * Fetch library folder and save in target directory.
  *
  * @param array $library
  *  Library properties
  * @param string $target
  *  Where the library folder will be saved
  */
 public function exportLibrary($library, $target)
 {
     $folder = \H5PCore::libraryToString($library, true);
     $context = \context_system::instance();
     self::exportFileTree("{$target}/{$folder}", $context->id, 'libraries', "/{$folder}/");
 }
Пример #5
0
    }
}
if (empty($export)) {
    // Remove Download button when there's no export URL
    $content['disable'] |= \H5PCore::DISABLE_DOWNLOAD;
}
// Find cm context
$context = \context_module::instance($cm->id);
// Add JavaScript settings for this content.
$cid = 'cid-' . $content['id'];
$settings['contents'][$cid] = array('library' => \H5PCore::libraryToString($content['library']), 'jsonContent' => $safeparameters, 'fullScreen' => $content['library']['fullscreen'], 'exportUrl' => $export, 'title' => $content['title'], 'disable' => $content['disable'], 'url' => "{$CFG->httpswwwroot}/mod/hvp/view.php?id={$id}", 'contentUrl' => "{$CFG->httpswwwroot}/pluginfile.php/{$context->id}/mod_hvp/content/" . $content['id'], 'contentUserData' => array(0 => \mod_hvp\content_user_data::load_pre_loaded_user_data($content['id'])));
// Get assets for this content.
$preloadeddependencies = $core->loadContentDependencies($content['id'], 'preloaded');
$files = $core->getDependenciesFiles($preloadeddependencies);
// Determine embed type.
$embedtype = \H5PCore::determineEmbedType($content['embedType'], $content['library']['embedTypes']);
if ($embedtype === 'div') {
    $context = \context_system::instance();
    $hvppath = "/pluginfile.php/{$context->id}/mod_hvp";
    // Schedule JavaScripts for loading through Moodle.
    foreach ($files['scripts'] as $script) {
        $url = $hvppath . $script->path . $script->version;
        $settings['loadedJs'][] = $url;
        $PAGE->requires->js(new moodle_url($CFG->httpswwwroot . $url), true);
    }
    // Schedule stylesheets for loading through Moodle.
    foreach ($files['styles'] as $style) {
        $url = $hvppath . $style->path . $style->version;
        $settings['loadedCss'][] = $url;
        $PAGE->requires->css(new moodle_url($CFG->httpswwwroot . $url));
    }
Пример #6
0
    }
    // Schedule stylesheets for loading through Moodle.
    foreach ($files['styles'] as $style) {
        $url = $hvppath . $style->path . $style->version;
        $settings['loadedCss'][] = $url;
        $PAGE->requires->css(new moodle_url($CFG->httpswwwroot . $url));
    }
} else {
    // JavaScripts and stylesheets will be loaded through h5p.js.
    $settings['contents'][$cid]['scripts'] = $core->getAssetsUrls($files['scripts']);
    $settings['contents'][$cid]['styles'] = $core->getAssetsUrls($files['styles']);
}
// Print JavaScript settings to page.
$PAGE->requires->data_for_js('H5PIntegration', $settings, true);
// H5P JS xAPI event listener & Moodle event log dispatcher.
$jsparams = array('hvpid' => $id, 'courseid' => $course->id, 'debug' => $CFG->debug, 'token' => \H5PCore::createToken('logxapievent'));
$PAGE->requires->js_call_amd('mod_hvp/xapi-stmt-dispatcher', 'init', array($jsparams));
// Print page HTML.
echo $OUTPUT->header();
echo $OUTPUT->heading(format_string($content['title']));
echo '<div class="clearer"></div>';
// Print any messages.
\mod_hvp\framework::printMessages('info', \mod_hvp\framework::messages('info'));
\mod_hvp\framework::printMessages('error', \mod_hvp\framework::messages('error'));
// Print intro.
if (trim(strip_tags($content['intro']))) {
    echo $OUTPUT->box_start('mod_introbox', 'hvpintro');
    echo format_module_intro('hvp', (object) array('intro' => $content['intro'], 'introformat' => $content['introformat']), $cm->id);
    echo $OUTPUT->box_end();
}
// Print H5P Content
 /**
  * Include settings and assets for the given content.
  *
  * @since 1.0.0
  * @param array $content
  * @param boolean $no_cache
  * @return string Embed code
  */
 public function add_assets($content, $no_cache = FALSE)
 {
     // Add core assets
     $this->add_core_assets();
     // Detemine embed type
     $embed = H5PCore::determineEmbedType($content['embedType'], $content['library']['embedTypes']);
     // Make sure content isn't added twice
     $cid = 'cid-' . $content['id'];
     if (!isset(self::$settings['contents'][$cid])) {
         self::$settings['contents'][$cid] = $this->get_content_settings($content);
         $core = $this->get_h5p_instance('core');
         // Get assets for this content
         $preloaded_dependencies = $core->loadContentDependencies($content['id'], 'preloaded');
         $files = $core->getDependenciesFiles($preloaded_dependencies);
         $this->alter_assets($files, $preloaded_dependencies, $embed);
         if ($embed === 'div') {
             $this->enqueue_assets($files);
         } elseif ($embed === 'iframe') {
             self::$settings['contents'][$cid]['scripts'] = $core->getAssetsUrls($files['scripts']);
             self::$settings['contents'][$cid]['styles'] = $core->getAssetsUrls($files['styles']);
         }
     }
     if ($embed === 'div') {
         return '<div class="h5p-content" data-content-id="' . $content['id'] . '"></div>';
     } else {
         return '<div class="h5p-iframe-wrapper"><iframe id="h5p-iframe-' . $content['id'] . '" class="h5p-iframe" data-content-id="' . $content['id'] . '" style="height:1px" src="about:blank" frameBorder="0" scrolling="no"></iframe></div>';
     }
 }
Пример #8
0
 /**
  * Process a single field.
  *
  * @staticvar string $h5peditor_path
  * @param object $field
  * @param mixed $params
  * @param array $files
  */
 private function processField(&$field, &$params, &$files)
 {
     switch ($field->type) {
         case 'file':
         case 'image':
             if (isset($params->path)) {
                 $this->processFile($params, $files);
                 // Process original image
                 if (isset($params->originalImage) && isset($params->originalImage->path)) {
                     $this->processFile($params->originalImage, $files);
                 }
             }
             break;
         case 'video':
         case 'audio':
             if (is_array($params)) {
                 for ($i = 0, $s = count($params); $i < $s; $i++) {
                     $this->processFile($params[$i], $files);
                 }
             }
             break;
         case 'library':
             if (isset($params->library) && isset($params->params)) {
                 $library = H5PCore::libraryFromString($params->library);
                 $semantics = $this->h5p->loadLibrarySemantics($library['machineName'], $library['majorVersion'], $library['minorVersion']);
                 // Process parameters for the library.
                 $this->processSemantics($files, $semantics, $params->params);
             }
             break;
         case 'group':
             if (isset($params)) {
                 if (count($field->fields) == 1) {
                     $params = (object) array($field->fields[0]->name => $params);
                 }
                 $this->processSemantics($files, $field->fields, $params);
             }
             break;
         case 'list':
             if (is_array($params)) {
                 for ($j = 0, $t = count($params); $j < $t; $j++) {
                     $this->processField($field->field, $params[$j], $files);
                 }
             }
             break;
     }
 }
Пример #9
0
 /**
  * Validate given library value against library semantics.
  * Check if provided library is within allowed options.
  *
  * Will recurse into validating the library's semantics too.
  */
 public function validateLibrary(&$value, $semantics)
 {
     if (!isset($value->library) || !in_array($value->library, $semantics->options)) {
         $this->h5pF->setErrorMessage($this->h5pF->t('Library used in content is not a valid library according to semantics'));
         $value = new stdClass();
         return;
     }
     if (!isset($this->libraries[$value->library])) {
         $libspec = H5PCore::libraryFromString($value->library);
         $library = $this->h5pC->loadLibrary($libspec['machineName'], $libspec['majorVersion'], $libspec['minorVersion']);
         $library['semantics'] = $this->h5pC->loadLibrarySemantics($libspec['machineName'], $libspec['majorVersion'], $libspec['minorVersion']);
         $this->libraries[$value->library] = $library;
     } else {
         $library = $this->libraries[$value->library];
     }
     $this->validateGroup($value->params, (object) array('type' => 'group', 'fields' => $library['semantics']), FALSE);
     $validkeys = array('library', 'params');
     if (isset($semantics->extraAttributes)) {
         $validkeys = array_merge($validkeys, $semantics->extraAttributes);
     }
     $this->filterParams($value, $validkeys);
     // Find all dependencies for this library
     $depkey = 'preloaded-' . $library['machineName'];
     if (!isset($this->dependencies[$depkey])) {
         $this->dependencies[$depkey] = array('library' => $library, 'type' => 'preloaded');
         $this->nextWeight = $this->h5pC->findLibraryDependencies($this->dependencies, $library, $this->nextWeight);
         $this->dependencies[$depkey]['weight'] = $this->nextWeight++;
     }
 }
                                   FROM {hvp_libraries} hl1 JOIN {hvp_libraries} hl2 ON hl1.machine_name = hl2.machine_name
                                  WHERE hl1.id = ?
                               ORDER BY hl2.title ASC, hl2.major_version ASC, hl2.minor_version ASC', array($libraryid));
$versions = array();
foreach ($results as $result) {
    $versions[$result->id] = $result;
}
$library = $versions[$libraryid];
$upgrades = $core->getUpgrades($library, $versions);
$PAGE->set_heading(get_string('upgradeheading', 'hvp', $library->title . ' (' . \H5PCore::libraryVersion($library) . ')'));
// Get num of contents that can be upgraded.
$numcontents = $core->h5pF->getNumContent($libraryid);
if (count($versions) < 2) {
    echo $OUTPUT->header();
    echo get_string('upgradenoavailableupgrades', 'hvp');
} else {
    if ($numcontents === 0) {
        echo $OUTPUT->header();
        echo get_string('upgradenothingtodo', 'hvp');
    } else {
        $settings = array('libraryInfo' => array('message' => get_string('upgrademessage', 'hvp', $numcontents), 'inProgress' => get_string('upgradeinprogress', 'hvp'), 'error' => get_string('upgradeerror', 'hvp'), 'errorData' => get_string('upgradeerrordata', 'hvp'), 'errorScript' => get_string('upgradeerrorscript', 'hvp'), 'errorContent' => get_string('upgradeerrorcontent', 'hvp'), 'errorParamsBroken' => get_string('upgradeerrorparamsbroken', 'hvp'), 'done' => get_string('upgradedone', 'hvp', $numcontents) . ' <a href="' . (new moodle_url('/mod/hvp/library_list.php'))->out(false) . '">' . get_string('upgradereturn', 'hvp') . '</a>', 'library' => array('name' => $library->name, 'version' => $library->major_version . '.' . $library->minor_version), 'libraryBaseUrl' => (new moodle_url('/mod/hvp/ajax.php', array('action' => 'getlibrarydataforupgrade')))->out(false) . '&library=', 'scriptBaseUrl' => (new moodle_url('/mod/hvp/library/js'))->out(false), 'buster' => hvp_get_cache_buster(), 'versions' => $upgrades, 'contents' => $numcontents, 'buttonLabel' => get_string('upgradebuttonlabel', 'hvp'), 'infoUrl' => (new moodle_url('/mod/hvp/ajax.php', array('action' => 'libraryupgradeprogress', 'library_id' => $libraryid)))->out(false), 'total' => $numcontents, 'token' => \H5PCore::createToken('contentupgrade')));
        // Add JavaScripts.
        $liburl = $CFG->httpswwwroot . '/mod/hvp/library/';
        hvp_admin_add_generic_css_and_js($PAGE, $liburl, $settings);
        $PAGE->requires->js(new moodle_url($liburl . 'js/h5p-version.js' . hvp_get_cache_buster()), true);
        $PAGE->requires->js(new moodle_url($liburl . 'js/h5p-content-upgrade.js' . hvp_get_cache_buster()), true);
        echo $OUTPUT->header();
        echo '<div id="h5p-admin-container">' . get_string('enablejavascript', 'hvp') . '</div>';
    }
}
echo $OUTPUT->footer();
Пример #11
0
        global $CFG;
        // Trigger a Moodle log event for each xAPI statement
        // that is dispatched by the H5P (hvp) object.
        if (!\H5PCore::validToken('logxapievent', required_param('token', PARAM_RAW))) {
            \H5PCore::ajaxError(get_string('invalidtoken', 'hvp'));
            exit;
        }
        $hvpid = optional_param('hvpid', null, PARAM_INT);
        $courseid = optional_param('courseid', null, PARAM_INT);
        $jsonxapistatement = optional_param('xapistatement', null, PARAM_RAW);
        $xapistatement = json_decode($jsonxapistatement, true);
        $context = \context_module::instance($hvpid);
        $event = \mod_hvp\event\hvp_xapi::create(array('objectid' => $hvpid, 'context' => $context, 'other' => array('statement' => $xapistatement['data']['statement']), 'courseid' => $courseid));
        $event->trigger();
        // Debugging...
        if (!empty($CFG->debug) and $CFG->debug >= DEBUG_DEVELOPER) {
            $msg = "xAPI '" . $xapistatement['data']['statement']['verb']['display']['en-US'] . "' statement dispatched";
            \H5PCore::ajaxSuccess($msg);
            http_response_code(200);
        }
        break;
        /*
         * Throw error if AJAX isnt handeled
         */
    /*
     * Throw error if AJAX isnt handeled
     */
    default:
        throw new coding_exception('Unhandled AJAX');
        break;
}
Пример #12
0
 /**
  * Implements deleteLibrary
  */
 public function deleteLibrary($library)
 {
     global $wpdb;
     // Delete library files
     H5PCore::deleteFileTree($this->getH5pPath() . '/libraries/' . $library->name . '-' . $library->major_version . '.' . $library->minor_version);
     // Remove library data from database
     $wpdb->delete($wpdb->prefix . 'h5p_libraries_libraries', array('library_id' => $library->id), array('%d'));
     $wpdb->delete($wpdb->prefix . 'h5p_libraries_languages', array('library_id' => $library->id), array('%d'));
     $wpdb->delete($wpdb->prefix . 'h5p_libraries', array('id' => $library->id), array('%d'));
 }
 /**
  * Handle user results reported by the H5P content.
  *
  * @since 1.5.0
  */
 public function ajax_contents_user_data()
 {
     global $wpdb;
     $content_id = filter_input(INPUT_GET, 'content_id');
     $data_id = filter_input(INPUT_GET, 'data_type');
     $sub_content_id = filter_input(INPUT_GET, 'sub_content_id');
     $current_user = wp_get_current_user();
     if ($content_id === NULL || $data_id === NULL || $sub_content_id === NULL || !$current_user->ID) {
         return;
         // Missing parameters
     }
     $response = (object) array('success' => TRUE);
     $data = filter_input(INPUT_POST, 'data');
     $preload = filter_input(INPUT_POST, 'preload');
     $invalidate = filter_input(INPUT_POST, 'invalidate');
     if ($data !== NULL && $preload !== NULL && $invalidate !== NULL) {
         if (!wp_verify_nonce(filter_input(INPUT_POST, 'token'), 'h5p_contentuserdata')) {
             H5PCore::ajaxError(__('Invalid security token', $this->plugin_slug));
             exit;
         }
         if ($data === '0') {
             // Remove data
             $wpdb->delete($wpdb->prefix . 'h5p_contents_user_data', array('content_id' => $content_id, 'data_id' => $data_id, 'user_id' => $current_user->ID, 'sub_content_id' => $sub_content_id), array('%d', '%s', '%d', '%d'));
         } else {
             // Wash values to ensure 0 or 1.
             $preload = $preload === '0' ? 0 : 1;
             $invalidate = $invalidate === '0' ? 0 : 1;
             // Determine if we should update or insert
             $update = $wpdb->get_var($wpdb->prepare("SELECT content_id\n           FROM {$wpdb->prefix}h5p_contents_user_data\n           WHERE content_id = %d\n             AND user_id = %d\n             AND data_id = %s\n             AND sub_content_id = %d", $content_id, $current_user->ID, $data_id, $sub_content_id));
             if ($update === NULL) {
                 // Insert new data
                 $wpdb->insert($wpdb->prefix . 'h5p_contents_user_data', array('user_id' => $current_user->ID, 'content_id' => $content_id, 'sub_content_id' => $sub_content_id, 'data_id' => $data_id, 'data' => $data, 'preload' => $preload, 'invalidate' => $invalidate, 'updated_at' => current_time('mysql', 1)), array('%d', '%d', '%d', '%s', '%s', '%d', '%d', '%s'));
             } else {
                 // Update old data
                 $wpdb->update($wpdb->prefix . 'h5p_contents_user_data', array('data' => $data, 'preload' => $preload, 'invalidate' => $invalidate, 'updated_at' => current_time('mysql', 1)), array('user_id' => $current_user->ID, 'content_id' => $content_id, 'data_id' => $data_id, 'sub_content_id' => $sub_content_id), array('%s', '%d', '%d', '%s'), array('%d', '%d', '%s', '%d'));
             }
         }
         // Inserted, updated or deleted
         H5PCore::ajaxSuccess();
         exit;
     } else {
         // Fetch data
         $response->data = $wpdb->get_var($wpdb->prepare("SELECT hcud.data\n         FROM {$wpdb->prefix}h5p_contents_user_data hcud\n         WHERE user_id = %d\n           AND content_id = %d\n           AND data_id = %s\n           AND sub_content_id = %d", $current_user->ID, $content_id, $data_id, $sub_content_id));
         if ($response->data === NULL) {
             unset($response->data);
         }
     }
     header('Cache-Control: no-cache');
     header('Content-type: application/json; charset=utf-8');
     print json_encode($response);
     exit;
 }
Пример #14
0
/**
 * Handle content upgrade progress
 *
 * @method hvp_content_upgrade_progress
 * @param  int $library_id
 * @return object An object including the json content for the H5P instances
 *                (maximum 40) that should be upgraded.
 */
function hvp_content_upgrade_progress($libraryid)
{
    global $DB;
    $tolibraryid = filter_input(INPUT_POST, 'libraryId');
    // Verify security token.
    if (!\H5PCore::validToken('contentupgrade', required_param('token', PARAM_RAW))) {
        print get_string('upgradeinvalidtoken', 'hvp');
        return;
    }
    // Get the library we're upgrading to.
    $tolibrary = $DB->get_record('hvp_libraries', array('id' => $tolibraryid));
    if (!$tolibrary) {
        print get_string('upgradelibrarymissing', 'hvp');
        return;
    }
    // Prepare response.
    $out = new stdClass();
    $out->params = array();
    $out->token = \H5PCore::createToken('contentupgrade');
    // Prepare our interface.
    $interface = \mod_hvp\framework::instance('interface');
    // Get updated params.
    $params = filter_input(INPUT_POST, 'params');
    if ($params !== null) {
        // Update params.
        $params = json_decode($params);
        foreach ($params as $id => $param) {
            $DB->update_record('hvp', (object) array('id' => $id, 'main_library_id' => $tolibrary->id, 'json_content' => $param, 'filtered' => ''));
            // Log content upgrade successful
            new \mod_hvp\event('content', 'upgrade', $id, $DB->get_field_sql("SELECT name FROM {hvp} WHERE id = ?", array($id)), $tolibrary->machine_name, $tolibrary->major_version . '.' . $tolibrary->minor_version);
        }
    }
    // Get number of contents for this library.
    $out->left = $interface->getNumContent($libraryid);
    if ($out->left) {
        // Find the 40 first contents using this library version and add to params.
        $results = $DB->get_records_sql("SELECT id, json_content as params\n               FROM {hvp}\n              WHERE main_library_id = ?\n           ORDER BY name ASC", array($libraryid), 0, 40);
        foreach ($results as $content) {
            $out->params[$content->id] = $content->params;
        }
    }
    return $out;
}
 /**
  * Handle file uploads through AJAX.
  *
  * @since 1.1.0
  */
 public function ajax_files()
 {
     $plugin = H5P_Plugin::get_instance();
     $files_directory = $plugin->get_h5p_path();
     if (!wp_verify_nonce(filter_input(INPUT_GET, 'token', FILTER_SANITIZE_STRING), 'h5p_editor_ajax')) {
         H5PCore::ajaxError(__('Invalid security token. Please reload the editor.', $this->plugin_slug));
         exit;
     }
     $contentId = filter_input(INPUT_POST, 'contentId', FILTER_SANITIZE_NUMBER_INT);
     if ($contentId) {
         $files_directory .= '/content/' . $contentId;
     } else {
         $files_directory .= '/editor';
     }
     $editor = $this->get_h5peditor_instance();
     $interface = $plugin->get_h5p_instance('interface');
     $file = new H5peditorFile($interface, $files_directory);
     if (!$file->isLoaded()) {
         H5PCore::ajaxError(__('File not found on server. Check file upload settings.', $this->plugin_slug));
         exit;
     }
     if ($file->validate() && $file->copy()) {
         // Keep track of temporary files so they can be cleaned up later.
         $editor->addTmpFile($file);
     }
     header('Cache-Control: no-cache');
     // Must support IE, so cannot use application/json
     header('Content-type: text/plain; charset=utf-8');
     print $file->getResult();
     exit;
 }
Пример #16
0
/**
 * Does the actual process of saving the H5P content that's submitted through
 * the activity form
 *
 * @param stdClass $hvp
 * @return int Content ID
 */
function hvp_save_content($hvp)
{
    // Determine disabled content features
    $hvp->disable = hvp_get_disabled_content_features($hvp);
    // Determine if we're uploading or creating
    if ($hvp->h5paction === 'upload') {
        // Save uploaded package
        $hvp->uploaded = true;
        $h5pstorage = \mod_hvp\framework::instance('storage');
        $h5pstorage->savePackage((array) $hvp);
        $hvp->id = $h5pstorage->contentId;
    } else {
        // Save newly created or edited content
        $core = \mod_hvp\framework::instance();
        $editor = \mod_hvp\framework::instance('editor');
        if (!empty($hvp->id)) {
            // Load existing content to get old parameters for comparison
            $content = $core->loadContent($hvp->id);
            $oldlib = $content['library'];
            $oldparams = json_decode($content['params']);
        }
        // Make params and library available for core to save
        $hvp->params = $hvp->h5pparams;
        $hvp->library = H5PCore::libraryFromString($hvp->h5plibrary);
        $hvp->library['libraryId'] = $core->h5pF->getLibraryId($hvp->library['machineName'], $hvp->library['majorVersion'], $hvp->library['minorVersion']);
        $hvp->id = $core->saveContent((array) $hvp);
        // We need to process the parameters to move any images or files and
        // to determine which dependencies the content has.
        // Prepare current parameters
        $params = json_decode($hvp->params);
        // Move any uploaded images or files. Determine content dependencies.
        $editor->processParameters($hvp->id, $hvp->library, $params, isset($oldlib) ? $oldlib : NULL, isset($oldparams) ? $oldparams : NULL);
    }
    return $hvp->id;
}
Пример #17
0
$settings = array();
$i = 0;
foreach ($libraries as $versions) {
    foreach ($versions as $library) {
        $usage = $core->h5pF->getLibraryUsage($library->id, $numNotFiltered ? true : false);
        if ($library->runnable) {
            $upgrades = $core->getUpgrades($library, $versions);
            $upgradeUrl = empty($upgrades) ? false : (new moodle_url('/mod/hvp/upgrade_content_page.php', array('library_id' => $library->id)))->out(false);
            $restricted = isset($library->restricted) && $library->restricted == 1 ? true : false;
            $restricted_url = (new moodle_url('/mod/hvp/ajax.php', array('action' => 'restrict_library', 'token' => \H5PCore::createToken('library_' . $library->id), 'restrict' => $restricted ? 0 : 1, 'library_id' => $library->id)))->out(false);
        } else {
            $upgradeUrl = null;
            $restricted = null;
            $restricted_url = null;
        }
        $settings['libraryList']['listData'][] = array('title' => $library->title . ' (' . \H5PCore::libraryVersion($library) . ')', 'restricted' => $restricted, 'restrictedUrl' => $restricted_url, 'numContent' => $core->h5pF->getNumContent($library->id), 'numContentDependencies' => $usage['content'] === -1 ? '' : $usage['content'], 'numLibraryDependencies' => $usage['libraries'], 'upgradeUrl' => $upgradeUrl, 'detailsUrl' => null, 'deleteUrl' => null);
        $i++;
    }
}
// All translations are made server side
$settings['libraryList']['listHeaders'] = array(get_string('librarylisttitle', 'hvp'), get_string('librarylistrestricted', 'hvp'), get_string('librarylistinstances', 'hvp'), get_string('librarylistinstancedependencies', 'hvp'), get_string('librarylistlibrarydependencies', 'hvp'), get_string('librarylistactions', 'hvp'));
// Add js
$lib_url = $CFG->httpswwwroot . '/mod/hvp/library/';
hvp_admin_add_generic_css_and_js($PAGE, $lib_url, $settings);
$PAGE->requires->js(new moodle_url($lib_url . 'js/h5p-library-list.js' . hvp_get_cache_buster()), true);
// RENDER PAGE OUTPUT
echo $OUTPUT->header();
// Print any messages
\mod_hvp\framework::printMessages('info', \mod_hvp\framework::messages('info'));
\mod_hvp\framework::printMessages('error', \mod_hvp\framework::messages('error'));
// Page Header
Пример #18
0
 /**
  * Process a single field.
  *
  * @staticvar string $h5peditor_path
  * @param object $field
  * @param mixed $params
  * @param array $files
  * @param array $libraries
  */
 private function processField(&$field, &$params, &$files)
 {
     static $h5peditor_path;
     if (!$h5peditor_path) {
         $h5peditor_path = $this->editorFilesDir . DIRECTORY_SEPARATOR;
     }
     switch ($field->type) {
         case 'file':
         case 'image':
             if (isset($params->path)) {
                 $oldPath = $h5peditor_path . $params->path;
                 $newPath = $this->content_directory . $params->path;
                 if (file_exists($oldPath)) {
                     rename($oldPath, $newPath);
                     $this->storage->keepFile($oldPath, $newPath);
                 } elseif (file_exists($newPath)) {
                     $this->storage->keepFile($newPath, $newPath);
                 }
                 $files[] = $params->path;
             }
             break;
         case 'video':
         case 'audio':
             if (is_array($params)) {
                 for ($i = 0, $s = count($params); $i < $s; $i++) {
                     $oldPath = $h5peditor_path . $params[$i]->path;
                     $newPath = $this->content_directory . $params[$i]->path;
                     if (file_exists($oldPath)) {
                         rename($oldPath, $newPath);
                         $this->storage->keepFile($oldPath, $newPath);
                     } elseif (file_exists($newPath)) {
                         $this->storage->keepFile($newPath, $newPath);
                     }
                     $files[] = $params[$i]->path;
                 }
             }
             break;
         case 'library':
             if (isset($params->library) && isset($params->params)) {
                 $library = H5PCore::libraryFromString($params->library);
                 $semantics = $this->h5p->loadLibrarySemantics($library['machineName'], $library['majorVersion'], $library['minorVersion']);
                 // Process parameters for the library.
                 $this->processSemantics($files, $semantics, $params->params);
             }
             break;
         case 'group':
             if (isset($params)) {
                 if (count($field->fields) == 1) {
                     $params = (object) array($field->fields[0]->name => $params);
                 }
                 $this->processSemantics($files, $field->fields, $params);
             }
             break;
         case 'list':
             if (is_array($params)) {
                 for ($j = 0, $t = count($params); $j < $t; $j++) {
                     $this->processField($field->field, $params[$j], $files);
                 }
             }
             break;
     }
 }
 /**
  * Fetch library folder and save in target directory.
  *
  * @param array $library
  *  Library properties
  * @param string $target
  *  Where the library folder will be saved
  * @param string $developmentPath
  *  Folder that library resides in
  */
 public function exportLibrary($library, $target, $developmentPath = NULL)
 {
     $folder = \H5PCore::libraryToString($library, TRUE);
     $srcPath = $developmentPath === NULL ? "/libraries/{$folder}" : $developmentPath;
     self::copyFileTree("{$this->path}{$srcPath}", "{$target}/{$folder}");
 }
Пример #20
0
 /**
  * Display details for a given content library.
  *
  * @since 1.1.0
  */
 private function display_library_details()
 {
     global $wpdb;
     $library = $this->get_library();
     H5P_Plugin_Admin::print_messages();
     if (!$library) {
         return;
     }
     // Add settings and translations
     $plugin = H5P_Plugin::get_instance();
     $interface = $plugin->get_h5p_instance('interface');
     $settings = array('containerSelector' => '#h5p-admin-container');
     // Build the translations needed
     $settings['libraryInfo']['translations'] = array('noContent' => __('No content is using this library', $this->plugin_slug), 'contentHeader' => __('Content using this library', $this->plugin_slug), 'pageSizeSelectorLabel' => __('Elements per page', $this->plugin_slug), 'filterPlaceholder' => __('Filter content', $this->plugin_slug), 'pageXOfY' => __('Page $x of $y', $this->plugin_slug));
     $notCached = $interface->getNumNotFiltered();
     if ($notCached) {
         $settings['libraryInfo']['notCached'] = $this->get_not_cached_settings($notCached);
     } else {
         // List content which uses this library
         $contents = $wpdb->get_results($wpdb->prepare("SELECT DISTINCT hc.id, hc.title\n            FROM {$wpdb->prefix}h5p_contents_libraries hcl\n            JOIN {$wpdb->prefix}h5p_contents hc ON hcl.content_id = hc.id\n            WHERE hcl.library_id = %d\n            ORDER BY hc.title", $library->id));
         foreach ($contents as $content) {
             $settings['libraryInfo']['content'][] = array('title' => $content->title, 'url' => admin_url('admin.php?page=h5p&task=show&id=' . $content->id));
         }
     }
     // Build library info
     $settings['libraryInfo']['info'] = array(__('Version', $this->plugin_slug) => H5PCore::libraryVersion($library), __('Fullscreen', $this->plugin_slug) => $library->fullscreen ? __('Yes', $this->plugin_slug) : __('No', $this->plugin_slug), __('Content library', $this->plugin_slug) => $library->runnable ? __('Yes', $this->plugin_slug) : __('No', $this->plugin_slug), __('Used by', $this->plugin_slug) => isset($contents) ? sprintf(_n('1 content', '%d contents', count($contents), $this->plugin_slug), count($contents)) : __('N/A', $this->plugin_slug));
     $this->add_admin_assets();
     H5P_Plugin_Admin::add_script('library-list', 'h5p-php-library/js/h5p-library-details.js');
     include_once 'views/library-details.php';
     $plugin->print_settings($settings, 'H5PAdminIntegration');
 }
Пример #21
0
 /**
  * Extract disabled content features from input post.
  *
  * @since 1.2.0
  * @param H5PCore $core
  * @param int $current
  * @return int
  */
 private function get_disabled_content_features($core, &$content)
 {
     $set = array('frame' => filter_input(INPUT_POST, 'frame', FILTER_VALIDATE_BOOLEAN), 'download' => filter_input(INPUT_POST, 'download', FILTER_VALIDATE_BOOLEAN), 'embed' => filter_input(INPUT_POST, 'embed', FILTER_VALIDATE_BOOLEAN), 'copyright' => filter_input(INPUT_POST, 'copyright', FILTER_VALIDATE_BOOLEAN));
     $content['disable'] = $core->getDisable($set, $content['disable']);
 }
Пример #22
0
 /**
  * Implements loadContentDependencies
  */
 public function loadContentDependencies($id, $type = null)
 {
     global $DB;
     $query = "SELECT hcl.id AS unidepid\n                       , hl.id\n                       , hl.machine_name\n                       , hl.major_version\n                       , hl.minor_version\n                       , hl.patch_version\n                       , hl.preloaded_css\n                       , hl.preloaded_js\n                       , hcl.drop_css\n                       , hcl.dependency_type\n                   FROM {hvp_contents_libraries} hcl\n                   JOIN {hvp_libraries} hl ON hcl.library_id = hl.id\n                  WHERE hcl.hvp_id = ?";
     $queryArgs = array($id);
     if ($type !== null) {
         $query .= " AND hcl.dependency_type = ?";
         $queryArgs[] = $type;
     }
     $query .= " ORDER BY hcl.weight";
     $data = $DB->get_records_sql($query, $queryArgs);
     $dependencies = array();
     foreach ($data as $dependency) {
         unset($dependency->unidepid);
         $dependencies[] = \H5PCore::snakeToCamel($dependency);
     }
     return $dependencies;
 }
Пример #23
0
  *  int contextId
  */
 case 'files':
     global $DB;
     // TODO: Check permissions
     if (!\H5PCore::validToken('editorajax', required_param('token', PARAM_RAW))) {
         \H5PCore::ajaxError(get_string('invalidtoken', 'hvp'));
         exit;
     }
     // Get Content ID and Context ID for upload
     $contentid = required_param('contentId', PARAM_INT);
     $contextid = required_param('contextId', PARAM_INT);
     // Create file
     $file = new H5peditorFile(\mod_hvp\framework::instance('interface'));
     if (!$file->isLoaded()) {
         H5PCore::ajaxError(get_string('filenotfound', 'hvp'));
         break;
     }
     // Make sure file is valid
     if ($file->validate()) {
         $core = \mod_hvp\framework::instance('core');
         // Save the valid file
         $file_id = $core->fs->saveFile($file, $contentid, $contextid);
         // Track temporary files for later cleanup
         $DB->insert_record_raw('hvp_tmpfiles', array('id' => $file_id), false, false, true);
     }
     $file->printResult();
     break;
     /*
      * Throw error if AJAX isnt handeled
      */
Пример #24
0
 public function validation($data, $files)
 {
     global $CFG;
     $errors = parent::validation($data, $files);
     if ($data['h5paction'] === 'upload') {
         // Validate uploaded H5P file
         if (empty($data['h5pfile'])) {
             // Field missing
             $errors['h5pfile'] = get_string('required');
         } else {
             $files = $this->get_draft_files('h5pfile');
             if (count($files) < 1) {
                 // No file uploaded
                 $errors['h5pfile'] = get_string('required');
             } else {
                 // Prepare to validate package
                 $file = reset($files);
                 $interface = \mod_hvp\framework::instance('interface');
                 $path = $CFG->tempdir . uniqid('/hvp-');
                 $interface->getUploadedH5pFolderPath($path);
                 $path .= '.h5p';
                 $interface->getUploadedH5pPath($path);
                 $file->copy_content_to($path);
                 $h5pvalidator = \mod_hvp\framework::instance('validator');
                 if (!$h5pvalidator->isValidPackage()) {
                     // Errors while validating the package
                     $infomessages = implode('<br/>', \mod_hvp\framework::messages('info'));
                     $errormessages = implode('<br/>', \mod_hvp\framework::messages('error'));
                     $errors['h5pfile'] = ($errormessages ? $errormessages . '<br/>' : '') . $infomessages;
                 }
             }
         }
     } else {
         // Validate library and params used in editor
         $core = \mod_hvp\framework::instance();
         // Get library array from string
         $library = H5PCore::libraryFromString($data['h5plibrary']);
         if (!$library) {
             $errors['h5peditor'] = get_string('invalidlibrary', 'hvp');
         } else {
             // Check that library exists
             $library['libraryId'] = $core->h5pF->getLibraryId($library['machineName'], $library['majorVersion'], $library['minorVersion']);
             if (!$library['libraryId']) {
                 $errors['h5peditor'] = get_string('nosuchlibrary', 'hvp');
             } else {
                 $data['h5plibrary'] = $library;
                 // Verify that parameters are valid
                 if (empty($data['h5pparams'])) {
                     $errors['h5peditor'] = get_string('noparameters', 'hvp');
                 } else {
                     $params = json_decode($data['h5pparams']);
                     if ($params === NULL) {
                         $errors['h5peditor'] = get_string('invalidparameters', 'hvp');
                     } else {
                         $data['h5pparams'] = $params;
                     }
                 }
             }
         }
     }
     return $errors;
 }
 /**
  * Retrieves ajax parameters for content and update or delete
  * user data depending on params.
  *
  * @throws \coding_exception
  */
 public static function handle_ajax()
 {
     global $DB;
     // Query String Parameters.
     $content_id = required_param('content_id', PARAM_INT);
     $data_id = required_param('data_type', PARAM_RAW);
     $sub_content_id = required_param('sub_content_id', PARAM_INT);
     // Form Data.
     $data = optional_param('data', null, PARAM_RAW);
     $pre_load = optional_param('preload', null, PARAM_INT);
     $invalidate = optional_param('invalidate', null, PARAM_INT);
     if ($content_id === null || $data_id === null || $sub_content_id === null) {
         \H5PCore::ajaxError(get_string('missingparameters', 'hvp'));
         exit;
         // Missing parameters.
     }
     // Saving data
     if ($data !== NULL && $pre_load !== NULL && $invalidate !== NULL) {
         // Validate token
         if (!\H5PCore::validToken('contentuserdata', required_param('token', PARAM_RAW))) {
             \H5PCore::ajaxError(get_string('invalidtoken', 'hvp'));
             exit;
         }
         // Use context id if supplied
         $context_id = optional_param('contextId', null, PARAM_INT);
         if ($context_id) {
             $context = \context::instance_by_id($context_id);
         } else {
             // Otherwise try to find it from content id
             $context = \context_course::instance($DB->get_field('hvp', 'course', array('id' => $content_id)));
         }
         // Check permissions
         if (!has_capability('mod/hvp:savecontentuserdata', $context)) {
             \H5PCore::ajaxError(get_string('nopermissiontosavecontentuserdata', 'hvp'));
             http_response_code(403);
             exit;
         }
         if ($data === '0') {
             // Delete user data.
             self::delete_user_data($content_id, $sub_content_id, $data_id);
         } else {
             // Save user data.
             self::save_user_data($content_id, $sub_content_id, $data_id, $pre_load, $invalidate, $data);
         }
         \H5PCore::ajaxSuccess();
     } else {
         // Fetch user data
         $user_data = self::get_user_data($content_id, $sub_content_id, $data_id);
         if ($user_data === false) {
             // Did not find data, return nothing
             \H5PCore::ajaxSuccess();
         } else {
             // Found data, return encoded data
             \H5PCore::ajaxSuccess($user_data->data);
         }
     }
     exit;
 }