diff --git a/composer.json b/composer.json index 42a578a..478f782 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,8 @@ ], "require": { "guzzlehttp/guzzle": "^7.2 || ^7.8", - "php": "^7.4 || ^8.0" + "php": "^7.4 || ^8.0", + "jenssegers/agent": "^2.6" }, "require-dev": { diff --git a/composer.lock b/composer.lock index 41250c8..6766c45 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "e522db0770fc65691d5296e84a0e311a", + "content-hash": "e35830d1084f69a56ddbbf2a5c70467b", "packages": [ { "name": "guzzlehttp/guzzle", @@ -331,6 +331,203 @@ ], "time": "2023-12-03T20:05:35+00:00" }, + { + "name": "jaybizzle/crawler-detect", + "version": "v1.2.116", + "source": { + "type": "git", + "url": "https://github.com/JayBizzle/Crawler-Detect.git", + "reference": "97e9fe30219e60092e107651abb379a38b342921" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/JayBizzle/Crawler-Detect/zipball/97e9fe30219e60092e107651abb379a38b342921", + "reference": "97e9fe30219e60092e107651abb379a38b342921", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8|^5.5|^6.5|^9.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Jaybizzle\\CrawlerDetect\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mark Beech", + "email": "m@rkbee.ch", + "role": "Developer" + } + ], + "description": "CrawlerDetect is a PHP class for detecting bots/crawlers/spiders via the user agent", + "homepage": "https://github.com/JayBizzle/Crawler-Detect/", + "keywords": [ + "crawler", + "crawler detect", + "crawler detector", + "crawlerdetect", + "php crawler detect" + ], + "support": { + "issues": "https://github.com/JayBizzle/Crawler-Detect/issues", + "source": "https://github.com/JayBizzle/Crawler-Detect/tree/v1.2.116" + }, + "time": "2023-07-21T15:49:49+00:00" + }, + { + "name": "jenssegers/agent", + "version": "v2.6.4", + "source": { + "type": "git", + "url": "https://github.com/jenssegers/agent.git", + "reference": "daa11c43729510b3700bc34d414664966b03bffe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jenssegers/agent/zipball/daa11c43729510b3700bc34d414664966b03bffe", + "reference": "daa11c43729510b3700bc34d414664966b03bffe", + "shasum": "" + }, + "require": { + "jaybizzle/crawler-detect": "^1.2", + "mobiledetect/mobiledetectlib": "^2.7.6", + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5.0|^6.0|^7.0" + }, + "suggest": { + "illuminate/support": "Required for laravel service providers" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + }, + "laravel": { + "providers": [ + "Jenssegers\\Agent\\AgentServiceProvider" + ], + "aliases": { + "Agent": "Jenssegers\\Agent\\Facades\\Agent" + } + } + }, + "autoload": { + "psr-4": { + "Jenssegers\\Agent\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jens Segers", + "homepage": "https://jenssegers.com" + } + ], + "description": "Desktop/mobile user agent parser with support for Laravel, based on Mobiledetect", + "homepage": "https://github.com/jenssegers/agent", + "keywords": [ + "Agent", + "browser", + "desktop", + "laravel", + "mobile", + "platform", + "user agent", + "useragent" + ], + "support": { + "issues": "https://github.com/jenssegers/agent/issues", + "source": "https://github.com/jenssegers/agent/tree/v2.6.4" + }, + "funding": [ + { + "url": "https://github.com/jenssegers", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/jenssegers/agent", + "type": "tidelift" + } + ], + "time": "2020-06-13T08:05:20+00:00" + }, + { + "name": "mobiledetect/mobiledetectlib", + "version": "2.8.45", + "source": { + "type": "git", + "url": "https://github.com/serbanghita/Mobile-Detect.git", + "reference": "96aaebcf4f50d3d2692ab81d2c5132e425bca266" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/serbanghita/Mobile-Detect/zipball/96aaebcf4f50d3d2692ab81d2c5132e425bca266", + "reference": "96aaebcf4f50d3d2692ab81d2c5132e425bca266", + "shasum": "" + }, + "require": { + "php": ">=5.0.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.8.36" + }, + "type": "library", + "autoload": { + "psr-0": { + "Detection": "namespaced/" + }, + "classmap": [ + "Mobile_Detect.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Serban Ghita", + "email": "serbanghita@gmail.com", + "homepage": "http://mobiledetect.net", + "role": "Developer" + } + ], + "description": "Mobile_Detect is a lightweight PHP class for detecting mobile devices. It uses the User-Agent string combined with specific HTTP headers to detect the mobile environment.", + "homepage": "https://github.com/serbanghita/Mobile-Detect", + "keywords": [ + "detect mobile devices", + "mobile", + "mobile detect", + "mobile detector", + "php mobile detect" + ], + "support": { + "issues": "https://github.com/serbanghita/Mobile-Detect/issues", + "source": "https://github.com/serbanghita/Mobile-Detect/tree/2.8.45" + }, + "funding": [ + { + "url": "https://github.com/serbanghita", + "type": "github" + } + ], + "time": "2023-11-07T21:57:25+00:00" + }, { "name": "psr/http-client", "version": "1.0.3", diff --git a/src/Controllers/LamoudNelcXapiController.php b/src/Controllers/LamoudNelcXapiController.php index 992f0cd..917d561 100644 --- a/src/Controllers/LamoudNelcXapiController.php +++ b/src/Controllers/LamoudNelcXapiController.php @@ -23,19 +23,164 @@ public function getIndex(Request $request) public function postIndex(Request $request) { + $request->validate([ + 'xapi_statement' => ['required', 'string', 'in:registered,initialized,watched,completed_lesson,completed_unit,progressed,attempted,completed_course,earned,rated'] + ]); + $xapi = new XapiIntegration(); - $response = $xapi->Registered( - '123456789', // Student National ID - 'betalamoud@gmail.com', // Student Email - '123', // Course Id OR url Or slug - 'New Course', - 'New Course description', - 'MR Hassan', // instructor Name - 'mrhassan@mail.com', // instructor Email - ); - - return redirect()->back()->with('success', $response); + switch ( $request->xapi_statement ) + { + case "registered": + $response = $xapi->Registered( + '123456789', // Student National ID + 'betalamoud@gmail.com', // Student Email + '123', // Course Id OR url Or slug + 'New Course', + 'New Course description', + 'MR Hassan', // instructor Name + 'mrhassan@mail.com', // instructor Email + ); + break; + case "initialized": + $response = $xapi->Initialized( + '123456789', // Student National ID + 'betalamoud@gmail.com', // Student Email + '123', // Course Id OR url Or slug + 'New Course', + 'New Course description', + 'MR Hassan', // instructor Name + 'mrhassan@mail.com', // instructor Email + ); + break; + case "watched": + $response = $xapi->Watched( + '123456789', // Student National ID + 'betalamoud@gmail.com', // Student Email + '/url/to/lesson', + 'Lesson title', + 'Lesson description', + true, // is lesson completed + 'PT15M', // watching duration + '123', + 'New Course', + 'New Course description', + 'MR Hassan', // instructor Name + 'mrhassan@mail.com', // instructor Email + + ); + break; + case "completed_lesson": + $response = $xapi->CompletedLesson( + '123456789', // Student National ID + 'betalamoud@gmail.com', // Student Email + '/url/to/lesson', + 'Lesson title', + 'Lesson description', + '123', + 'New Course', + 'New Course description', + 'MR Hassan', // instructor Name + 'mrhassan@mail.com', // instructor Email + ); + break; + case "completed_unit": + $response = $xapi->CompletedUnit( + '123456789', // Student National ID + 'betalamoud@gmail.com', // Student Email + '/url/to/unit', + 'Unit title', + 'Unit description', + '123', + 'New Course', + 'New Course description', + 'MR Hassan', // instructor Name + 'mrhassan@mail.com', // instructor Email + ); + break; + case "progressed": + $response = $xapi->Progressed( + '123456789', // Student National ID + 'betalamoud@gmail.com', // Student Email + '123', + 'New Course', + 'New Course description', + 'MR Hassan', // instructor Name + 'mrhassan@mail.com', // instructor Email + 0.5, + true + ); + break; + case "attempted": + $response = $xapi->Attempted( + '123456789', // Student National ID + 'betalamoud@gmail.com', // Student Email + '/path/to/quiz', + 'Quiz title', + 'Quiz description', + 1, // attempt Number + '123', + 'New Course', + 'New Course description', + 'MR Hassan', // instructor Name + 'mrhassan@mail.com', // instructor Email + 0.5, // scaled + 30, // raw + 25, // min + 50, // max + true, + true + ); + break; + case "completed_course": + $response = $xapi->CompletedCourse( + '123456789', // Student National ID + 'betalamoud@gmail.com', // Student Email + '123', + 'New Course', + 'New Course description', + 'MR Hassan', // instructor Name + 'mrhassan@mail.com', // instructor Email + ); + break; + case "earned": + $response = $xapi->Earned( + '123456789', // Student National ID + 'betalamoud@gmail.com', // Student Email + 'path/to/cert', + 'cert name', + '123', + 'New Course', + 'New Course description', + ); + break; + case "rated": + $response = $xapi->Rated( + '123456789', // Student National ID + 'betalamoud@gmail.com', // Student Email + '123', + 'New Course', + 'New Course description', + 'MR Hassan', // instructor Name + 'mrhassan@mail.com', // instructor Email + 0.8, + 5, + 'Thank you' + ); + break; + default: + $response = $xapi->Registered( + '123456789', // Student National ID + 'betalamoud@gmail.com', // Student Email + '123', // Course Id OR url Or slug + 'New Course', + 'New Course description', + 'MR Hassan', // instructor Name + 'mrhassan@mail.com', // instructor Email + ); + } + + return redirect()->back()->with(['success'=> $response, 'st'=> $request->xapi_statement]); } } \ No newline at end of file diff --git a/src/Interactions/Attempted.php b/src/Interactions/Attempted.php new file mode 100644 index 0000000..fba7c63 --- /dev/null +++ b/src/Interactions/Attempted.php @@ -0,0 +1,105 @@ +platform_in_arabic = config('platform_in_arabic'); + $this->platform_in_english = config('platform_in_english'); + $this->platform = App::getLocale() === 'ar' ? $this->platform_in_arabic : $this->platform_in_english; + $this->lang = App::getLocale() === 'ar' ? 'ar-SA' : 'en-US'; + + $agent = new Agent(); + $this->browserName = $agent->browser(); + $this->browserVersion = $agent->version($this->browserName); + $this->browserCode = $agent->platform(); + + } + + public function Send( $actor, $actorEmail, $quizUrl, $quizTitle, $quizDesc, $attempNumber, $courseId, $courseTitle, $courseDesc, $instructor, $instructorEmail, $scaled, $raw, $min, $max, bool $completion, bool $success ){ + + $data = array( + 'actor' => array( + 'name' => strval($actor), + 'mbox' => 'mailto:'.strval($actorEmail), + 'objectType' => 'Agent', + ), + 'verb' => array( + 'id' => 'http://adlnet.gov/expapi/verbs/attempted', + 'display' => array("en-US" => "attempted") + ), + 'object' => array( + 'id'=> strval($quizUrl), + 'definition' => array( + 'name' => array( strval($this->lang) => strval($quizTitle) ), + 'description' => array( strval($this->lang) => strval($quizDesc) ), + 'type' => 'http://id.tincanapi.com/activitytype/unit-test' + ), + 'objectType' => 'Activity', + ), + 'context' => array( + 'instructor' => array( + 'name' => strval($instructor), + 'mbox' => 'mailto:'.strval($instructorEmail), + ), + 'platform' => strval($this->platform), + 'language' => strval($this->lang), + 'extensions' => array ( + "http://id.tincanapi.com/extension/attempt-id" => strval($attempNumber), + "http://id.tincanapi.com/extension/browser-info" => array( + "code_name" => strval($this->browserCode), + "name" => strval($this->browserName), + "version" => strval($this->browserVersion) + ), + "https://nelc.gov.sa/extensions/platform" => array( + "name" => array( + "ar-SA" => strval($this->platform_in_arabic), + "en-US" => strval($this->platform_in_english) + ) + ) + ), + 'contextActivities' => array( + 'parent' => array( + array ( + 'id' => strval($courseId), + 'definition' => array( + 'name' => array(strval($this->lang) => strval($courseTitle)), + 'description' => array( strval($this->lang) => strval($courseDesc) ), + 'type' => 'https://w3id.org/xapi/cmi5/activitytype/course' + ), + 'objectType' => "Activity" + ) + ) + ) + ), + 'result' => array( + "score" => array( + "scaled" => $scaled, + "raw" => $raw, + "min" => $min, + "max" => $max + ), + 'completion' => $completion, + "success" => $success, + ), + 'timestamp' => date('Y-m-d\TH:i:s'.substr((string)microtime(), 1, 4).'\Z') + ); + + return $data; + } + +} \ No newline at end of file diff --git a/src/Interactions/Completed.php b/src/Interactions/Completed.php new file mode 100644 index 0000000..3bd4321 --- /dev/null +++ b/src/Interactions/Completed.php @@ -0,0 +1,95 @@ +platform_in_arabic = config('platform_in_arabic'); + $this->platform_in_english = config('platform_in_english'); + $this->platform = App::getLocale() === 'ar' ? $this->platform_in_arabic : $this->platform_in_english; + $this->lang = App::getLocale() === 'ar' ? 'ar-SA' : 'en-US'; + + $agent = new Agent(); + $this->browserName = $agent->browser(); + $this->browserVersion = $agent->version($this->browserName); + $this->browserCode = $agent->platform(); + + } + + public function Send( $actor, $actorEmail, $lessonUrl, $lessonTitle, $lessonDesc, $courseId, $courseTitle, $courseDesc, $instructor, $instructorEmail ){ + + $data = array( + 'actor' => array( + 'name' => strval($actor), + 'mbox' => 'mailto:'.strval($actorEmail), + 'objectType' => 'Agent', + ), + 'verb' => array( + 'id' => 'http://adlnet.gov/expapi/verbs/completed', + 'display' => array("en-US" => "completed") + ), + 'object' => array( + 'id'=> strval($lessonUrl), + 'definition' => array( + 'name' => array(strval($this->lang) => strval($lessonTitle)), + 'description' => array(strval($this->lang) => strval($lessonDesc)), + 'type' => 'http://adlnet.gov/expapi/activities/lesson' + ), + 'objectType' => 'Activity', + ), + 'context' => array( + 'instructor' => array( + 'name' => strval($instructor), + 'mbox' => 'mailto:'.strval($instructorEmail), + ), + 'platform' => strval($this->platform), + 'language' => strval($this->lang), + 'extensions' => array ( + "http://id.tincanapi.com/extension/browser-info" => array( + "code_name" => strval($this->browserCode), + "name" => strval($this->browserName), + "version" => strval($this->browserVersion) + ), + "https://nelc.gov.sa/extensions/platform" => array( + "name" => array( + "ar-SA" => strval($this->platform_in_arabic), + "en-US" => strval($this->platform_in_english) + ) + ) + ), + 'contextActivities' => array( + 'parent' => array( + array ( + 'id' => strval($courseId), + 'definition' => array( + 'name' => array(strval($this->lang) => strval($courseTitle)), + 'description' => array( strval($this->lang) => strval($courseDesc) ), + 'type' => 'https://w3id.org/xapi/cmi5/activitytype/course' + ), + 'objectType' => "Activity" + ) + ) + ) + ), + + 'timestamp' => date('Y-m-d\TH:i:s'.substr((string)microtime(), 1, 4).'\Z') + ); + + return $data; + } + +} \ No newline at end of file diff --git a/src/Interactions/CompletedCourse.php b/src/Interactions/CompletedCourse.php new file mode 100644 index 0000000..be65992 --- /dev/null +++ b/src/Interactions/CompletedCourse.php @@ -0,0 +1,68 @@ +platform_in_arabic = config('platform_in_arabic'); + $this->platform_in_english = config('platform_in_english'); + $this->platform = App::getLocale() === 'ar' ? $this->platform_in_arabic : $this->platform_in_english; + $this->lang = App::getLocale() === 'ar' ? 'ar-SA' : 'en-US'; + + } + + public function Send( $actor, $actorEmail, $courseId, $courseTitle, $courseDesc, $instructor, $instructorEmail ){ + + $data = array( + 'actor' => array( + 'name' => strval($actor), + 'mbox' => 'mailto:'.strval($actorEmail), + 'objectType' => 'Agent', + ), + 'verb' => array( + 'id' => 'http://adlnet.gov/expapi/verbs/completed', + 'display' => array("en-US" => "completed") + ), + 'object' => array( + 'id'=> strval($courseId), + 'definition' => array( + 'name' => array(strval($this->lang) => strval($courseTitle)), + 'description' => array(strval($this->lang) => strval($courseDesc)), + 'type' => 'https://w3id.org/xapi/cmi5/activitytype/course' + ), + 'objectType' => 'Activity', + ), + 'context' => array( + 'instructor' => array( + 'name' => strval($instructor), + 'mbox' => 'mailto:'.strval($instructorEmail), + ), + 'platform' => strval($this->platform), + 'language' => strval($this->lang), + 'extensions' => array ( + "https://nelc.gov.sa/extensions/platform" => array( + "name" => array( + "ar-SA" => strval($this->platform_in_arabic), + "en-US" => strval($this->platform_in_english) + ) + ) + ) + ), + + 'timestamp' => date('Y-m-d\TH:i:s'.substr((string)microtime(), 1, 4).'\Z') + ); + + return $data; + } + +} \ No newline at end of file diff --git a/src/Interactions/CompletedUnit.php b/src/Interactions/CompletedUnit.php new file mode 100644 index 0000000..bda369f --- /dev/null +++ b/src/Interactions/CompletedUnit.php @@ -0,0 +1,95 @@ +platform_in_arabic = config('platform_in_arabic'); + $this->platform_in_english = config('platform_in_english'); + $this->platform = App::getLocale() === 'ar' ? $this->platform_in_arabic : $this->platform_in_english; + $this->lang = App::getLocale() === 'ar' ? 'ar-SA' : 'en-US'; + + $agent = new Agent(); + $this->browserName = $agent->browser(); + $this->browserVersion = $agent->version($this->browserName); + $this->browserCode = $agent->platform(); + + } + + public function Send( $actor, $actorEmail, $unitUrl, $unitTitle, $unitDesc, $courseId, $courseTitle, $courseDesc, $instructor, $instructorEmail ){ + + $data = array( + 'actor' => array( + 'name' => strval($actor), + 'mbox' => 'mailto:'.strval($actorEmail), + 'objectType' => 'Agent', + ), + 'verb' => array( + 'id' => 'http://adlnet.gov/expapi/verbs/completed', + 'display' => array("en-US" => "completed") + ), + 'object' => array( + 'id'=> strval($unitUrl), + 'definition' => array( + 'name' => array($this->lang => strval($unitTitle)), + 'description' => array($this->lang => strval($unitDesc)), + 'type' => 'http://adlnet.gov/expapi/activities/module' + ), + 'objectType' => 'Activity', + ), + 'context' => array( + 'instructor' => array( + 'name' => strval($instructor), + 'mbox' => 'mailto:'.strval($instructorEmail), + ), + 'platform' => strval($this->platform), + 'language' => strval($this->lang), + 'extensions' => array ( + "http://id.tincanapi.com/extension/browser-info" => array( + "code_name" => strval($this->browserCode), + "name" => strval($this->browserName), + "version" => strval($this->browserVersion) + ), + "https://nelc.gov.sa/extensions/platform" => array( + "name" => array( + "ar-SA" => strval($this->platform_in_arabic), + "en-US" => strval($this->platform_in_english) + ) + ) + ), + 'contextActivities' => array( + 'parent' => array( + array ( + 'id' => strval($courseId), + 'definition' => array( + 'name' => array(strval($this->lang) => strval($courseTitle)), + 'description' => array( strval($this->lang) => strval($courseDesc) ), + 'type' => 'https://w3id.org/xapi/cmi5/activitytype/course' + ), + 'objectType' => "Activity" + ) + ) + ) + ), + + 'timestamp' => date('Y-m-d\TH:i:s'.substr((string)microtime(), 1, 4).'\Z') + ); + + return $data; + } + +} \ No newline at end of file diff --git a/src/Interactions/Earned.php b/src/Interactions/Earned.php new file mode 100644 index 0000000..2866deb --- /dev/null +++ b/src/Interactions/Earned.php @@ -0,0 +1,74 @@ +platform_in_arabic = config('platform_in_arabic'); + $this->platform_in_english = config('platform_in_english'); + $this->platform = App::getLocale() === 'ar' ? $this->platform_in_arabic : $this->platform_in_english; + $this->lang = App::getLocale() === 'ar' ? 'ar-SA' : 'en-US'; + } + + public function Send( $actor, $actorEmail, $certUrl, $certName, $courseId, $courseTitle, $courseDesc ){ + + $data = array( + 'actor' => array( + 'name' => strval($actor), + 'mbox' => 'mailto:'.strval($actorEmail), + 'objectType' => 'Agent', + ), + 'verb' => array( + 'id' => 'http://id.tincanapi.com/verb/earned', + 'display' => array("en-US" => "earned") + ), + 'object' => array( + 'id'=> strval($certUrl), + 'definition' => array( + 'name' => array($this->lang => strval($certName)), + 'type' => 'https://www.opigno.org/en/tincan_registry/activity_type/certificate' + ), + 'objectType' => 'Activity', + ), + 'context' => array( + 'extensions' => array ( + "http://id.tincanapi.com/extension/jws-certificate-location" => strval($certUrl), + "https://nelc.gov.sa/extensions/platform" => array( + "name" => array( + "ar-SA" => strval($this->platform_in_arabic), + "en-US" => strval($this->platform_in_english) + ) + ) + ), + 'platform' => strval($this->platform), + 'language' => strval($this->lang), + 'contextActivities' => array( + 'parent' => array( + array ( + 'id' => strval($courseId), + 'definition' => array( + 'name' => array(strval($this->lang) => strval($courseTitle)), + 'description' => array( strval($this->lang) => strval($courseDesc) ), 'type' => 'https://w3id.org/xapi/cmi5/activitytype/course' + ), + 'objectType' => "Activity" + ) + ) + ) + ), + 'timestamp' => date('Y-m-d\TH:i:s'.substr((string)microtime(), 1, 4).'\Z') + ); + + return $data; + } + +} \ No newline at end of file diff --git a/src/Interactions/Initialized.php b/src/Interactions/Initialized.php new file mode 100644 index 0000000..e28945e --- /dev/null +++ b/src/Interactions/Initialized.php @@ -0,0 +1,67 @@ +platform_in_arabic = config('platform_in_arabic'); + $this->platform_in_english = config('platform_in_english'); + $this->platform = App::getLocale() === 'ar' ? $this->platform_in_arabic : $this->platform_in_english; + $this->lang = App::getLocale() === 'ar' ? 'ar-SA' : 'en-US'; + + } + + public function Send( $actor, $actorEmail, $courseId, $courseTitle, $courseDesc, $instructor, $instructorEmail ){ + + $data = array( + 'actor' => array( + 'name' => strval($actor), + 'mbox' => 'mailto:'.strval($actorEmail), + 'objectType' => 'Agent', + ), + 'verb' => array( + 'id' => 'http://adlnet.gov/expapi/verbs/initialized', + 'display' => array('en-US' => 'initialized') + ), + 'object' => array( + 'id'=> strval($courseId), + 'definition' => array( + 'name' => array(strval($this->lang) => strval($courseTitle)), + 'description' => array(strval($this->lang) => strval($courseDesc)), + 'type' => 'https://w3id.org/xapi/cmi5/activitytype/course' + ), + 'objectType' => 'Activity', + ), + 'context' => array( + 'instructor' => array( + 'name' => strval($instructor), + 'mbox' => 'mailto:'.strval($instructorEmail), + ), + 'platform' => strval($this->platform), + 'language' => strval($this->lang), + "extensions" => array( + "https://nelc.gov.sa/extensions/platform" => array( + "name" => array( + "ar-SA" => strval($this->platform_in_arabic), + "en-US" => strval($this->platform_in_english) + ) + ) + ) + ), + 'timestamp' => date('Y-m-d\TH:i:s'.substr((string)microtime(), 1, 4).'\Z') + ); + + return $data; + } + +} \ No newline at end of file diff --git a/src/Interactions/Progressed.php b/src/Interactions/Progressed.php new file mode 100644 index 0000000..5365414 --- /dev/null +++ b/src/Interactions/Progressed.php @@ -0,0 +1,72 @@ +platform_in_arabic = config('platform_in_arabic'); + $this->platform_in_english = config('platform_in_english'); + $this->platform = App::getLocale() === 'ar' ? $this->platform_in_arabic : $this->platform_in_english; + $this->lang = App::getLocale() === 'ar' ? 'ar-SA' : 'en-US'; + } + + public function Send( $actor, $actorEmail, $courseId, $courseTitle, $courseDesc, $instructor, $instructorEmail, $scaled, bool $completion ){ + + $data = array( + 'actor' => array( + 'name' => strval($actor), + 'mbox' => 'mailto:'.strval($actorEmail), + 'objectType' => 'Agent', + ), + 'verb' => array( + 'id' => 'http://adlnet.gov/expapi/verbs/progressed', + 'display' => array("en-US" => "progressed") + ), + 'object' => array( + 'id'=> strval($courseId), + 'definition' => array( + 'name' => array(strval($this->lang) => strval($courseTitle)), + 'description' => array(strval($this->lang) => strval($courseDesc)), + 'type' => 'https://w3id.org/xapi/cmi5/activitytype/course' + ), + 'objectType' => 'Activity', + ), + 'context' => array( + 'instructor' => array( + 'name' => strval($instructor), + 'mbox' => 'mailto:'.strval($instructorEmail), + ), + 'platform' => strval($this->platform), + 'language' => strval($this->lang), + "extensions" => array( + "https://nelc.gov.sa/extensions/platform" => array( + "name" => array( + "ar-SA" => strval($this->platform_in_arabic), + "en-US" => strval($this->platform_in_english) + ) + ) + ) + ), + 'result' => array( + "score" => array( + "scaled" => $scaled + ), + "completion" => $completion, + ), + 'timestamp' => date('Y-m-d\TH:i:s'.substr((string)microtime(), 1, 4).'\Z') + ); + + return $data; + } + +} \ No newline at end of file diff --git a/src/Interactions/Rated.php b/src/Interactions/Rated.php new file mode 100644 index 0000000..76e29a0 --- /dev/null +++ b/src/Interactions/Rated.php @@ -0,0 +1,75 @@ +platform_in_arabic = config('platform_in_arabic'); + $this->platform_in_english = config('platform_in_english'); + $this->platform = App::getLocale() === 'ar' ? $this->platform_in_arabic : $this->platform_in_english; + $this->lang = App::getLocale() === 'ar' ? 'ar-SA' : 'en-US'; + } + + public function Send( $actor, $actorEmail, $courseId, $courseTitle, $courseDesc, $instructor, $instructorEmail, $scaled, $raw, $comment ){ + + $data = array( + 'actor' => array( + 'name' => strval($actor), + 'mbox' => 'mailto:'.strval($actorEmail), + 'objectType' => 'Agent', + ), + 'verb' => array( + 'id' => 'http://id.tincanapi.com/verb/rated', + 'display' => array('en-US' => 'rated') + ), + 'object' => array( + 'id'=> strval($courseId), + 'definition' => array( + 'name' => array(strval($this->lang) => strval($courseTitle)), + 'description' => array( strval($this->lang) => strval($courseDesc) ), + 'type' => 'https://w3id.org/xapi/cmi5/activitytype/course' + ), + 'objectType' => 'Activity', + ), + 'context' => array( + 'instructor' => array( + 'name' => strval($instructor), + 'mbox' => 'mailto:'.strval($instructorEmail), + ), + 'platform' => strval($this->platform), + 'language' => strval($this->lang), + "extensions" => array( + "https://nelc.gov.sa/extensions/platform" => array( + "name" => array( + "ar-SA" => strval($this->platform_in_arabic), + "en-US" => strval($this->platform_in_english) + ) + ) + ) + ), + "result" => array( + "score" => array( + "scaled" => $scaled, + "raw" => $raw, + "min" => 0, + "max" => 5 + ), + "response" => strval($comment) + ), + 'timestamp' => date('Y-m-d\TH:i:s'.substr((string)microtime(), 1, 4).'\Z') + ); + + return $data; + } + +} \ No newline at end of file diff --git a/src/Interactions/Registered.php b/src/Interactions/Registered.php index f69e6b2..9f6ff45 100644 --- a/src/Interactions/Registered.php +++ b/src/Interactions/Registered.php @@ -18,15 +18,14 @@ public function __construct() $this->platform_in_english = config('platform_in_english'); $this->platform = App::getLocale() === 'ar' ? $this->platform_in_arabic : $this->platform_in_english; $this->lang = App::getLocale() === 'ar' ? 'ar-SA' : 'en-US'; - } public function Send( $actor, $actorEmail, $courseId, $courseTitle, $courseDesc, $instructor, $instructorEmail ){ $data = array( 'actor' => array( - 'name' => $actor, - 'mbox' => 'mailto:'.$actorEmail, + 'name' => strval($actor), + 'mbox' => 'mailto:'.strval($actorEmail), 'objectType' => 'Agent', ), 'verb' => array( @@ -34,26 +33,26 @@ public function Send( $actor, $actorEmail, $courseId, $courseTitle, $courseDesc, 'display' => array('en-US' => 'registered') ), 'object' => array( - 'id'=> $courseId, + 'id'=> strval($courseId), 'definition' => array( - 'name' => array($this->lang => $courseTitle), - 'description' => array($this->lang => $courseDesc), + 'name' => array(strval($this->lang) => strval($courseTitle)), + 'description' => array(strval($this->lang) => strval($courseDesc)), 'type' => 'https://w3id.org/xapi/cmi5/activitytype/course' ), 'objectType' => 'Activity', ), 'context' => array( 'instructor' => array( - 'name' => $instructor, - 'mbox' => 'mailto:'.$instructorEmail, + 'name' => strval($instructor), + 'mbox' => 'mailto:'.strval($instructorEmail), ), - 'platform' => $this->platform, - 'language' => $this->lang, + 'platform' => strval($this->platform), + 'language' => strval($this->lang), "extensions" => array( "https://nelc.gov.sa/extensions/platform" => array( "name" => array( - "ar-SA" => $this->platform_in_arabic, - "en-US" => $this->platform_in_english + "ar-SA" => strval($this->platform_in_arabic), + "en-US" => strval($this->platform_in_english) ) ) ) diff --git a/src/Interactions/Watched.php b/src/Interactions/Watched.php new file mode 100644 index 0000000..5abf90b --- /dev/null +++ b/src/Interactions/Watched.php @@ -0,0 +1,92 @@ +platform_in_arabic = config('platform_in_arabic'); + $this->platform_in_english = config('platform_in_english'); + $this->platform = App::getLocale() === 'ar' ? $this->platform_in_arabic : $this->platform_in_english; + $this->lang = App::getLocale() === 'ar' ? 'ar-SA' : 'en-US'; + + $agent = new Agent(); + $this->browserName = $agent->browser(); + $this->browserVersion = $agent->version($this->browserName); + $this->browserCode = $agent->platform(); + + } + + public function Send( $actor, $actorEmail, $lessonUrl, $lessonTitle, $lessonDesc, bool $completion, $duration, $courseId, $courseTitle, $courseDesc, $instructor, $instructorEmail ){ + + $data = array( + 'actor' => array( + 'name' => strval($actor), + 'mbox' => 'mailto:'.strval($actorEmail), + 'objectType' => 'Agent', + ), + 'verb' => array( + 'id' => 'http://activitystrea.ms/watch', + 'display' => array("en-US" => "watched") + ), + 'object' => array( + 'id'=> strval($lessonUrl), + 'definition' => array( + 'name' => array(strval($this->lang) => strval($lessonTitle)), + 'description' => array(strval($this->lang) => strval($lessonDesc)), + 'type' => 'http://adlnet.gov/expapi/activities/lesson' + ), + 'objectType' => 'Activity', + ), + 'context' => array( + 'instructor' => array( + 'name' => strval($instructor), + 'mbox' => 'mailto:'.strval($instructorEmail), + ), + 'platform' => strval($this->platform), + 'language' => strval($this->lang), + 'extensions' => array ( + "http://id.tincanapi.com/extension/browser-info" => array( + "code_name" => strval($this->browserCode), + "name" => strval($this->browserName), + "version" => strval($this->browserVersion) + ) + ), + 'contextActivities' => array( + 'parent' => array( + array ( + 'id' => strval($courseId), + 'definition' => array( + 'name' => array(strval($this->lang) => strval($courseTitle)), + 'description' => array( strval($this->lang) => strval($courseDesc) ), + 'type' => 'https://w3id.org/xapi/cmi5/activitytype/course' + ), + 'objectType' => "Activity" + ) + ) + ) + ), + 'result' => array( + 'completion' => $completion, + 'duration' => $duration, + ), + 'timestamp' => date('Y-m-d\TH:i:s'.substr((string)microtime(), 1, 4).'\Z') + ); + + return $data; + } + +} \ No newline at end of file diff --git a/src/XapiIntegration.php b/src/XapiIntegration.php index 3951c3e..3f269a1 100644 --- a/src/XapiIntegration.php +++ b/src/XapiIntegration.php @@ -4,7 +4,16 @@ use GuzzleHttp\Client; use GuzzleHttp\Exception\RequestException; +use Lamoud\LaravelNelcXapiIntegration\Interactions\Attempted; +use Lamoud\LaravelNelcXapiIntegration\Interactions\Completed; +use Lamoud\LaravelNelcXapiIntegration\Interactions\CompletedCourse; +use Lamoud\LaravelNelcXapiIntegration\Interactions\CompletedUnit; +use Lamoud\LaravelNelcXapiIntegration\Interactions\Earned; +use Lamoud\LaravelNelcXapiIntegration\Interactions\Initialized; +use Lamoud\LaravelNelcXapiIntegration\Interactions\Progressed; +use Lamoud\LaravelNelcXapiIntegration\Interactions\Rated; use Lamoud\LaravelNelcXapiIntegration\Interactions\Registered; +use Lamoud\LaravelNelcXapiIntegration\Interactions\Watched; class XapiIntegration { @@ -39,6 +48,78 @@ public function Registered( $actor, $actorEmail, $courseId, $courseTitle, $cours return $this->sendXAPIRequest( $data ); } + public function Initialized( $actor, $actorEmail, $courseId, $courseTitle, $courseDesc, $instructor, $instructorEmail) + { + $instance = new Initialized(); + $data = $instance->Send( $actor, $actorEmail, $courseId, $courseTitle, $courseDesc, $instructor, $instructorEmail); + + return $this->sendXAPIRequest( $data ); + } + + public function Watched( $actor, $actorEmail, $lessonUrl, $lessonTitle, $lessonDesc, bool $completion, $duration, $courseId, $courseTitle, $courseDesc, $instructor, $instructorEmail ) + { + $instance = new Watched(); + $data = $instance->Send( $actor, $actorEmail, $lessonUrl, $lessonTitle, $lessonDesc, $completion, $duration, $courseId, $courseTitle, $courseDesc, $instructor, $instructorEmail ); + + return $this->sendXAPIRequest( $data ); + } + + public function CompletedLesson( $actor, $actorEmail, $lessonUrl, $lessonTitle, $lessonDesc, $courseId, $courseTitle, $courseDesc, $instructor, $instructorEmail ) + { + $instance = new Completed(); + $data = $instance->Send( $actor, $actorEmail, $lessonUrl, $lessonTitle, $lessonDesc, $courseId, $courseTitle, $courseDesc, $instructor, $instructorEmail ); + + return $this->sendXAPIRequest( $data ); + } + + public function CompletedUnit( $actor, $actorEmail, $unitUrl, $unitTitle, $unitDesc, $courseId, $courseTitle, $courseDesc, $instructor, $instructorEmail ) + { + $instance = new CompletedUnit(); + $data = $instance->Send( $actor, $actorEmail, $unitUrl, $unitTitle, $unitDesc, $courseId, $courseTitle, $courseDesc, $instructor, $instructorEmail ); + + return $this->sendXAPIRequest( $data ); + } + + public function CompletedCourse( $actor, $actorEmail, $courseId, $courseTitle, $courseDesc, $instructor, $instructorEmail ) + { + $instance = new CompletedCourse(); + $data = $instance->Send( $actor, $actorEmail, $courseId, $courseTitle, $courseDesc, $instructor, $instructorEmail ); + + return $this->sendXAPIRequest( $data ); + } + + public function Progressed( $actor, $actorEmail, $courseId, $courseTitle, $courseDesc, $instructor, $instructorEmail, $scaled, bool $completion ) + { + $instance = new Progressed(); + $data = $instance->Send( $actor, $actorEmail, $courseId, $courseTitle, $courseDesc, $instructor, $instructorEmail, $scaled, $completion ); + + return $this->sendXAPIRequest( $data ); + } + + public function Attempted( $actor, $actorEmail, $quizUrl, $quizTitle, $quizDesc, $attempNumber, $courseId, $courseTitle, $courseDesc, $instructor, $instructorEmail, $scaled, $raw, $min, $max, bool $completion, bool $success ) + { + $instance = new Attempted(); + $data = $instance->Send( $actor, $actorEmail, $quizUrl, $quizTitle, $quizDesc, $attempNumber, $courseId, $courseTitle, $courseDesc, $instructor, $instructorEmail, $scaled, $raw, $min, $max, $completion, $success ); + + return $this->sendXAPIRequest( $data ); + } + + public function Earned( $actor, $actorEmail, $certUrl, $certName, $courseId, $courseTitle, $courseDesc ) + { + $instance = new Earned(); + $data = $instance->Send( $actor, $actorEmail, $certUrl, $certName, $courseId, $courseTitle, $courseDesc ); + + return $this->sendXAPIRequest( $data ); + } + + public function Rated( $actor, $actorEmail, $courseId, $courseTitle, $courseDesc, $instructor, $instructorEmail, $scaled, $raw, $comment ) + { + $instance = new Rated(); + $data = $instance->Send( $actor, $actorEmail, $courseId, $courseTitle, $courseDesc, $instructor, $instructorEmail, $scaled, $raw, $comment ); + + return $this->sendXAPIRequest( $data ); + } + public function sendXAPIRequest($data = []) { diff --git a/src/views/index.blade.php b/src/views/index.blade.php index 19e3c27..49c6b3b 100644 --- a/src/views/index.blade.php +++ b/src/views/index.blade.php @@ -33,26 +33,31 @@
- +
- - -
- -
- - + +
@if ($message = Session::get('success')) +

{{ Session::get('st') ?? 'Unknown' }}