From c50a814c2a9dc563954769d74287707b7fd446a0 Mon Sep 17 00:00:00 2001 From: Bernhard Kaindl Date: Wed, 20 Sep 2023 12:00:00 +0200 Subject: [PATCH] Save the HTTP referer and WordPress post_id in a new context table and display the stored HTTP referer and the WordPress post_id data. --- class-database.php | 71 ++++++++++++++++++++++++++++++++++++++++++++-- h5pxapikachu.php | 32 ++++++++++++++++++++- 2 files changed, 100 insertions(+), 3 deletions(-) diff --git a/class-database.php b/class-database.php index ced8391..881cffb 100644 --- a/class-database.php +++ b/class-database.php @@ -14,6 +14,7 @@ class Database { private static $table_verb; private static $table_object; private static $table_result; + private static $table_context; private static $table_h5p_content_types; private static $table_h5p_libraries; @@ -37,6 +38,7 @@ public static function build_tables() { id_verb MEDIUMINT(9), id_object MEDIUMINT(9), id_result MEDIUMINT(9), + id_context MEDIUMINT(9), time datetime DEFAULT '0000-00-00 00:00:00' NOT NULL, xapi TEXT, PRIMARY KEY (id) @@ -91,6 +93,15 @@ public static function build_tables() { $ok = dbDelta( $sql ); + $sql = 'CREATE TABLE ' . self::$table_context . " ( + id mediumint(9) NOT NULL AUTO_INCREMENT, + http_referer TEXT, + wp_post_id INT, + PRIMARY KEY (id) + ) $charset_collate;"; + + $ok = dbDelta( $sql ); + $filled = $wpdb->get_var( 'SELECT id FROM ' . self::$table_result . ' WHERE id = 1' ); @@ -122,6 +133,7 @@ public static function delete_tables() { $wpdb->query( 'DROP TABLE IF EXISTS ' . self::$table_verb ); $wpdb->query( 'DROP TABLE IF EXISTS ' . self::$table_object ); $wpdb->query( 'DROP TABLE IF EXISTS ' . self::$table_result ); + $wpdb->query( 'DROP TABLE IF EXISTS ' . self::$table_context ); } /** @@ -154,6 +166,11 @@ public static function delete_data() { $error_count++; } + $ok = $wpdb->query( 'TRUNCATE TABLE ' . self::$table_context ); + if ( false === $ok ) { + $error_count++; + } + $ok = $wpdb->insert( self::$table_result, array( @@ -210,6 +227,8 @@ public static function get_column_titles() { 'result_completion', 'result_success', 'result_duration', + 'http_referer', + 'wp_post_id', 'time', 'xapi', 'wp_user_id', @@ -307,6 +326,7 @@ public static function get_user_table( $wpid, $page, $page_size ) { ver.verb_id, ver.verb_display, obj.xobject_id, obj.object_name, obj.object_description, obj.object_choices, obj.object_correct_responses_pattern, res.result_response, res.result_score_raw, res.result_score_scaled, res.result_completion, res.result_success, res.result_duration, + context.http_referer, context.wp_post_id, mst.time, mst.xapi, act.wp_user_id, obj.h5p_content_id, obj.h5p_subcontent_id FROM @@ -315,11 +335,13 @@ public static function get_user_table( $wpid, $page, $page_size ) { ' . self::$table_verb . ' as ver, ' . self::$table_object . ' as obj, ' . self::$table_result . ' as res + ' . self::$table_context . ' as context, WHERE mst.id_actor = act.id AND mst.id_verb = ver.id AND mst.id_object = obj.id AND mst.id_result = res.id AND + mst.id_context = context.id AND act.wp_user_id = %d LIMIT %d, %d ', @@ -348,6 +370,7 @@ public static function get_complete_table( $wp_user_id = 0 ) { ver.verb_id, ver.verb_display, obj.xobject_id, obj.object_name, obj.object_description, obj.object_choices, obj.object_correct_responses_pattern, res.result_response, res.result_score_raw, res.result_score_scaled, res.result_completion, res.result_success, res.result_duration, + context.http_referer, context.wp_post_id, mst.time, mst.xapi, act.wp_user_id, obj.h5p_content_id, obj.h5p_subcontent_id FROM @@ -356,12 +379,14 @@ public static function get_complete_table( $wp_user_id = 0 ) { ' . self::$table_verb . ' as ver, ' . self::$table_object . ' as obj, ' . self::$table_result . ' as res, + ' . self::$table_context . ' as context, ' . self::$table_h5p_content_types . ' as cnt WHERE mst.id_actor = act.id AND mst.id_verb = ver.id AND mst.id_object = obj.id AND mst.id_result = res.id and + mst.id_context = context.id AND obj.h5p_content_id = cnt.id AND cnt.user_id LIKE %s ORDER BY @@ -421,10 +446,11 @@ public static function get_h5p_content_types() { * @param array $verb Verb data. * @param array $object Object data. * @param array $result Result data. + * @param array $context Context data. * @param string $xapi Original xapi data. * @return true|false False on error within database transactions. */ - public static function insert_data( $actor, $verb, $object, $result, $xapi ) { + public static function insert_data( $actor, $verb, $object, $result, $context, $xapi ) { global $wpdb; $error_count = 0; @@ -451,11 +477,17 @@ public static function insert_data( $actor, $verb, $object, $result, $xapi ) { $error_count++; } + $context_id = self::insert_context( $context ); + if ( false === $context_id ) { + $error_count++; + } + $main_id = self::insert_main( $actor_id, $verb_id, $object_id, $result_id, + $context_id, $xapi ); if ( false === $main_id ) { @@ -477,10 +509,11 @@ public static function insert_data( $actor, $verb, $object, $result, $xapi ) { * @param int $verb_id Verb ID. * @param int $object_id Object ID. * @param int $result_id Result ID. + * @param int $context_id Context ID. * @param string $xapi Original xAPI data. * @param true|null True if ok, null else */ - private static function insert_main( $actor_id, $verb_id, $object_id, $result_id, $xapi ) { + private static function insert_main( $actor_id, $verb_id, $object_id, $result_id, $context_id, $xapi ) { global $wpdb; $ok = $wpdb->insert( @@ -490,6 +523,7 @@ private static function insert_main( $actor_id, $verb_id, $object_id, $result_id 'id_verb' => $verb_id, 'id_object' => $object_id, 'id_result' => $result_id, + 'id_context'=> $context_id, 'time' => current_time( 'mysql' ), 'xapi' => $xapi, ) @@ -665,6 +699,36 @@ private static function insert_result( $result ) { return $result_id; } + /** + * Insert context data into database. + * @param array $context context data. + * @return int Database table index. + */ + private static function insert_context( $context ) { + global $wpdb; + + // Check if entry already exists and return index accordingly. + $context_id = $wpdb->get_var( + $wpdb->prepare( + 'SELECT id FROM ' . self::$table_context . ' WHERE http_referer = %s', + $context['http_referer'] + ) + ); + + if ( is_null( $context_id ) ) { + $ok = $wpdb->insert( + self::$table_context, + array( + 'http_referer' => $context['http_referer'], + 'wp_post_id' => $context['wp_post_id'], + ) + ); + + $context_id = ( 1 === $ok ) ? $wpdb->insert_id : false; + } + return $context_id; + } + /** * Complete missing WordPress User ID for old data. * Just needed for the update from 0.1.3 to 0.2.0 @@ -799,6 +863,8 @@ static function set_column_names() { 'result_completion' => __( 'Result Completion', 'H5PXAPIKATCHU' ), 'result_success' => __( 'Result Success', 'H5PXAPIKATCHU' ), 'result_duration' => __( 'Result Duration', 'H5PXAPIKATCHU' ), + 'http_referer' => __( 'HTTP Referer', 'H5PXAPIKATCHU' ), + 'wp_post_id' => __( 'WP Post ID', 'H5PXAPIKATCHU' ), 'time' => __( 'Time', 'H5PXAPIKATCHU' ), 'xapi' => __( 'xAPI', 'H5PXAPIKATCHU' ), 'wp_user_id' => __( 'WP User ID', 'H5PXAPIKATCHU' ), @@ -837,6 +903,7 @@ static function init() { self::$table_verb = $wpdb->prefix . 'h5pxapikatchu_verb'; self::$table_object = $wpdb->prefix . 'h5pxapikatchu_object'; self::$table_result = $wpdb->prefix . 'h5pxapikatchu_result'; + self::$table_context = $wpdb->prefix . 'h5pxapikatchu_context'; self::$table_h5p_content_types = $wpdb->prefix . 'h5p_contents'; self::$table_h5p_libraries = $wpdb->prefix . 'h5p_libraries'; } diff --git a/h5pxapikachu.php b/h5pxapikachu.php index 4340a02..2a20fc2 100644 --- a/h5pxapikachu.php +++ b/h5pxapikachu.php @@ -264,6 +264,23 @@ function filter_insert_data_verb( $verb ) { return apply_filters( 'h5pxapikatchu_insert_data_verb', $verb ); } +/** + * Filter for context array with XAPI verb, object, result + * and the raw XAPI data string as additional parameters. + * + * @since 0.4.4 + * @param array context array containing e.g. the referrer and the WordPress post_id (if found) + * @param object actor XAPI actor object. + * @param object verb XAPI verb object. + * @param object object XAPI object object. + * @param object result XAPI result object. + * @param string xapi raw XAPI string. + * @return object Filtered context object. + */ +function filter_insert_data_context( $context, $actor, $verb, $object, $result, $xapi ) { + return apply_filters( 'h5pxapikatchu_insert_data_context', $context, $actor, $verb, $object, $result, $xapi ); +} + /** * Filter for xAPI object object. * @@ -337,10 +354,23 @@ function insert_data() { } $xapi = filter_insert_data_xapi( $xapi ); + // Create context array with the referer URL and the WordPress post_id (if found) + $referer = wp_get_referer(); + $context = array( + 'id' => crc32($referer), # For switching to a CRC use CRC64 instead! + 'http_referer' => $referer, + 'wp_post_id' => url_to_postid( $referer ), + ); + // Call a filter for filtering the context with all other XAPI data as additional arguments + $context = filter_insert_data_context( $context, $actor, $verb, $object, $result, $xapi ); + // This filter would likely be obsolete if this works fine: + // Call a hook to provide the complete data record for additional actions: + do_action( 'h5pxapikatchu_data_record_complete', $context, $actor, $verb, $object, $result, $xapi ); + // Add hook 'h5pxapikatchu_insert_data_pre_database' do_action( 'h5pxapikatchu_insert_data_pre_database' ); - $main_id = Database::insert_data( $actor, $verb, $object, $result, $xapi ); + $main_id = Database::insert_data( $actor, $verb, $object, $result, $context, $xapi ); // Add hook 'h5pxapikatchu_insert_data_post_database' do_action( 'h5pxapikatchu_insert_data_post_database', $main_id );